From 7b5e5df95207164ee54a75c42c1617db44d8308f Mon Sep 17 00:00:00 2001 From: jaby Date: Fri, 7 Jun 2024 07:36:24 +0200 Subject: [PATCH] Founding of the BugFestival --- include/PSX/System/IOPorts/cd_io.hpp | 7 +- include/PSX/System/syscalls.hpp | 6 +- .../internal-include/CD/cd_internal.hpp | 70 ++++++++++++------- src/Library/src/Audio/CDDA.cpp | 18 ++--- src/Library/src/Audio/CDXA.cpp | 15 ++-- src/Library/src/BootLoader/cd_boot.cpp | 2 +- src/Library/src/CD/cd.cpp | 46 ++++++------ .../src/File/Processor/cd_file_processor.cpp | 2 +- src/Library/src/GPU/gpu.cpp | 18 +++-- src/Library/src/Timer/high_res_timer.cpp | 13 ++-- 10 files changed, 108 insertions(+), 89 deletions(-) diff --git a/include/PSX/System/IOPorts/cd_io.hpp b/include/PSX/System/IOPorts/cd_io.hpp index bb98e61e..51ef894d 100644 --- a/include/PSX/System/IOPorts/cd_io.hpp +++ b/include/PSX/System/IOPorts/cd_io.hpp @@ -151,19 +151,20 @@ namespace JabyEngine { Interrupt::Type complete_irq; }; + // TODO: Seems they all need to be ACK? Can we remove this? static constexpr Desc GetStat{0x01, Interrupt::Type::Acknowledge}; static constexpr Desc SetLoc{0x02, Interrupt::Type::Acknowledge}; static constexpr Desc Play{0x03, Interrupt::Type::Acknowledge}; - static constexpr Desc ReadN{0x06, Interrupt::Type::DataReady}; + static constexpr Desc ReadN{0x06, Interrupt::Type::Acknowledge}; static constexpr Desc Pause{0x09, Interrupt::Type::Complete}; - static constexpr Desc Init{0x0A, Interrupt::Type::Complete}; + //static constexpr Desc Init{0x0A, Interrupt::Type::Complete}; static constexpr Desc Demute{0x0C, Interrupt::Type::Acknowledge}; static constexpr Desc Filter{0x0D, Interrupt::Type::Acknowledge}; static constexpr Desc SetMode{0x0E, Interrupt::Type::Acknowledge}; static constexpr Desc GetLocP{0x11, Interrupt::Type::Acknowledge}; static constexpr Desc GetTN{0x13, Interrupt::Type::Acknowledge}; static constexpr Desc GetTD{0x14, Interrupt::Type::Acknowledge}; - static constexpr Desc ReadS{0x1B, Interrupt::Type::DataReady}; + static constexpr Desc ReadS{0x1B, Interrupt::Type::Acknowledge}; }; static constexpr auto IORegister1Adr = 0x1F801801; diff --git a/include/PSX/System/syscalls.hpp b/include/PSX/System/syscalls.hpp index 46fb8436..1c0349a4 100644 --- a/include/PSX/System/syscalls.hpp +++ b/include/PSX/System/syscalls.hpp @@ -117,7 +117,7 @@ namespace JabyEngine { }; typedef InterruptVerifierResult (*InterruptVerifier)(); - typedef uint32_t (*InterruptHandler)(uint32_t); + typedef void (*InterruptHandler)(uint32_t); using ThreadHandle = uint32_t; #pragma pack(push, 1) @@ -127,8 +127,8 @@ namespace JabyEngine { InterruptVerifier verifier_function; uint32_t notUsed; - static constexpr InterruptCallback from_single_function(InterruptVerifier verifier) { - return InterruptCallback{nullptr, nullptr, verifier, 0}; + static constexpr InterruptCallback from(InterruptVerifier verifier, InterruptHandler handler) { + return InterruptCallback{nullptr, handler, verifier, 0}; } }; #pragma pack(pop) diff --git a/src/Library/internal-include/CD/cd_internal.hpp b/src/Library/internal-include/CD/cd_internal.hpp index ac935c55..9dbcb88c 100644 --- a/src/Library/internal-include/CD/cd_internal.hpp +++ b/src/Library/internal-include/CD/cd_internal.hpp @@ -1,5 +1,6 @@ #pragma once #include "cd_types.hpp" +#include namespace JabyEngine { namespace CD { @@ -19,33 +20,52 @@ namespace JabyEngine { extern uint8_t cmd_interrupt_bit; struct Command { - static void wait_completed() { - while(const_cast(cmd_interrupt_bit) > 0); - } + struct Internal { + static void wait_completed(CD_IO::Interrupt::Type irq) { + while(bit::is_set(const_cast(cmd_interrupt_bit), irq)); + } + static void wait_completed_irq(CD_IO::Interrupt::Type irq) { + static const auto get_next_irq = []() -> CD_IO::Interrupt::Type { + CD_IO::Interrupt::Type cur_irq; + + do { + cur_irq = CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlag); + } while(cur_irq == CD_IO::Interrupt::None); + CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag); + cmd_interrupt_bit = bit::clear(cmd_interrupt_bit, cur_irq); + + return cur_irq; + }; + CD_IO::PortIndex1::change_to(); + while(get_next_irq() != irq); + CD_IO::PortIndex0::change_to(); + } + + template + static void send(IOPort& cmd_fifo, IOPort& parameter_fifo, CD_IO::Command::Desc cmd, ARGS...args) { + while(CD_IO::IndexStatus.read().is_set(CD_IO::IndexStatus::IsTransmissionBusy)); + + cmd_interrupt_bit = bit::set(cmd_interrupt_bit, cmd.complete_irq); + ((parameter_fifo.write(CD_IO::ParameterFifo{args})),...); + cmd_fifo.write(CD_IO::CommandFifo {cmd.id}); + } + }; + + // Requires Index 0 template - static void send(IOPort& cmd_fifo, IOPort& parameter_fifo, CD_IO::Command::Desc cmd, ARGS...args) { - while(CD_IO::IndexStatus.read().is_set(CD_IO::IndexStatus::IsTransmissionBusy)); - - cmd_interrupt_bit = bit::set(0, cmd.complete_irq); - ((parameter_fifo.write(CD_IO::ParameterFifo{args})),...); - cmd_fifo.write(CD_IO::CommandFifo {cmd.id}); - } - - template - static void send(CD_IO::Command::Desc cmd, ARGS...args) { - send(T::CommandFifo, T::ParameterFifo, cmd, args...); - } - - template - static void send_wait(IOPort& cmd_fifo, IOPort& parameter_fifo, CD_IO::Command::Desc cmd, ARGS...args) { - send(cmd_fifo, parameter_fifo, cmd, args...); - wait_completed(); - } - - template static void send_wait(CD_IO::Command::Desc cmd, ARGS...args) { - send_wait(T::CommandFifo, T::ParameterFifo, cmd, args...); + SysCall::EnterCriticalSection(); + Internal::send(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, cmd, args...); + SysCall::ExitCriticalSection(); + Internal::wait_completed(cmd.complete_irq); + } + + // Requires Index 0 + template + static void send_wait_irq(CD_IO::Command::Desc cmd, ARGS...args) { + Internal::send(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, cmd, args...); + Internal::wait_completed_irq(cmd.complete_irq); } }; @@ -68,7 +88,7 @@ namespace JabyEngine { static void pause() { CD_IO::PortIndex0::change_to(); - Command::send(CD_IO::Command::Pause); + Command::send_wait(CD_IO::Command::Pause); } } } diff --git a/src/Library/src/Audio/CDDA.cpp b/src/Library/src/Audio/CDDA.cpp index 625968c6..683e2746 100644 --- a/src/Library/src/Audio/CDDA.cpp +++ b/src/Library/src/Audio/CDDA.cpp @@ -9,10 +9,8 @@ namespace JabyEngine { static CD::BCDTimeStamp last_track; TrackList get_tracks() { - CD::Command::wait_completed(); - CD_IO::PortIndex0::change_to(); - CD::Command::send_wait(CD_IO::Command::GetTN); + CD::Command::send_wait(CD_IO::Command::GetTN); const auto stat = CD_IO::PortIndex0::ResponseFifo.read(); const auto first = CD_IO::PortIndex0::ResponseFifo.read().raw; @@ -27,14 +25,13 @@ namespace JabyEngine { } void play(uint8_t track) { - CD::enable_CDDA(); // < Command waits - - CD::Command::send_wait(CD_IO::Command::GetTD, track); + CD::enable_CDDA(); + CD::Command::send_wait(CD_IO::Command::GetTD, track); const auto stats = CD_IO::PortIndex0::ResponseFifo.read().raw; playing_track.min = CD_IO::PortIndex0::ResponseFifo.read().raw; playing_track.sec = CD_IO::PortIndex0::ResponseFifo.read().raw; - CD::Command::send(CD_IO::Command::Play, track); + CD::Command::send_wait(CD_IO::Command::Play, track); } void stop() { @@ -47,10 +44,9 @@ namespace JabyEngine { } void pop_play() { - CD::Command::wait_completed(); - CD::enable_CDDA(); // < Command waits - CD::Command::send_wait(CD_IO::Command::SetLoc, last_track.min, last_track.sec, last_track.sector); - CD::Command::send(CD_IO::Command::Play); + CD::enable_CDDA(); + CD::Command::send_wait(CD_IO::Command::SetLoc, last_track.min, last_track.sec, last_track.sector); + CD::Command::send_wait(CD_IO::Command::Play); } } } \ No newline at end of file diff --git a/src/Library/src/Audio/CDXA.cpp b/src/Library/src/Audio/CDXA.cpp index ba4b4fa5..6beaa02e 100644 --- a/src/Library/src/Audio/CDXA.cpp +++ b/src/Library/src/Audio/CDXA.cpp @@ -23,7 +23,7 @@ namespace JabyEngine { CD::IRQ::read_sector_to0(reinterpret_cast(&xa_file), sizeof(CD::RawXADataSector)); if(setting.channel == xa_file.sub_header.channel_number) { CD::IRQ::resume_at0(setting.start_loc); - CD::Command::send(CD_IO::Command::ReadS); + CD::Command::send_wait_irq(CD_IO::Command::ReadS); } } break; @@ -40,9 +40,8 @@ namespace JabyEngine { CD::current_state = CD::State::XAMode; CD::enable_CDXA(double_speed); //< Activates PortIndex0 set_channel(channel); - CD::Command::wait_completed(); - CD::Command::send_wait(CD_IO::Command::SetLoc, setting.start_loc.min, setting.start_loc.sec, setting.start_loc.sector); - CD::Command::send(CD_IO::Command::ReadS); + CD::Command::send_wait(CD_IO::Command::SetLoc, setting.start_loc.min, setting.start_loc.sec, setting.start_loc.sector); + CD::Command::send_wait(CD_IO::Command::ReadS); } void stop() { @@ -53,7 +52,7 @@ namespace JabyEngine { static constexpr uint8_t File = 1; CD_IO::PortIndex0::change_to(); - CD::Command::send(CD_IO::Command::Filter, File, channel); + CD::Command::send_wait(CD_IO::Command::Filter, File, channel); setting.channel = channel; } @@ -63,14 +62,12 @@ namespace JabyEngine { } void pop_play() { - CD::Command::wait_completed(); CD::current_state = CD::State::XAMode; CD::enable_CDXA(setting.double_speed); //< Activates PortIndex0 set_channel(setting.channel); - CD::Command::wait_completed(); - CD::Command::send_wait(CD_IO::Command::SetLoc, setting.last_loc.min, setting.last_loc.sec, setting.last_loc.sector); - CD::Command::send(CD_IO::Command::ReadS); + CD::Command::send_wait(CD_IO::Command::SetLoc, setting.last_loc.min, setting.last_loc.sec, setting.last_loc.sector); + CD::Command::send_wait(CD_IO::Command::ReadS); } } } \ No newline at end of file diff --git a/src/Library/src/BootLoader/cd_boot.cpp b/src/Library/src/BootLoader/cd_boot.cpp index b8accbd6..77f03922 100644 --- a/src/Library/src/BootLoader/cd_boot.cpp +++ b/src/Library/src/BootLoader/cd_boot.cpp @@ -47,7 +47,7 @@ namespace JabyEngine { __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);*/ - Command::send(CD_IO::Command::Demute); + Command::send_wait(CD_IO::Command::Demute); } } } diff --git a/src/Library/src/CD/cd.cpp b/src/Library/src/CD/cd.cpp index 901d54e0..ecc34faa 100644 --- a/src/Library/src/CD/cd.cpp +++ b/src/Library/src/CD/cd.cpp @@ -32,6 +32,7 @@ namespace JabyEngine { namespace IRQ { static SysCall::InterruptVerifierResult verifier(); + static void handler(uint32_t); } static SectorBufferAllocator sector_allocator; @@ -39,13 +40,13 @@ namespace JabyEngine { uint8_t cmd_interrupt_bit = 0; State current_state = State::Ready; - auto irq_callback = SysCall::InterruptCallback::from_single_function(IRQ::verifier); + auto irq_callback = SysCall::InterruptCallback::from(IRQ::verifier, IRQ::handler); - static BCDTimeStamp send_read_cmd0(uint32_t lba, CD_IO::Command::Desc desc) { + static BCDTimeStamp send_read_cmd0(uint32_t lba, CD_IO::Command::Desc cmd) { const auto loc = BCDTimeStamp::from(lba); - Command::send_wait(CD_IO::Command::SetLoc, loc.min, loc.sec, loc.sector); - Command::send(desc); + Command::send_wait(CD_IO::Command::SetLoc, loc.min, loc.sec, loc.sector); + Command::send_wait(cmd); return loc; } @@ -85,12 +86,7 @@ namespace JabyEngine { } void resume_at0(const BCDTimeStamp& cd_time) { - Command::send(CD_IO::Command::SetLoc, cd_time.min, cd_time.sec, cd_time.sector); - - CD_IO::PortIndex1::change_to(); - while(CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlag) != CD_IO::Interrupt::Acknowledge); - CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag); - CD_IO::PortIndex0::change_to(); + Command::send_wait_irq(CD_IO::Command::SetLoc, cd_time.min, cd_time.sec, cd_time.sector); } //###################################################################################################################### @@ -104,7 +100,9 @@ namespace JabyEngine { CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag); CD_IO::PortIndex0::change_to(); + //printf("Before: %i (IRQ: %i)\n", cmd_interrupt_bit, cur_irq); cmd_interrupt_bit = bit::clear(cmd_interrupt_bit, cur_irq); + //printf("After: %i (IRQ: %i)\n", cmd_interrupt_bit, cur_irq); if(current_state != State::XAMode) { switch(cur_irq) { @@ -117,20 +115,20 @@ namespace JabyEngine { if(cur_file.done_processing()) { current_state = State::Done; - pause(); + Command::send_wait_irq(CD_IO::Command::Pause); } } else { current_state = State::BufferFull; - pause(); + Command::send_wait_irq(CD_IO::Command::Pause); } } break; case CD_IO::Interrupt::DataEnd: { // TODO: Fix this!! This is a freaking static time resume_at0(BCDTimeStamp{.min = 0x0, .sec = 0x09, .sector = 0x0}); - Command::send(CD_IO::Command::Play); + Command::send_wait_irq(CD_IO::Command::Play); } break; case CD_IO::Interrupt::DiskError: { @@ -145,40 +143,40 @@ namespace JabyEngine { // 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(); + return SysCall::InterruptVerifierResult::ExecuteHandler; } else { return SysCall::InterruptVerifierResult::SkipHandler; } } + + static void handler(uint32_t) { + Interrupt::ack_irq(Interrupt::CDROM); + SysCall::ReturnFromException(); + } } void read_file(AutoLBAEntry file_info, const SectorBufferAllocator& buffer_allocator) { cur_file.set_from(file_info); sector_allocator = buffer_allocator; - Command::wait_completed(); CD_IO::PortIndex0::change_to(); - Command::send_wait(CD_IO::Command::SetMode, DataSectorMode); + Command::send_wait(CD_IO::Command::SetMode, DataSectorMode); send_read_n0(cur_file.cur_lba); } void continue_reading() { if(current_state == State::BufferFull) { - Command::wait_completed(); CD_IO::PortIndex0::change_to(); send_read_n0(cur_file.cur_lba); } } BCDTimeStamp get_loc() { - Command::wait_completed(); CD_IO::PortIndex0::change_to(); - Command::send_wait(CD_IO::Command::GetLocP); + Command::send_wait(CD_IO::Command::GetLocP); const auto track = CD_IO::PortIndex0::ResponseFifo.read().raw; // track number (AAh=Lead-out area) (FFh=unknown, toc, none?) const auto index = CD_IO::PortIndex0::ResponseFifo.read().raw; // index number (Usually 01h) @@ -193,9 +191,8 @@ namespace JabyEngine { } void enable_CDDA() { - Command::wait_completed(); CD_IO::PortIndex0::change_to(); - Command::send_wait(CD_IO::Command::SetMode, AudioSectorMode); + Command::send_wait(CD_IO::Command::SetMode, AudioSectorMode); } void enable_CDXA(bool double_speed) { @@ -204,9 +201,8 @@ namespace JabyEngine { const uint8_t mode = XAAudioSectorMode.raw | (double_speed ? DoubleSpeedBit : SingleSpeedBit); - Command::wait_completed(); CD_IO::PortIndex0::change_to(); - Command::send_wait(CD_IO::Command::SetMode, mode); + Command::send_wait(CD_IO::Command::SetMode, mode); } } } diff --git a/src/Library/src/File/Processor/cd_file_processor.cpp b/src/Library/src/File/Processor/cd_file_processor.cpp index 6a8acc2b..0db5e716 100644 --- a/src/Library/src/File/Processor/cd_file_processor.cpp +++ b/src/Library/src/File/Processor/cd_file_processor.cpp @@ -56,7 +56,7 @@ namespace JabyEngine { return self.circular_buffer.allocate(); })); - printf(">>> CD needs to load LBA: %i -> %i (is LZ4: [%s])\n", cur_lba.get_lba(), cur_lba.get_size_in_sectors(), cur_lba.is_lz4() ? "Yes" : "No"); + printf(">>> %i.) CD needs to load LBA: %i -> %i (is LZ4: [%s])\n", cur_job.rel_lba_idx, cur_lba.get_lba(), cur_lba.get_size_in_sectors(), cur_lba.is_lz4() ? "Yes" : "No"); } bool CDFileProcessor :: process_data() { diff --git a/src/Library/src/GPU/gpu.cpp b/src/Library/src/GPU/gpu.cpp index 2b2c634f..83679bf0 100644 --- a/src/Library/src/GPU/gpu.cpp +++ b/src/Library/src/GPU/gpu.cpp @@ -15,19 +15,18 @@ namespace JabyEngine { } static SysCall::InterruptVerifierResult interrupt_verifier(); + static void interrupt_handler(uint32_t); static uint8_t vsync_counter = 0; - auto irq_callback = SysCall::InterruptCallback::from_single_function(interrupt_verifier); + auto irq_callback = SysCall::InterruptCallback::from(interrupt_verifier, interrupt_handler); static SysCall::InterruptVerifierResult interrupt_verifier() { if(Interrupt::is_irq(Interrupt::VBlank)) { vsync_counter++; MasterTime::value++; - Interrupt::ack_irq(Interrupt::VBlank); //Callback::internal::VSync::execute(); - SysCall::ReturnFromException(); - __builtin_unreachable(); + return SysCall::InterruptVerifierResult::ExecuteHandler; } else { @@ -35,6 +34,11 @@ namespace JabyEngine { } } + static void interrupt_handler(uint32_t) { + Interrupt::ack_irq(Interrupt::VBlank); + SysCall::ReturnFromException(); + } + uint32_t Display :: exchange_buffer_and_display() { static constexpr uint16_t TexturePageHeight = 256; @@ -46,10 +50,12 @@ namespace JabyEngine { return draw_area_y; } + uint8_t dst_value = 0; + void wait_vsync(uint8_t syncs) { volatile auto& vsync_count = reinterpret_cast(vsync_counter); - const uint8_t dst_value = vsync_count + syncs; - + + dst_value = vsync_count + syncs; while(vsync_count != dst_value); } diff --git a/src/Library/src/Timer/high_res_timer.cpp b/src/Library/src/Timer/high_res_timer.cpp index bf00ad40..9bfd0f35 100644 --- a/src/Library/src/Timer/high_res_timer.cpp +++ b/src/Library/src/Timer/high_res_timer.cpp @@ -9,16 +9,19 @@ namespace JabyEngine { static SysCall::InterruptVerifierResult interrupt_verifier() { if(Interrupt::is_irq(Interrupt::Timer2)) { HighResTime::global_counter_10ms = HighResTime::global_counter_10ms + 1; - - Interrupt::ack_irq(Interrupt::Timer2); - SysCall::ReturnFromException(); - __builtin_unreachable(); + return SysCall::InterruptVerifierResult::ExecuteHandler; } else { return SysCall::InterruptVerifierResult::SkipHandler; } } - auto irq_callback = SysCall::InterruptCallback::from_single_function(interrupt_verifier); + + static void interrupt_handler(uint32_t) { + Interrupt::ack_irq(Interrupt::Timer2); + SysCall::ReturnFromException(); + } + + auto irq_callback = SysCall::InterruptCallback::from(interrupt_verifier, interrupt_handler); } } \ No newline at end of file