From 0618aa1fb77e891d3632f8bacc20a4826a702a27 Mon Sep 17 00:00:00 2001 From: Jaby Date: Thu, 9 May 2024 14:13:28 +0200 Subject: [PATCH] Support CDDA auto-repeat --- include/PSX/Audio/CDDA.hpp | 2 +- include/PSX/System/IOPorts/cd_io.hpp | 1 + src/Library/src/Audio/CDDA.cpp | 14 +++++--- src/Library/src/CD/cd.cpp | 52 ++++++++++++++++++---------- 4 files changed, 45 insertions(+), 24 deletions(-) diff --git a/include/PSX/Audio/CDDA.hpp b/include/PSX/Audio/CDDA.hpp index bea2d1d6..acb6fc89 100644 --- a/include/PSX/Audio/CDDA.hpp +++ b/include/PSX/Audio/CDDA.hpp @@ -15,7 +15,7 @@ namespace JabyEngine { TrackList get_tracks(); void play(uint8_t track); - void pause(); + void stop(); void push_play(); void pop_play(); diff --git a/include/PSX/System/IOPorts/cd_io.hpp b/include/PSX/System/IOPorts/cd_io.hpp index 8c1038bf..1ea6ecf0 100644 --- a/include/PSX/System/IOPorts/cd_io.hpp +++ b/include/PSX/System/IOPorts/cd_io.hpp @@ -160,6 +160,7 @@ namespace JabyEngine { 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 auto IORegister1Adr = 0x1F801801; diff --git a/src/Library/src/Audio/CDDA.cpp b/src/Library/src/Audio/CDDA.cpp index 527e5ec4..8888ae88 100644 --- a/src/Library/src/Audio/CDDA.cpp +++ b/src/Library/src/Audio/CDDA.cpp @@ -1,11 +1,11 @@ #include "../../internal-include/CD/cd_internal.hpp" #include -#include namespace JabyEngine { namespace CDDA { namespace CD = JabyEngine::CD::internal; + static CD::CDTimeStamp playing_track; static CD::CDTimeStamp last_track; TrackList get_tracks() { @@ -28,16 +28,22 @@ namespace JabyEngine { void play(uint8_t track) { CD::enable_CDDA(); // < Command waits + + 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); } - void pause() { + void stop() { CD::Command::wait_completed(); CD::Command::send(CD_IO::Command::Pause); } void push_play() { - pause(); + stop(); CD::Command::wait_completed(); CD::Command::send_wait(CD_IO::Command::GetLocP); @@ -53,8 +59,8 @@ namespace JabyEngine { void pop_play() { CD::Command::wait_completed(); - CD::Command::send_wait(CD_IO::Command::SetLoc, last_track.min, last_track.sec, last_track.sector); 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); } } diff --git a/src/Library/src/CD/cd.cpp b/src/Library/src/CD/cd.cpp index df38ae1f..6205ca71 100644 --- a/src/Library/src/CD/cd.cpp +++ b/src/Library/src/CD/cd.cpp @@ -6,7 +6,7 @@ namespace JabyEngine { namespace CD { namespace internal { - static constexpr auto AudioSectorMode = CD_IO::Mode::from(CD_IO::Mode::SingleSpeed, CD_IO::Mode::CDDA); + static constexpr auto AudioSectorMode = CD_IO::Mode::from(CD_IO::Mode::SingleSpeed, CD_IO::Mode::AutoPauseTrack, CD_IO::Mode::CDDA); static constexpr auto DataSectorMode = CD_IO::Mode::from(CD_IO::Mode::DoubleSpeed, CD_IO::Mode::DataSector); static SysCall::InterruptVerifierResult interrupt_verifier(); @@ -88,28 +88,42 @@ namespace JabyEngine { 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); + switch(cur_irq) { + case 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; + cur_lba++; + if(cur_lba == dst_lba) { + current_state = State::Done; + pause_cd(); + } + } + + else { + current_state = State::BufferFull; pause_cd(); } - } + } break; - else { - current_state = State::BufferFull; - pause_cd(); - } - } + case CD_IO::Interrupt::DataEnd: { + CD_IO::PortIndex0::change_to(); + Command::send(CD_IO::Command::SetLoc, static_cast(0x0), static_cast(0x09), static_cast(0x0)); - else if(cur_irq == CD_IO::Interrupt::DiskError) { - current_state = State::Error; + 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(CD_IO::Command::Play); + } break; + + case CD_IO::Interrupt::DiskError: { + current_state = State::Error; + } break; } // No masking required because we can only write bit 0 - 2 @@ -141,7 +155,7 @@ 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); } } }