diff --git a/src/Library/internal-include/CD/cd_internal.hpp b/src/Library/internal-include/CD/cd_internal.hpp index 0911bd2a..3d451007 100644 --- a/src/Library/internal-include/CD/cd_internal.hpp +++ b/src/Library/internal-include/CD/cd_internal.hpp @@ -8,6 +8,21 @@ namespace JabyEngine { namespace CD { namespace internal { + struct File { + uint32_t cur_lba; + uint32_t dst_lba; + + void set_from(const AutoLBAEntry& file_info) { + this->cur_lba = file_info.get_lba(); + this->dst_lba = this->cur_lba + file_info.get_size_in_sectors(); + } + + bool done_processing() { + this->cur_lba++; + return this->cur_lba == this->dst_lba; + } + }; + enum struct State { Ready = 0, Done = 0, @@ -50,12 +65,6 @@ namespace JabyEngine { } }; - namespace IRQ { - void process(uint32_t irq); - void read_sector_to0(uint32_t* dst, size_t bytes); - void resume_at0(const BCDTimeStamp& cd_time); - } - static State read_current_state() { return const_cast(current_state); } @@ -64,6 +73,15 @@ namespace JabyEngine { void end_read_file(); void continue_reading(); + void copy_from_sector(uint32_t* dst, size_t bytes); + template + T copy_from_sector() { + T data; + + copy_from_sector(reinterpret_cast(&data), sizeof(T)); + return data; + } + BCDTimeStamp get_loc(); BCDTimeStamp get_locL(); @@ -71,6 +89,10 @@ namespace JabyEngine { void enable_CDDA(); void enable_CDXA(bool double_speed); + static void set_loc(const BCDTimeStamp& cd_time) { + Command::send_no_wait(CD_IO::Command::SetLoc, cd_time.min, cd_time.sec, cd_time.sector); + } + static void pause() { Command::send(CD_IO::Command::Pause); } diff --git a/src/Library/src/Audio/CDXA.cpp b/src/Library/src/Audio/CDXA.cpp index 6026d1fa..5d81818b 100644 --- a/src/Library/src/Audio/CDXA.cpp +++ b/src/Library/src/Audio/CDXA.cpp @@ -17,13 +17,10 @@ namespace JabyEngine { switch(irq) { case CD_IO::Interrupt::DataReady: { // The IRQ stack is 0x1000 bytes large so this should fit - CD::RawXADataSector xa_file; - - CD_IO::PortIndex0::change_to(); - CD::IRQ::read_sector_to0(reinterpret_cast(&xa_file), sizeof(CD::RawXADataSector)); + const auto xa_file = CD::copy_from_sector(); if(setting.channel == xa_file.sub_header.channel_number) { - CD::IRQ::resume_at0(setting.start_loc); - CD::Command::send(CD_IO::Command::ReadS); + CD::set_loc(setting.start_loc); + CD::Command::send_no_wait(CD_IO::Command::ReadS); } } break; diff --git a/src/Library/src/BootLoader/callbacks_boot.cpp b/src/Library/src/BootLoader/callbacks_boot.cxx similarity index 80% rename from src/Library/src/BootLoader/callbacks_boot.cpp rename to src/Library/src/BootLoader/callbacks_boot.cxx index c14b4bb1..90fa716c 100644 --- a/src/Library/src/BootLoader/callbacks_boot.cpp +++ b/src/Library/src/BootLoader/callbacks_boot.cxx @@ -7,17 +7,18 @@ namespace JabyEngine { namespace InternalCallback = JabyEngine::Callback::internal; void setup() { - SysCall::EnterCriticalSection(); + // We do not use threads anymore but keep the code for it + /*SysCall::EnterCriticalSection(); /*InternalCallback::VSync::thread_handle = SysCall::OpenThread( InternalCallback::VSync::routine, &InternalCallback::VSync::stack[InternalCallback::VSync::StackSize - 1], SysCall::get_gp() ); - Thread::set_user_mode_for(InternalCallback::VSync::thread_handle);*/ + Thread::set_user_mode_for(InternalCallback::VSync::thread_handle); InternalCallback::CD::thread_handle = Thread::create(InternalCallback::CD::routine, InternalCallback::CD::stack); Thread::set_user_mode_for(InternalCallback::CD::thread_handle); - SysCall::ExitCriticalSection(); + SysCall::ExitCriticalSection();*/ } } } diff --git a/src/Library/src/BootLoader/start_boot.cpp b/src/Library/src/BootLoader/start_boot.cpp index bbfcb49e..d2990f37 100644 --- a/src/Library/src/BootLoader/start_boot.cpp +++ b/src/Library/src/BootLoader/start_boot.cpp @@ -76,7 +76,8 @@ namespace JabyEngine { BIOS::identify(); enable_vanilla_bios(); - Callbacks::setup(); + // Not used anymore + //Callbacks::setup(); __debug_boot_color_at(::JabyEngine::GPU::Color24::Grey(), DebugX, DebugY, DebugScale); DMA::setup(); diff --git a/src/Library/src/CD/cd.cpp b/src/Library/src/CD/cd.cpp index 1226ed69..b8347a48 100644 --- a/src/Library/src/CD/cd.cpp +++ b/src/Library/src/CD/cd.cpp @@ -9,51 +9,45 @@ // TODO: Do not spawn a new thread for handling the CD interrupt but use that thread for loading files or something? // TODO: Can you use the GPU IO Port while also using DMA? namespace JabyEngine { - namespace CDDA { - extern CD::internal::BCDTimeStamp playing_track; - } - - namespace CDXA { - CD::internal::State interrupt_handler(uint8_t irq); - } - namespace CD { - extern volatile uint32_t zero; - namespace internal { - struct File { - uint32_t cur_lba; - uint32_t dst_lba; - - void set_from(const AutoLBAEntry& file_info) { - this->cur_lba = file_info.get_lba(); - this->dst_lba = this->cur_lba + file_info.get_size_in_sectors(); - } - - bool done_processing() { - this->cur_lba++; - return this->cur_lba == this->dst_lba; - } - }; + extern SectorBufferAllocator sector_allocator; + extern File cur_file; static constexpr auto AudioSectorMode = CD_IO_Values::Mode::from(CD_IO_Values::Mode::SingleSpeed, CD_IO_Values::Mode::AutoPauseTrack, CD_IO_Values::Mode::CDDA); static constexpr auto DataSectorMode = CD_IO_Values::Mode::from(CD_IO_Values::Mode::DoubleSpeed, CD_IO_Values::Mode::DataSector); static constexpr auto XAAudioSectorMode = CD_IO_Values::Mode::from(CD_IO_Values::Mode::SingleSpeed, CD_IO_Values::Mode::XADPCM, CD_IO_Values::Mode::WholeSector, CD_IO_Values::Mode::UseXAFilter); namespace IRQ { - static SysCall::InterruptVerifierResult verifier(); - static void handler(uint32_t); + SysCall::InterruptVerifierResult verifier(); + void handler(uint32_t); } - - static SectorBufferAllocator sector_allocator; - static File cur_file; + auto irq_callback = SysCall::InterruptCallback::from(IRQ::verifier, IRQ::handler); State current_state = State::Ready; uint8_t irq_bit_pending = CD_IO::Interrupt::None; - auto irq_callback = SysCall::InterruptCallback::from(IRQ::verifier, IRQ::handler); + static void read_sector_dma(uint32_t* dst, size_t bytes) { + static const auto WaitSectorReady = []() { + while(!CD_IO::IndexStatus.read().is_set(CD_IO_Values::IndexStatus::HasDataFifoData)); + }; - static BCDTimeStamp send_read_cmd0(uint32_t lba, CD_IO::Command::Desc cmd) { + static const auto ReadSector = [](uint32_t* dst, size_t bytes) { + DMA_IO::CDROM.set_adr(reinterpret_cast(dst)); + DMA_IO::CDROM.block_ctrl.write(DMA_IO_Values::BCR::SyncMode0::for_cd(bytes >> 2)); + DMA_IO::CDROM.channel_ctrl.write(DMA_IO_Values::CHCHR::StartCDROM()); + + DMA_IO::CDROM.wait(); + CD_IO::PortIndex0::change_to(); + + CD_IO::PortIndex0::Request.write(CD_IO_Values::Request::reset()); + }; + + WaitSectorReady(); + ReadSector(dst, bytes); + } + + static BCDTimeStamp send_read_cmd(uint32_t lba, CD_IO::Command::Desc cmd) { const auto loc = BCDTimeStamp::from(lba); Command::send(CD_IO::Command::SetLoc, loc.min, loc.sec, loc.sector); @@ -61,122 +55,17 @@ namespace JabyEngine { return loc; } - static void send_read_n0(uint32_t lba) { - send_read_cmd0(lba, CD_IO::Command::ReadN); + static void send_read_n(uint32_t lba) { + send_read_cmd(lba, CD_IO::Command::ReadN); current_state = State::Reading; } - namespace IRQ { - static void read_sector_dma0(uint32_t* dst, size_t bytes) { - static const auto WaitSectorReady = []() { - while(!CD_IO::IndexStatus.read().is_set(CD_IO_Values::IndexStatus::HasDataFifoData)); - }; - - static const auto ReadSector = [](uint32_t* dst, size_t bytes) { - DMA_IO::CDROM.set_adr(reinterpret_cast(dst)); - DMA_IO::CDROM.block_ctrl.write(DMA_IO_Values::BCR::SyncMode0::for_cd(bytes >> 2)); - DMA_IO::CDROM.channel_ctrl.write(DMA_IO_Values::CHCHR::StartCDROM()); - - DMA_IO::CDROM.wait(); - CD_IO::PortIndex0::change_to(); - - CD_IO::PortIndex0::Request.write(CD_IO_Values::Request::reset()); - }; - - WaitSectorReady(); - ReadSector(dst, bytes); - } - - void read_sector_to0(uint32_t* dst, size_t bytes) { - // We only support DMA rn - read_sector_dma0(dst, bytes); - - // Do we ever want to support reading via IO Port? - // Doesn't seem to important when we can use DMA - } - - void resume_at0(const BCDTimeStamp& cd_time) { - Command::send(CD_IO::Command::SetLoc, cd_time.min, cd_time.sec, cd_time.sector); - } - - //###################################################################################################################### - - static SysCall::InterruptVerifierResult verifier() { - if(Interrupt::is_irq(Interrupt::CDROM)) { - Interrupt::ack_irq(Interrupt::CDROM); - return SysCall::InterruptVerifierResult::ExecuteHandler; - } - - else { - return SysCall::InterruptVerifierResult::SkipHandler; - } - } - - static void handler(uint32_t x) { - 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); - CD_IO::PortIndex1::change_to(); - CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag); - - irq_bit_pending = bit::clear(irq_bit_pending, cur_irq); - - CD_IO::PortIndex0::change_to(); - if(cur_irq == CD_IO::Interrupt::DataReady) { - CD_IO::PortIndex0::Request.write(CD_IO_Values::Request::want_data()); - } - - // No masking required because we can only write bit 0 - 2 - CD_IO::IndexStatus.write(old_status); - Callback::internal::CD::execute(cur_irq); - } - - void process(uint32_t irq) { - if(current_state != State::XAMode) { - switch(irq) { - case CD_IO::Interrupt::DataReady: { - // Obtain sector content here - auto* sector = sector_allocator.allocate_sector(); - if(sector) { - //Now obtain sector - read_sector_to0(sector->data, CD_IO::DataSector::SizeBytes); - - if(cur_file.done_processing()) { - current_state = State::Done; - Command::send(CD_IO::Command::Pause); - } - } - - else { - current_state = State::BufferFull; - Command::send(CD_IO::Command::Pause); - } - } break; - - case CD_IO::Interrupt::DataEnd: { - resume_at0(CDDA::playing_track); - Command::send(CD_IO::Command::Play); - } break; - - case CD_IO::Interrupt::DiskError: { - current_state = State::Error; - } break; - } - } - - else { - current_state = CDXA::interrupt_handler(irq); - } - } - } - void read_file(AutoLBAEntry file_info, const SectorBufferAllocator& buffer_allocator) { cur_file.set_from(file_info); sector_allocator = buffer_allocator; enable_CD(); - send_read_n0(cur_file.cur_lba); + send_read_n(cur_file.cur_lba); } void end_read_file() { @@ -186,10 +75,14 @@ namespace JabyEngine { void continue_reading() { if(current_state == State::BufferFull) { CD_IO::PortIndex0::change_to(); - send_read_n0(cur_file.cur_lba); + send_read_n(cur_file.cur_lba); } } + void copy_from_sector(uint32_t* dst, size_t bytes) { + read_sector_dma(dst, bytes); + } + BCDTimeStamp get_loc() { Command::send_wait_response(CD_IO::Command::GetLocP); diff --git a/src/Library/src/CD/cd_interrupt_handler.cpp b/src/Library/src/CD/cd_interrupt_handler.cpp new file mode 100644 index 00000000..1aa6b607 --- /dev/null +++ b/src/Library/src/CD/cd_interrupt_handler.cpp @@ -0,0 +1,93 @@ +#include "../../internal-include/CD/cd_internal.hpp" +#include + +namespace JabyEngine { + namespace CDDA { + extern CD::internal::BCDTimeStamp playing_track; + } + + namespace CDXA { + CD::internal::State interrupt_handler(uint8_t irq); + } + + namespace CD { + namespace internal { + SectorBufferAllocator sector_allocator; + File cur_file; + + namespace IRQ { + static void process(uint32_t irq) { + if(current_state != State::XAMode) { + switch(irq) { + case CD_IO::Interrupt::DataReady: { + // Obtain sector content here + auto* sector = sector_allocator.allocate_sector(); + if(sector) { + //Now obtain sector + copy_from_sector(sector->data, CD_IO::DataSector::SizeBytes); + + if(cur_file.done_processing()) { + current_state = State::Done; + Command::send_no_wait(CD_IO::Command::Pause); + } + } + + else { + current_state = State::BufferFull; + Command::send_no_wait(CD_IO::Command::Pause); + } + } break; + + case CD_IO::Interrupt::DataEnd: { + set_loc(CDDA::playing_track); + Command::send_no_wait(CD_IO::Command::Play); + } break; + + case CD_IO::Interrupt::DiskError: { + current_state = State::Error; + } break; + } + } + + else { + current_state = CDXA::interrupt_handler(irq); + } + } + + //###################################################################################################################### + + SysCall::InterruptVerifierResult verifier() { + if(Interrupt::is_irq(Interrupt::CDROM)) { + Interrupt::ack_irq(Interrupt::CDROM); + return SysCall::InterruptVerifierResult::ExecuteHandler; + } + + else { + return SysCall::InterruptVerifierResult::SkipHandler; + } + } + + void handler(uint32_t x) { + 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); + CD_IO::PortIndex1::change_to(); + CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag); + + irq_bit_pending = bit::clear(irq_bit_pending, cur_irq); + + CD_IO::PortIndex0::change_to(); + if(cur_irq == CD_IO::Interrupt::DataReady) { + CD_IO::PortIndex0::Request.write(CD_IO_Values::Request::want_data()); + } + + process(cur_irq); + // No masking required because we can only write bit 0 - 2 + CD_IO::IndexStatus.write(old_status); + return SysCall::ReturnFromException(); + } + } + } + } +} \ No newline at end of file diff --git a/src/Library/src/System/callbacks.cpp b/src/Library/src/System/callbacks.cxx similarity index 100% rename from src/Library/src/System/callbacks.cpp rename to src/Library/src/System/callbacks.cxx