Disable auto crlf
This commit is contained in:
@@ -1,50 +1,50 @@
|
||||
include ../../mkfile/RebuildTarget.mk
|
||||
JABY_ENGINE_DIR = ../../
|
||||
|
||||
ARTIFACT = libJabyEngine_$(TV_FORMAT)
|
||||
BUILD_DIR = bin
|
||||
|
||||
SPLASH_IMAGE = src/BootLoader/splash_image_pal_boot.hpp
|
||||
SPLASH_IMAGE_NTSC = src/BootLoader/splash_image_ntsc_boot.hpp
|
||||
|
||||
CCFLAGS += -Iinclude -I../../include -D__friends=public
|
||||
CCFLAGS += -save-temps=obj
|
||||
|
||||
include ../../mkfile/Wildcard.mk
|
||||
SRCS = $(call rwildcard, src, c cpp s)
|
||||
|
||||
include ../../mkfile/Makefile
|
||||
LIB_DIR = ../../lib/$(CONFIG_NAME)
|
||||
|
||||
MAIN_LIB_OBJS = $(filter-out $(MAIN_BOOT_OBJ) $(OVERLAY_BOOT_OBJ),$(OBJS))
|
||||
|
||||
#$(info $$var is [${MAIN_BOOT_OBJ}])
|
||||
#$(info $$var2 is [${MAIN_LIB_OBJS}])
|
||||
|
||||
#Linking rule
|
||||
$(TARGET).a: $(MAIN_LIB_OBJS) $(SPLASH_IMAGE)
|
||||
@mkdir -p $(dir $@)
|
||||
$(AR) rcs $(TARGET).a $(MAIN_LIB_OBJS)
|
||||
|
||||
#Copy rules
|
||||
$(LIB_DIR)/$(ARTIFACT).a: $(TARGET).a
|
||||
@mkdir -p $(LIB_DIR)
|
||||
cp $(TARGET).a $(LIB_DIR)/$(ARTIFACT).a
|
||||
|
||||
# Improve later
|
||||
# rule to make the boot image
|
||||
$(SPLASH_IMAGE): ressources/Splash.png
|
||||
jaby_engine_fconv --lz4 $< simple-tim full16 | cpp_out --name SplashScreen -o $@
|
||||
|
||||
$(SPLASH_IMAGE_NTSC): ressources/Splash_ntsc.png
|
||||
jaby_engine_fconv --lz4 $< simple-tim full16 | cpp_out --name SplashScreen -o $@
|
||||
|
||||
#Rules section for default compilation and linking
|
||||
all: $(SPLASH_IMAGE) $(SPLASH_IMAGE_NTSC) $(LIB_DIR)/$(ARTIFACT).a
|
||||
|
||||
clean:
|
||||
rm -fr $(SPLASH_IMAGE)
|
||||
rm -fr $(SPLASH_IMAGE_NTSC)
|
||||
rm -fr $(OUTPUT_DIR)
|
||||
rm -fr gcm.cache
|
||||
include ../../mkfile/RebuildTarget.mk
|
||||
JABY_ENGINE_DIR = ../../
|
||||
|
||||
ARTIFACT = libJabyEngine_$(TV_FORMAT)
|
||||
BUILD_DIR = bin
|
||||
|
||||
SPLASH_IMAGE = src/BootLoader/splash_image_pal_boot.hpp
|
||||
SPLASH_IMAGE_NTSC = src/BootLoader/splash_image_ntsc_boot.hpp
|
||||
|
||||
CCFLAGS += -Iinclude -I../../include -D__friends=public
|
||||
CCFLAGS += -save-temps=obj
|
||||
|
||||
include ../../mkfile/Wildcard.mk
|
||||
SRCS = $(call rwildcard, src, c cpp s)
|
||||
|
||||
include ../../mkfile/Makefile
|
||||
LIB_DIR = ../../lib/$(CONFIG_NAME)
|
||||
|
||||
MAIN_LIB_OBJS = $(filter-out $(MAIN_BOOT_OBJ) $(OVERLAY_BOOT_OBJ),$(OBJS))
|
||||
|
||||
#$(info $$var is [${MAIN_BOOT_OBJ}])
|
||||
#$(info $$var2 is [${MAIN_LIB_OBJS}])
|
||||
|
||||
#Linking rule
|
||||
$(TARGET).a: $(MAIN_LIB_OBJS) $(SPLASH_IMAGE)
|
||||
@mkdir -p $(dir $@)
|
||||
$(AR) rcs $(TARGET).a $(MAIN_LIB_OBJS)
|
||||
|
||||
#Copy rules
|
||||
$(LIB_DIR)/$(ARTIFACT).a: $(TARGET).a
|
||||
@mkdir -p $(LIB_DIR)
|
||||
cp $(TARGET).a $(LIB_DIR)/$(ARTIFACT).a
|
||||
|
||||
# Improve later
|
||||
# rule to make the boot image
|
||||
$(SPLASH_IMAGE): ressources/Splash.png
|
||||
jaby_engine_fconv --lz4 $< simple-tim full16 | cpp_out --name SplashScreen -o $@
|
||||
|
||||
$(SPLASH_IMAGE_NTSC): ressources/Splash_ntsc.png
|
||||
jaby_engine_fconv --lz4 $< simple-tim full16 | cpp_out --name SplashScreen -o $@
|
||||
|
||||
#Rules section for default compilation and linking
|
||||
all: $(SPLASH_IMAGE) $(SPLASH_IMAGE_NTSC) $(LIB_DIR)/$(ARTIFACT).a
|
||||
|
||||
clean:
|
||||
rm -fr $(SPLASH_IMAGE)
|
||||
rm -fr $(SPLASH_IMAGE_NTSC)
|
||||
rm -fr $(OUTPUT_DIR)
|
||||
rm -fr gcm.cache
|
||||
rm -fr $(LIB_DIR)/$(ARTIFACT).a
|
@@ -1,53 +1,53 @@
|
||||
#include "../../internal-include/BootLoader/boot_loader.hpp"
|
||||
#include "../../internal-include/CD/cd_internal.hpp"
|
||||
#include <PSX/System/IOPorts/interrupt_io.hpp>
|
||||
#include <PSX/System/IOPorts/memory_io.hpp>
|
||||
#include <PSX/System/syscalls.hpp>
|
||||
|
||||
namespace JabyEngine {
|
||||
namespace CD {
|
||||
namespace internal {
|
||||
extern SysCall::InterrupCallback callback;
|
||||
}
|
||||
}
|
||||
|
||||
namespace boot {
|
||||
namespace CD {
|
||||
using JabyEngine::CD::internal::Command;
|
||||
|
||||
void setup() {
|
||||
static constexpr auto DebugX = 1;
|
||||
static constexpr auto DebugY = 1;
|
||||
static constexpr auto DebugScale = 1.0;
|
||||
|
||||
__debug_boot_color_at(::JabyEngine::GPU::Color24::White(), DebugX, DebugY, DebugScale);
|
||||
SysCall::EnterCriticalSection();
|
||||
Memory_IO::COM_DELAY.write(Memory_IO::COM_DELAY::create());
|
||||
Memory_IO::CD_DELAY.write(Memory_IO::CD_DELAY::create());
|
||||
|
||||
SysCall::SysEnqIntRP(SysCall::Priority::CdromIoIrq, &::JabyEngine::CD::internal::callback);
|
||||
|
||||
CD_IO::PortIndex1::change_to();
|
||||
CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag);
|
||||
|
||||
CD_IO::Interrupt::enable(CD_IO::PortIndex1::InterruptEnable);
|
||||
|
||||
Interrupt::enable_irq(Interrupt::CDROM);
|
||||
Interrupt::ack_irq(Interrupt::CDROM);
|
||||
SysCall::ExitCriticalSection();
|
||||
|
||||
__debug_boot_color_at(::JabyEngine::GPU::Color24::Red(), DebugX, DebugY, DebugScale);
|
||||
CD_IO::PortIndex0::change_to();
|
||||
|
||||
__debug_boot_color_at(::JabyEngine::GPU::Color24::Green(), DebugX, DebugY, DebugScale);
|
||||
Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::GetStat);
|
||||
__debug_boot_color_at(::JabyEngine::GPU::Color24::Blue(), DebugX, DebugY, DebugScale);
|
||||
Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::GetStat);
|
||||
__debug_boot_color_at(::JabyEngine::GPU::Color24::Yellow(), DebugX, DebugY, DebugScale);
|
||||
Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::Init);
|
||||
|
||||
// Demute?
|
||||
}
|
||||
}
|
||||
}
|
||||
#include "../../internal-include/BootLoader/boot_loader.hpp"
|
||||
#include "../../internal-include/CD/cd_internal.hpp"
|
||||
#include <PSX/System/IOPorts/interrupt_io.hpp>
|
||||
#include <PSX/System/IOPorts/memory_io.hpp>
|
||||
#include <PSX/System/syscalls.hpp>
|
||||
|
||||
namespace JabyEngine {
|
||||
namespace CD {
|
||||
namespace internal {
|
||||
extern SysCall::InterrupCallback callback;
|
||||
}
|
||||
}
|
||||
|
||||
namespace boot {
|
||||
namespace CD {
|
||||
using JabyEngine::CD::internal::Command;
|
||||
|
||||
void setup() {
|
||||
static constexpr auto DebugX = 1;
|
||||
static constexpr auto DebugY = 1;
|
||||
static constexpr auto DebugScale = 1.0;
|
||||
|
||||
__debug_boot_color_at(::JabyEngine::GPU::Color24::White(), DebugX, DebugY, DebugScale);
|
||||
SysCall::EnterCriticalSection();
|
||||
Memory_IO::COM_DELAY.write(Memory_IO::COM_DELAY::create());
|
||||
Memory_IO::CD_DELAY.write(Memory_IO::CD_DELAY::create());
|
||||
|
||||
SysCall::SysEnqIntRP(SysCall::Priority::CdromIoIrq, &::JabyEngine::CD::internal::callback);
|
||||
|
||||
CD_IO::PortIndex1::change_to();
|
||||
CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag);
|
||||
|
||||
CD_IO::Interrupt::enable(CD_IO::PortIndex1::InterruptEnable);
|
||||
|
||||
Interrupt::enable_irq(Interrupt::CDROM);
|
||||
Interrupt::ack_irq(Interrupt::CDROM);
|
||||
SysCall::ExitCriticalSection();
|
||||
|
||||
__debug_boot_color_at(::JabyEngine::GPU::Color24::Red(), DebugX, DebugY, DebugScale);
|
||||
CD_IO::PortIndex0::change_to();
|
||||
|
||||
__debug_boot_color_at(::JabyEngine::GPU::Color24::Green(), DebugX, DebugY, DebugScale);
|
||||
Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::GetStat);
|
||||
__debug_boot_color_at(::JabyEngine::GPU::Color24::Blue(), DebugX, DebugY, DebugScale);
|
||||
Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::GetStat);
|
||||
__debug_boot_color_at(::JabyEngine::GPU::Color24::Yellow(), DebugX, DebugY, DebugScale);
|
||||
Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::Init);
|
||||
|
||||
// Demute?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,83 +1,83 @@
|
||||
#include "../../internal-include/GPU/gpu_internal.hpp"
|
||||
#include <PSX/System/IOPorts/interrupt_io.hpp>
|
||||
#include <PSX/Auxiliary/lz4_decompressor.hpp>
|
||||
#include <PSX/File/Processor/file_processor.hpp>
|
||||
#include <PSX/GPU/gpu.hpp>
|
||||
#include <PSX/System/syscalls.hpp>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef JABYENGINE_PAL
|
||||
#include "splash_image_pal_boot.hpp"
|
||||
#else
|
||||
#include "splash_image_ntsc_boot.hpp"
|
||||
#endif //JABYENGINE_PAL
|
||||
|
||||
extern "C" uint32_t __boot_loader_end;
|
||||
|
||||
namespace JabyEngine {
|
||||
namespace GPU {
|
||||
namespace internal {
|
||||
extern SysCall::InterrupCallback callback;
|
||||
}
|
||||
}
|
||||
|
||||
namespace boot {
|
||||
namespace GPU {
|
||||
using namespace JabyEngine::GPU;
|
||||
|
||||
static void configurate_display() {
|
||||
// Ideal I hope that an offset of 0,0 will produce a well enough centered picture for every TV
|
||||
GPU_IO::GP1.write(GPU_IO::Command::DisplayMode(::JabyEngine::GPU::internal::Display::DisplayMode));
|
||||
GPU::Display::set_offset(0, 0);
|
||||
}
|
||||
|
||||
static size_t decompress_logo() {
|
||||
LZ4Decompressor lz4_decomp(reinterpret_cast<uint8_t*>(&__boot_loader_end));
|
||||
|
||||
const auto [progress, bytes_ready] = lz4_decomp.process(ArrayRange(SplashScreen, sizeof(SplashScreen)), true);
|
||||
switch(progress) {
|
||||
case Progress::InProgress:
|
||||
printf("Decompressing still in progress... %llu\n", bytes_ready);
|
||||
break;
|
||||
|
||||
case Progress::Error:
|
||||
printf("Error decompressing!!!\n");
|
||||
break;
|
||||
|
||||
case Progress::Done:
|
||||
printf("Done decompressing: %llu Bytes ready\n", bytes_ready);
|
||||
break;
|
||||
}
|
||||
|
||||
return bytes_ready;
|
||||
}
|
||||
|
||||
void display_logo() {
|
||||
const auto bytes_ready = decompress_logo();
|
||||
|
||||
// Upload SplashScreen picture
|
||||
auto state = FileProcessor::create(&__boot_loader_end, SimpleTIM(32, 0, 0, 0));
|
||||
state.process(bytes_ready);
|
||||
|
||||
// Duplicate DisplayBuffer content
|
||||
::JabyEngine::GPU::internal::copy_vram_to_vram({PositionU16::create(0, Display::Height), SizeU16::create(Display::Width, Display::Height)}, PositionU16::create(0, 0));
|
||||
|
||||
Display::enable();
|
||||
}
|
||||
|
||||
void setup() {
|
||||
GPU_IO::GP1.write(GPU_IO::Command::Reset());
|
||||
configurate_display();
|
||||
::JabyEngine::GPU::internal::Display::exchange_buffer_and_display();
|
||||
|
||||
GPU::internal::wait_ready_for_CMD();
|
||||
GPU::internal::quick_fill_fast(Color24::Black(), {PositionU16::create(0, 0), SizeU16::create(Display::Width, Display::Height)});
|
||||
|
||||
SysCall::EnterCriticalSection();
|
||||
SysCall::SysEnqIntRP(SysCall::Priority::VblankIrq, &::JabyEngine::GPU::internal::callback);
|
||||
Interrupt::enable_irq(Interrupt::VBlank);
|
||||
SysCall::ExitCriticalSection();
|
||||
}
|
||||
}
|
||||
}
|
||||
#include "../../internal-include/GPU/gpu_internal.hpp"
|
||||
#include <PSX/System/IOPorts/interrupt_io.hpp>
|
||||
#include <PSX/Auxiliary/lz4_decompressor.hpp>
|
||||
#include <PSX/File/Processor/file_processor.hpp>
|
||||
#include <PSX/GPU/gpu.hpp>
|
||||
#include <PSX/System/syscalls.hpp>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef JABYENGINE_PAL
|
||||
#include "splash_image_pal_boot.hpp"
|
||||
#else
|
||||
#include "splash_image_ntsc_boot.hpp"
|
||||
#endif //JABYENGINE_PAL
|
||||
|
||||
extern "C" uint32_t __boot_loader_end;
|
||||
|
||||
namespace JabyEngine {
|
||||
namespace GPU {
|
||||
namespace internal {
|
||||
extern SysCall::InterrupCallback callback;
|
||||
}
|
||||
}
|
||||
|
||||
namespace boot {
|
||||
namespace GPU {
|
||||
using namespace JabyEngine::GPU;
|
||||
|
||||
static void configurate_display() {
|
||||
// Ideal I hope that an offset of 0,0 will produce a well enough centered picture for every TV
|
||||
GPU_IO::GP1.write(GPU_IO::Command::DisplayMode(::JabyEngine::GPU::internal::Display::DisplayMode));
|
||||
GPU::Display::set_offset(0, 0);
|
||||
}
|
||||
|
||||
static size_t decompress_logo() {
|
||||
LZ4Decompressor lz4_decomp(reinterpret_cast<uint8_t*>(&__boot_loader_end));
|
||||
|
||||
const auto [progress, bytes_ready] = lz4_decomp.process(ArrayRange(SplashScreen, sizeof(SplashScreen)), true);
|
||||
switch(progress) {
|
||||
case Progress::InProgress:
|
||||
printf("Decompressing still in progress... %llu\n", bytes_ready);
|
||||
break;
|
||||
|
||||
case Progress::Error:
|
||||
printf("Error decompressing!!!\n");
|
||||
break;
|
||||
|
||||
case Progress::Done:
|
||||
printf("Done decompressing: %llu Bytes ready\n", bytes_ready);
|
||||
break;
|
||||
}
|
||||
|
||||
return bytes_ready;
|
||||
}
|
||||
|
||||
void display_logo() {
|
||||
const auto bytes_ready = decompress_logo();
|
||||
|
||||
// Upload SplashScreen picture
|
||||
auto state = FileProcessor::create(&__boot_loader_end, SimpleTIM(32, 0, 0, 0));
|
||||
state.process(bytes_ready);
|
||||
|
||||
// Duplicate DisplayBuffer content
|
||||
::JabyEngine::GPU::internal::copy_vram_to_vram({PositionU16::create(0, Display::Height), SizeU16::create(Display::Width, Display::Height)}, PositionU16::create(0, 0));
|
||||
|
||||
Display::enable();
|
||||
}
|
||||
|
||||
void setup() {
|
||||
GPU_IO::GP1.write(GPU_IO::Command::Reset());
|
||||
configurate_display();
|
||||
::JabyEngine::GPU::internal::Display::exchange_buffer_and_display();
|
||||
|
||||
GPU::internal::wait_ready_for_CMD();
|
||||
GPU::internal::quick_fill_fast(Color24::Black(), {PositionU16::create(0, 0), SizeU16::create(Display::Width, Display::Height)});
|
||||
|
||||
SysCall::EnterCriticalSection();
|
||||
SysCall::SysEnqIntRP(SysCall::Priority::VblankIrq, &::JabyEngine::GPU::internal::callback);
|
||||
Interrupt::enable_irq(Interrupt::VBlank);
|
||||
SysCall::ExitCriticalSection();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,141 +1,141 @@
|
||||
#include "../../internal-include/CD/cd_internal.hpp"
|
||||
#include <PSX/System/IOPorts/dma_io.hpp>
|
||||
#include <PSX/System/IOPorts/interrupt_io.hpp>
|
||||
#include <PSX/System/syscalls.hpp>
|
||||
|
||||
namespace JabyEngine {
|
||||
namespace CD {
|
||||
namespace internal {
|
||||
static constexpr auto DataSectorMode = CD_IO::Mode::from(CD_IO::Mode::DoubleSpeed, CD_IO::Mode::DataSector);
|
||||
|
||||
static SysCall::InterruptVerifierResult interrupt_verifier();
|
||||
static uint32_t interrupt_handler(uint32_t);
|
||||
|
||||
static SectorBufferAllocator sector_allocator;
|
||||
static uint32_t cur_lba;
|
||||
static uint32_t dst_lba;
|
||||
|
||||
CD_IO::Interrupt::Type last_interrupt = CD_IO::Interrupt::Type::None;
|
||||
uint8_t cmd_interrupt_bit = 0;
|
||||
State current_state = State::Free;
|
||||
SysCall::InterrupCallback callback = {
|
||||
.next = nullptr,
|
||||
.handler_function = interrupt_handler,
|
||||
.verifier_function = interrupt_verifier
|
||||
};
|
||||
|
||||
static void pause_cd() {
|
||||
CD_IO::PortIndex0::change_to();
|
||||
Command::send<CD_IO::PortIndex0>(CD_IO::Command::Pause);
|
||||
}
|
||||
|
||||
// Requires Index0
|
||||
static void read_cd(uint32_t lba) {
|
||||
const auto loc = CDTimeStamp::from(lba);
|
||||
|
||||
Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::SetLoc, loc.get_min_cd(), loc.get_sec_cd(), loc.get_sector_cd());
|
||||
Command::send<CD_IO::PortIndex0>(CD_IO::Command::ReadN);
|
||||
current_state = State::Reading;
|
||||
}
|
||||
|
||||
static void read_sector_dma(CD_IO::DataSector& sector) {
|
||||
static const auto WaitSectorReady = []() {
|
||||
while(!CD_IO::IndexStatus.read().is_set(CD_IO::IndexStatus::HasDataFifoData));
|
||||
};
|
||||
|
||||
static const auto ReadSector = [](uint32_t* dst) {
|
||||
DMA_IO::CDROM.set_adr(reinterpret_cast<uintptr_t>(dst));
|
||||
DMA_IO::CDROM.block_ctrl.write(DMA_IO::BCR::SyncMode0::for_cd());
|
||||
DMA_IO::CDROM.channel_ctrl.write(DMA_IO::CHCHR::StartCDROM());
|
||||
|
||||
DMA_IO::CDROM.wait();
|
||||
|
||||
CD_IO::PortIndex0::Request.write(CD_IO::Request::reset());
|
||||
};
|
||||
|
||||
WaitSectorReady();
|
||||
ReadSector(sector.data);
|
||||
}
|
||||
|
||||
static void read_sector_to(CD_IO::DataSector& sector) {
|
||||
CD_IO::PortIndex0::change_to();
|
||||
CD_IO::PortIndex0::Request.write(CD_IO::Request::want_data());
|
||||
|
||||
// We only support DMA rn
|
||||
read_sector_dma(sector);
|
||||
|
||||
// Do we ever want to support reading via IO Port?
|
||||
// Doesn't seem to important when we can use DMA
|
||||
}
|
||||
|
||||
static SysCall::InterruptVerifierResult interrupt_verifier() {
|
||||
if(Interrupt::is_irq(Interrupt::CDROM)) {
|
||||
return SysCall::InterruptVerifierResult::ExecuteHandler;
|
||||
}
|
||||
|
||||
else {
|
||||
return SysCall::InterruptVerifierResult::SkipHandler;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t interrupt_handler(uint32_t) {
|
||||
const auto old_status = CD_IO::IndexStatus.read();
|
||||
|
||||
CD_IO::PortIndex1::change_to();
|
||||
const auto cur_irq = CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlag);
|
||||
last_interrupt = cur_irq;
|
||||
CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag);
|
||||
|
||||
cmd_interrupt_bit = bit::clear(cmd_interrupt_bit, cur_irq);
|
||||
if(cur_irq == CD_IO::Interrupt::DataReady) {
|
||||
// Obtain sector content here
|
||||
auto* sector = sector_allocator.allocate_sector();
|
||||
if(sector) {
|
||||
//Now obtain sector
|
||||
read_sector_to(*sector);
|
||||
|
||||
cur_lba++;
|
||||
if(cur_lba == dst_lba) {
|
||||
current_state = State::Done;
|
||||
pause_cd();
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
current_state = State::BufferFull;
|
||||
pause_cd();
|
||||
}
|
||||
}
|
||||
|
||||
else if(cur_irq == CD_IO::Interrupt::DiskError) {
|
||||
current_state = State::Error;
|
||||
}
|
||||
|
||||
// No masking required because we can only write bit 0 - 2
|
||||
CD_IO::IndexStatus.write(old_status);
|
||||
Interrupt::ack_irq(Interrupt::CDROM);
|
||||
SysCall::ReturnFromException();
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
void read_file(AutoLBAEntry file_info, const SectorBufferAllocator& buffer_allocator) {
|
||||
cur_lba = file_info.get_lba();
|
||||
dst_lba = cur_lba + file_info.get_size_in_sectors();
|
||||
sector_allocator = buffer_allocator;
|
||||
|
||||
Command::wait_completed();
|
||||
CD_IO::PortIndex0::change_to();
|
||||
Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::SetMode, DataSectorMode);
|
||||
|
||||
read_cd(cur_lba);
|
||||
}
|
||||
|
||||
void continue_reading() {
|
||||
if(current_state == State::BufferFull) {
|
||||
Command::wait_completed();
|
||||
read_cd(cur_lba);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#include "../../internal-include/CD/cd_internal.hpp"
|
||||
#include <PSX/System/IOPorts/dma_io.hpp>
|
||||
#include <PSX/System/IOPorts/interrupt_io.hpp>
|
||||
#include <PSX/System/syscalls.hpp>
|
||||
|
||||
namespace JabyEngine {
|
||||
namespace CD {
|
||||
namespace internal {
|
||||
static constexpr auto DataSectorMode = CD_IO::Mode::from(CD_IO::Mode::DoubleSpeed, CD_IO::Mode::DataSector);
|
||||
|
||||
static SysCall::InterruptVerifierResult interrupt_verifier();
|
||||
static uint32_t interrupt_handler(uint32_t);
|
||||
|
||||
static SectorBufferAllocator sector_allocator;
|
||||
static uint32_t cur_lba;
|
||||
static uint32_t dst_lba;
|
||||
|
||||
CD_IO::Interrupt::Type last_interrupt = CD_IO::Interrupt::Type::None;
|
||||
uint8_t cmd_interrupt_bit = 0;
|
||||
State current_state = State::Free;
|
||||
SysCall::InterrupCallback callback = {
|
||||
.next = nullptr,
|
||||
.handler_function = interrupt_handler,
|
||||
.verifier_function = interrupt_verifier
|
||||
};
|
||||
|
||||
static void pause_cd() {
|
||||
CD_IO::PortIndex0::change_to();
|
||||
Command::send<CD_IO::PortIndex0>(CD_IO::Command::Pause);
|
||||
}
|
||||
|
||||
// Requires Index0
|
||||
static void read_cd(uint32_t lba) {
|
||||
const auto loc = CDTimeStamp::from(lba);
|
||||
|
||||
Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::SetLoc, loc.get_min_cd(), loc.get_sec_cd(), loc.get_sector_cd());
|
||||
Command::send<CD_IO::PortIndex0>(CD_IO::Command::ReadN);
|
||||
current_state = State::Reading;
|
||||
}
|
||||
|
||||
static void read_sector_dma(CD_IO::DataSector& sector) {
|
||||
static const auto WaitSectorReady = []() {
|
||||
while(!CD_IO::IndexStatus.read().is_set(CD_IO::IndexStatus::HasDataFifoData));
|
||||
};
|
||||
|
||||
static const auto ReadSector = [](uint32_t* dst) {
|
||||
DMA_IO::CDROM.set_adr(reinterpret_cast<uintptr_t>(dst));
|
||||
DMA_IO::CDROM.block_ctrl.write(DMA_IO::BCR::SyncMode0::for_cd());
|
||||
DMA_IO::CDROM.channel_ctrl.write(DMA_IO::CHCHR::StartCDROM());
|
||||
|
||||
DMA_IO::CDROM.wait();
|
||||
|
||||
CD_IO::PortIndex0::Request.write(CD_IO::Request::reset());
|
||||
};
|
||||
|
||||
WaitSectorReady();
|
||||
ReadSector(sector.data);
|
||||
}
|
||||
|
||||
static void read_sector_to(CD_IO::DataSector& sector) {
|
||||
CD_IO::PortIndex0::change_to();
|
||||
CD_IO::PortIndex0::Request.write(CD_IO::Request::want_data());
|
||||
|
||||
// We only support DMA rn
|
||||
read_sector_dma(sector);
|
||||
|
||||
// Do we ever want to support reading via IO Port?
|
||||
// Doesn't seem to important when we can use DMA
|
||||
}
|
||||
|
||||
static SysCall::InterruptVerifierResult interrupt_verifier() {
|
||||
if(Interrupt::is_irq(Interrupt::CDROM)) {
|
||||
return SysCall::InterruptVerifierResult::ExecuteHandler;
|
||||
}
|
||||
|
||||
else {
|
||||
return SysCall::InterruptVerifierResult::SkipHandler;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t interrupt_handler(uint32_t) {
|
||||
const auto old_status = CD_IO::IndexStatus.read();
|
||||
|
||||
CD_IO::PortIndex1::change_to();
|
||||
const auto cur_irq = CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlag);
|
||||
last_interrupt = cur_irq;
|
||||
CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag);
|
||||
|
||||
cmd_interrupt_bit = bit::clear(cmd_interrupt_bit, cur_irq);
|
||||
if(cur_irq == CD_IO::Interrupt::DataReady) {
|
||||
// Obtain sector content here
|
||||
auto* sector = sector_allocator.allocate_sector();
|
||||
if(sector) {
|
||||
//Now obtain sector
|
||||
read_sector_to(*sector);
|
||||
|
||||
cur_lba++;
|
||||
if(cur_lba == dst_lba) {
|
||||
current_state = State::Done;
|
||||
pause_cd();
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
current_state = State::BufferFull;
|
||||
pause_cd();
|
||||
}
|
||||
}
|
||||
|
||||
else if(cur_irq == CD_IO::Interrupt::DiskError) {
|
||||
current_state = State::Error;
|
||||
}
|
||||
|
||||
// No masking required because we can only write bit 0 - 2
|
||||
CD_IO::IndexStatus.write(old_status);
|
||||
Interrupt::ack_irq(Interrupt::CDROM);
|
||||
SysCall::ReturnFromException();
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
void read_file(AutoLBAEntry file_info, const SectorBufferAllocator& buffer_allocator) {
|
||||
cur_lba = file_info.get_lba();
|
||||
dst_lba = cur_lba + file_info.get_size_in_sectors();
|
||||
sector_allocator = buffer_allocator;
|
||||
|
||||
Command::wait_completed();
|
||||
CD_IO::PortIndex0::change_to();
|
||||
Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::SetMode, DataSectorMode);
|
||||
|
||||
read_cd(cur_lba);
|
||||
}
|
||||
|
||||
void continue_reading() {
|
||||
if(current_state == State::BufferFull) {
|
||||
Command::wait_completed();
|
||||
read_cd(cur_lba);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,25 +1,25 @@
|
||||
#ifndef __JABYENGINE_INTERNAL_SIMPLE_HELPER_HPP__
|
||||
#define __JABYENGINE_INTERNAL_SIMPLE_HELPER_HPP__
|
||||
|
||||
#include <PSX/File/Processor/file_processor.hpp>
|
||||
|
||||
namespace JabyEngine {
|
||||
namespace FileProcessor {
|
||||
namespace Helper {
|
||||
template<typename T>
|
||||
static void simple_read(T& dst, State::Configuration& config) {
|
||||
static constexpr size_t T_SIZE = sizeof(T);
|
||||
|
||||
dst = *reinterpret_cast<const T*>(config.data_adr);
|
||||
config.processed(T_SIZE);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static Progress exchange_and_execute_process_function(State::GenericProcessRoutine<T> process_routine, State::Configuration& config, T& state) {
|
||||
config.process_routine = reinterpret_cast<State::ProcessRoutine>(process_routine);
|
||||
return process_routine(config, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef __JABYENGINE_INTERNAL_SIMPLE_HELPER_HPP__
|
||||
#define __JABYENGINE_INTERNAL_SIMPLE_HELPER_HPP__
|
||||
|
||||
#include <PSX/File/Processor/file_processor.hpp>
|
||||
|
||||
namespace JabyEngine {
|
||||
namespace FileProcessor {
|
||||
namespace Helper {
|
||||
template<typename T>
|
||||
static void simple_read(T& dst, State::Configuration& config) {
|
||||
static constexpr size_t T_SIZE = sizeof(T);
|
||||
|
||||
dst = *reinterpret_cast<const T*>(config.data_adr);
|
||||
config.processed(T_SIZE);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static Progress exchange_and_execute_process_function(State::GenericProcessRoutine<T> process_routine, State::Configuration& config, T& state) {
|
||||
config.process_routine = reinterpret_cast<State::ProcessRoutine>(process_routine);
|
||||
return process_routine(config, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // !__JABYENGINE_INTERNAL_SIMPLE_HELPER_HPP__
|
@@ -1,102 +1,102 @@
|
||||
#include "../../internal-include/GPU/gpu_internal.hpp"
|
||||
#include <PSX/Timer/frame_timer.hpp>
|
||||
#include <PSX/System/IOPorts/interrupt_io.hpp>
|
||||
#include <PSX/System/syscalls.hpp>
|
||||
|
||||
namespace JabyEngine {
|
||||
namespace GPU {
|
||||
uint8_t Display :: current_id = 1; //< Setup will call exchange and set it to 0
|
||||
|
||||
namespace internal {
|
||||
static SysCall::InterruptVerifierResult interrupt_verifier();
|
||||
static uint32_t interrupt_handler(uint32_t);
|
||||
|
||||
static uint8_t vsync_counter = 0;
|
||||
|
||||
SysCall::InterrupCallback callback = {
|
||||
.next = nullptr,
|
||||
.handler_function = interrupt_handler,
|
||||
.verifier_function = interrupt_verifier
|
||||
};
|
||||
|
||||
static SysCall::InterruptVerifierResult interrupt_verifier() {
|
||||
if(Interrupt::is_irq(Interrupt::VBlank)) {
|
||||
return SysCall::InterruptVerifierResult::ExecuteHandler;
|
||||
}
|
||||
|
||||
else {
|
||||
return SysCall::InterruptVerifierResult::SkipHandler;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t interrupt_handler(uint32_t) {
|
||||
vsync_counter++;
|
||||
MasterTime::value++;
|
||||
|
||||
Interrupt::ack_irq(Interrupt::VBlank);
|
||||
SysCall::ReturnFromException();
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
uint32_t Display :: exchange_buffer_and_display() {
|
||||
const uint16_t draw_area_y = (PublicDisplay::Height*PublicDisplay::current_id);
|
||||
|
||||
GPU::internal::set_draw_area(GPU::PositionU16::create(0, draw_area_y));
|
||||
PublicDisplay::current_id ^= 1;
|
||||
GPU_IO::GP1.write(GPU_IO::Command::DisplayArea(GPU::PositionU16::create(0, static_cast<uint16_t>((PublicDisplay::Height*PublicDisplay::current_id)))));
|
||||
return draw_area_y;
|
||||
}
|
||||
|
||||
void wait_vsync(uint8_t syncs) {
|
||||
volatile auto& vsync_count = reinterpret_cast<volatile uint8_t&>(vsync_counter);
|
||||
const uint8_t dst_value = vsync_count + syncs;
|
||||
|
||||
while(vsync_count != dst_value);
|
||||
}
|
||||
|
||||
void render(const uint32_t* data, size_t words) {
|
||||
wait_ready_for_CMD();
|
||||
for(size_t n = 0; n < words; n++) {
|
||||
GPU_IO::GP0.write({data[n]});
|
||||
}
|
||||
}
|
||||
|
||||
void render_dma(const uint32_t* data) {
|
||||
wait_ready_for_CMD();
|
||||
// DPCR already enabled
|
||||
GPU_IO::GP1.write(GPU_IO::Command::DMADirection(GPU_IO::DMADirection::CPU2GPU));
|
||||
DMA_IO::GPU.set_adr(reinterpret_cast<uintptr_t>(data));
|
||||
DMA_IO::GPU.block_ctrl.write(DMA_IO::BCR::SyncMode2::for_gpu_cmd());
|
||||
DMA_IO::GPU.channel_ctrl.write(DMA_IO::CHCHR::StartGPULinked());
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef USE_NO$PSX
|
||||
void Display :: set_offset(uint16_t x, uint16_t y) {
|
||||
x += 78;
|
||||
y += 43;
|
||||
|
||||
GPU_IO::GP1.write(GPU_IO::Command::HorizontalDisplayRange((x << 3), (x + Display::Width) << 3));
|
||||
GPU_IO::GP1.write(GPU_IO::Command::VerticalDisplayRange(y, y + Display::Height));
|
||||
}
|
||||
#else
|
||||
void Display :: set_offset(uint16_t x, uint16_t y) {
|
||||
GPU_IO::GP1.write(GPU_IO::Command::HorizontalDisplayRange(x, (x + Display::Width*8)));
|
||||
GPU_IO::GP1.write(GPU_IO::Command::VerticalDisplayRange(y - (ScanlinesV/2), y + (ScanlinesV/2)));
|
||||
}
|
||||
#endif //USE_NO$PSX
|
||||
|
||||
uint8_t swap_buffers_vsync(uint8_t syncs, bool clear_screen) {
|
||||
// Waits for finish FIFO
|
||||
internal::wait_ready_for_CMD();
|
||||
|
||||
internal::wait_vsync(syncs);
|
||||
const int16_t draw_offset_y = internal::Display::exchange_buffer_and_display();
|
||||
internal::set_draw_offset(GPU::PositionI16::create(0, draw_offset_y));
|
||||
if(clear_screen) {
|
||||
internal::quick_fill_fast(Color24::Black(), AreaU16::create(0, static_cast<uint16_t>(draw_offset_y), Display::Width, Display::Height));
|
||||
}
|
||||
return Display::current_id;
|
||||
}
|
||||
}
|
||||
#include "../../internal-include/GPU/gpu_internal.hpp"
|
||||
#include <PSX/Timer/frame_timer.hpp>
|
||||
#include <PSX/System/IOPorts/interrupt_io.hpp>
|
||||
#include <PSX/System/syscalls.hpp>
|
||||
|
||||
namespace JabyEngine {
|
||||
namespace GPU {
|
||||
uint8_t Display :: current_id = 1; //< Setup will call exchange and set it to 0
|
||||
|
||||
namespace internal {
|
||||
static SysCall::InterruptVerifierResult interrupt_verifier();
|
||||
static uint32_t interrupt_handler(uint32_t);
|
||||
|
||||
static uint8_t vsync_counter = 0;
|
||||
|
||||
SysCall::InterrupCallback callback = {
|
||||
.next = nullptr,
|
||||
.handler_function = interrupt_handler,
|
||||
.verifier_function = interrupt_verifier
|
||||
};
|
||||
|
||||
static SysCall::InterruptVerifierResult interrupt_verifier() {
|
||||
if(Interrupt::is_irq(Interrupt::VBlank)) {
|
||||
return SysCall::InterruptVerifierResult::ExecuteHandler;
|
||||
}
|
||||
|
||||
else {
|
||||
return SysCall::InterruptVerifierResult::SkipHandler;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t interrupt_handler(uint32_t) {
|
||||
vsync_counter++;
|
||||
MasterTime::value++;
|
||||
|
||||
Interrupt::ack_irq(Interrupt::VBlank);
|
||||
SysCall::ReturnFromException();
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
uint32_t Display :: exchange_buffer_and_display() {
|
||||
const uint16_t draw_area_y = (PublicDisplay::Height*PublicDisplay::current_id);
|
||||
|
||||
GPU::internal::set_draw_area(GPU::PositionU16::create(0, draw_area_y));
|
||||
PublicDisplay::current_id ^= 1;
|
||||
GPU_IO::GP1.write(GPU_IO::Command::DisplayArea(GPU::PositionU16::create(0, static_cast<uint16_t>((PublicDisplay::Height*PublicDisplay::current_id)))));
|
||||
return draw_area_y;
|
||||
}
|
||||
|
||||
void wait_vsync(uint8_t syncs) {
|
||||
volatile auto& vsync_count = reinterpret_cast<volatile uint8_t&>(vsync_counter);
|
||||
const uint8_t dst_value = vsync_count + syncs;
|
||||
|
||||
while(vsync_count != dst_value);
|
||||
}
|
||||
|
||||
void render(const uint32_t* data, size_t words) {
|
||||
wait_ready_for_CMD();
|
||||
for(size_t n = 0; n < words; n++) {
|
||||
GPU_IO::GP0.write({data[n]});
|
||||
}
|
||||
}
|
||||
|
||||
void render_dma(const uint32_t* data) {
|
||||
wait_ready_for_CMD();
|
||||
// DPCR already enabled
|
||||
GPU_IO::GP1.write(GPU_IO::Command::DMADirection(GPU_IO::DMADirection::CPU2GPU));
|
||||
DMA_IO::GPU.set_adr(reinterpret_cast<uintptr_t>(data));
|
||||
DMA_IO::GPU.block_ctrl.write(DMA_IO::BCR::SyncMode2::for_gpu_cmd());
|
||||
DMA_IO::GPU.channel_ctrl.write(DMA_IO::CHCHR::StartGPULinked());
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef USE_NO$PSX
|
||||
void Display :: set_offset(uint16_t x, uint16_t y) {
|
||||
x += 78;
|
||||
y += 43;
|
||||
|
||||
GPU_IO::GP1.write(GPU_IO::Command::HorizontalDisplayRange((x << 3), (x + Display::Width) << 3));
|
||||
GPU_IO::GP1.write(GPU_IO::Command::VerticalDisplayRange(y, y + Display::Height));
|
||||
}
|
||||
#else
|
||||
void Display :: set_offset(uint16_t x, uint16_t y) {
|
||||
GPU_IO::GP1.write(GPU_IO::Command::HorizontalDisplayRange(x, (x + Display::Width*8)));
|
||||
GPU_IO::GP1.write(GPU_IO::Command::VerticalDisplayRange(y - (ScanlinesV/2), y + (ScanlinesV/2)));
|
||||
}
|
||||
#endif //USE_NO$PSX
|
||||
|
||||
uint8_t swap_buffers_vsync(uint8_t syncs, bool clear_screen) {
|
||||
// Waits for finish FIFO
|
||||
internal::wait_ready_for_CMD();
|
||||
|
||||
internal::wait_vsync(syncs);
|
||||
const int16_t draw_offset_y = internal::Display::exchange_buffer_and_display();
|
||||
internal::set_draw_offset(GPU::PositionI16::create(0, draw_offset_y));
|
||||
if(clear_screen) {
|
||||
internal::quick_fill_fast(Color24::Black(), AreaU16::create(0, static_cast<uint16_t>(draw_offset_y), Display::Width, Display::Height));
|
||||
}
|
||||
return Display::current_id;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,12 +1,12 @@
|
||||
.set push
|
||||
.set noreorder
|
||||
.section .text, "ax", @progbits
|
||||
.align 2
|
||||
.global _ZN10JabyEngine7SysCall6printfEPKcz
|
||||
.type _ZN10JabyEngine7SysCall6printfEPKcz, @function
|
||||
|
||||
_ZN10JabyEngine7SysCall6printfEPKcz:
|
||||
li $t2, 0xa0
|
||||
jr $t2
|
||||
li $t1, 0x3f
|
||||
.set push
|
||||
.set noreorder
|
||||
.section .text, "ax", @progbits
|
||||
.align 2
|
||||
.global _ZN10JabyEngine7SysCall6printfEPKcz
|
||||
.type _ZN10JabyEngine7SysCall6printfEPKcz, @function
|
||||
|
||||
_ZN10JabyEngine7SysCall6printfEPKcz:
|
||||
li $t2, 0xa0
|
||||
jr $t2
|
||||
li $t1, 0x3f
|
||||
|
Reference in New Issue
Block a user