Start to move CDXA code around

This commit is contained in:
jaby 2024-05-31 23:47:39 +02:00
parent 9fab686e1e
commit 658eed7b46
6 changed files with 101 additions and 102 deletions

View File

@ -7,7 +7,6 @@
#include <FontWriter/font_writer.hpp> #include <FontWriter/font_writer.hpp>
//#include <PSX/Audio/CDDA.hpp> //#include <PSX/Audio/CDDA.hpp>
#include <PSX/Periphery/periphery.hpp> #include <PSX/Periphery/periphery.hpp>
#include <PSX/System/callbacks.hpp>
#include <stdio.hpp> #include <stdio.hpp>
using namespace JabyEngine; using namespace JabyEngine;
@ -149,7 +148,7 @@ namespace LoadingScene {
static constexpr auto TitleLength = (sizeof(Title) - 1)*DefaultFont::Info.get_font_size().width; static constexpr auto TitleLength = (sizeof(Title) - 1)*DefaultFont::Info.get_font_size().width;
auto cursor = FontWriter::update(JabyEngine::Make::PositionI16((GPU::Display::Width-TitleLength)/2, (GPU::Display::Height-16)/2)); auto cursor = FontWriter::update(JabyEngine::Make::PositionI16((GPU::Display::Width-TitleLength)/2, (GPU::Display::Height-16)/2));
FontWriter::new_font_writer.write(cursor, Title, GPU::Color24::Blue(0xD0)); FontWriter::new_font_writer.write(cursor, Title, GPU::Color24::Blue(0xD0));
} }
static void render() { static void render() {
@ -159,12 +158,8 @@ namespace LoadingScene {
static void run() { static void run() {
if(old_state_changer != state_changer) { if(old_state_changer != state_changer) {
printf("Loading new state...\n"); printf("Loading new state...\n");
Callback::VSyncCallback::install([]() {
// TODO: Use it or remove it!!
printf("Still loading...\n");
});
// TODO: Callback for file load? Locally?
update(); update();
GPU::swap_buffers_vsync(1); GPU::swap_buffers_vsync(1);
render(); render();
@ -175,7 +170,6 @@ namespace LoadingScene {
state_changer.asset_load(); state_changer.asset_load();
old_state_changer = state_changer; old_state_changer = state_changer;
//CDDA::pop_play(); //CDDA::pop_play();
Callback::VSyncCallback::uninstall();
} }
state_changer.main(); state_changer.main();

View File

@ -49,15 +49,19 @@ namespace JabyEngine {
} }
}; };
namespace IRQ {
void read_sector_to(uint32_t* dst, size_t bytes);
void resume_at(const BCDTimeStamp& cd_time);
}
static State read_current_state() { static State read_current_state() {
return const_cast<volatile State&>(current_state); return const_cast<volatile State&>(current_state);
} }
void read_file(AutoLBAEntry file_info, const SectorBufferAllocator& buffer_allocator); void read_file(AutoLBAEntry file_info, const SectorBufferAllocator& buffer_allocator);
void read_xa(uint32_t lba, uint8_t channel);
void continue_reading(); void continue_reading();
CDTimeStamp get_lock(); BCDTimeStamp get_loc();
void enable_CDDA(); void enable_CDDA();
void enable_CDXA(bool double_speed); void enable_CDXA(bool double_speed);

View File

@ -62,7 +62,7 @@ namespace JabyEngine {
} }
}; };
struct CDTimeStamp { struct BCDTimeStamp {
static constexpr size_t MaxSector = 75; static constexpr size_t MaxSector = 75;
static constexpr size_t MaxSeconds = 60; static constexpr size_t MaxSeconds = 60;
@ -70,23 +70,15 @@ namespace JabyEngine {
uint8_t sec; uint8_t sec;
uint8_t sector; uint8_t sector;
static constexpr CDTimeStamp from(uint32_t lba) { static constexpr BCDTimeStamp from_time(uint8_t min, uint8_t sec, uint8_t sectors) {
return BCDTimeStamp{.min = to_bcd(min), .sec = to_bcd(sec), .sector = to_bcd(sectors)};
}
static constexpr BCDTimeStamp from(uint32_t lba) {
const auto [min, new_lba] = div_and_mod(lba, MaxSector*MaxSeconds); const auto [min, new_lba] = div_and_mod(lba, MaxSector*MaxSeconds);
const auto [sec, sectors] = div_and_mod(new_lba, MaxSector); const auto [sec, sectors] = div_and_mod(new_lba, MaxSector);
return CDTimeStamp{static_cast<uint8_t>(min), static_cast<uint8_t>(sec), static_cast<uint8_t>(sectors)}; return BCDTimeStamp::from_time(min, sec, sectors);
}
constexpr uint8_t get_min_cd() const {
return to_bcd(this->min);
}
constexpr uint8_t get_sec_cd() const {
return to_bcd(this->sec);
}
constexpr uint8_t get_sector_cd() const {
return to_bcd(this->sector);
} }
}; };
} }

View File

@ -5,8 +5,8 @@ namespace JabyEngine {
namespace CDDA { namespace CDDA {
namespace CD = JabyEngine::CD::internal; namespace CD = JabyEngine::CD::internal;
static CD::CDTimeStamp playing_track; static CD::BCDTimeStamp playing_track;
static CD::CDTimeStamp last_track; static CD::BCDTimeStamp last_track;
TrackList get_tracks() { TrackList get_tracks() {
CD::Command::wait_completed(); CD::Command::wait_completed();
@ -43,7 +43,7 @@ namespace JabyEngine {
void push_play() { void push_play() {
stop(); stop();
last_track = CD::get_lock(); last_track = CD::get_loc();
} }
void pop_play() { void pop_play() {

View File

@ -1,33 +1,72 @@
#include "../../internal-include/CD/cd_internal.hpp" #include "../../internal-include/CD/cd_internal.hpp"
#include "../../internal-include/CD/cd_types.hpp"
#include <PSX/Audio/CDXA.hpp> #include <PSX/Audio/CDXA.hpp>
namespace JabyEngine { namespace JabyEngine {
namespace CDXA { namespace CDXA {
namespace CD = JabyEngine::CD::internal; namespace CD = JabyEngine::CD::internal;
static struct {
CD::BCDTimeStamp start_loc;
CD::BCDTimeStamp last_loc;
bool double_speed;
uint8_t channel;
} setting;
CD::State interrupt_handler(uint8_t irq) {
switch(irq) {
case CD_IO::Interrupt::DataReady: {
// The IRQ stack is 0x1000 bytes large so this should fit
CD::RawXADataSector xa_file;
CD::IRQ::read_sector_to(reinterpret_cast<uint32_t*>(&xa_file), sizeof(CD::RawXADataSector));
if(setting.channel == xa_file.sub_header.channel_number) {
CD::IRQ::resume_at(setting.start_loc);
CD::Command::send<CD_IO::PortIndex0>(CD_IO::Command::ReadS);
}
} break;
case CD_IO::Interrupt::DiskError:
return CD::State::Error;
};
return CD::State::XAMode;
}
void play(const volatile AutoLBAEntry* lba, uint8_t rel_lba_idx, uint8_t channel, bool double_speed) { void play(const volatile AutoLBAEntry* lba, uint8_t rel_lba_idx, uint8_t channel, bool double_speed) {
setting.start_loc = CD::BCDTimeStamp::from(lba[rel_lba_idx].get_lba());
setting.double_speed = double_speed;
CD::enable_CDXA(double_speed); CD::enable_CDXA(double_speed);
CD::read_xa(lba[rel_lba_idx].get_lba(), channel); set_channel(channel);
CD::Command::wait_completed();
CD::Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::SetLoc, setting.start_loc.min, setting.start_loc.sec, setting.start_loc.sector);
CD::Command::send<CD_IO::PortIndex0>(CD_IO::Command::ReadS);
} }
void stop() { void stop() {
// TODO: Alias this?
CD::pause(); CD::pause();
} }
void set_channel(uint8_t channel) { void set_channel(uint8_t channel) {
//CD::Command::send<CD_IO::PortIndex0>(CD_IO::Command::Filter, File, channel); static constexpr uint8_t File = 1;
CD::Command::send<CD_IO::PortIndex0>(CD_IO::Command::Filter, File, channel);
setting.channel = channel;
} }
void push_play() { void push_play() {
/*stop(); stop();
last_track = CD::get_lock();*/ setting.last_loc = CD::get_loc();
} }
void pop_play() { void pop_play() {
/*CD::Command::wait_completed(); CD::Command::wait_completed();
CD::enable_CDDA(); // < Command waits CD::enable_CDXA(setting.double_speed);
CD::Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::SetLoc, last_track.min, last_track.sec, last_track.sector);
CD::Command::send<CD_IO::PortIndex0>(CD_IO::Command::Play);*/ set_channel(setting.channel);
CD::Command::wait_completed();
CD::Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::SetLoc, setting.last_loc.min, setting.last_loc.sec, setting.last_loc.sector);
CD::Command::send<CD_IO::PortIndex0>(CD_IO::Command::ReadS);
} }
} }
} }

View File

@ -5,31 +5,25 @@
#include <stdio.hpp> #include <stdio.hpp>
namespace JabyEngine { namespace JabyEngine {
namespace CDXA {
CD::internal::State interrupt_handler(uint8_t irq);
}
namespace CD { namespace CD {
namespace internal { namespace internal {
union Configuration { struct File {
struct File { uint32_t cur_lba;
uint32_t cur_lba; uint32_t dst_lba;
uint32_t dst_lba;
void set_from(const AutoLBAEntry& file_info) { void set_from(const AutoLBAEntry& file_info) {
this->cur_lba = file_info.get_lba(); this->cur_lba = file_info.get_lba();
this->dst_lba = this->cur_lba + file_info.get_size_in_sectors(); this->dst_lba = this->cur_lba + file_info.get_size_in_sectors();
} }
bool done_processing() { bool done_processing() {
this->cur_lba++; this->cur_lba++;
return this->cur_lba == this->dst_lba; return this->cur_lba == this->dst_lba;
} }
};
struct XA {
CDTimeStamp start_time;
uint8_t channel;
};
File file;
XA xa;
}; };
static constexpr auto AudioSectorMode = CD_IO::Mode::from(CD_IO::Mode::SingleSpeed, CD_IO::Mode::AutoPauseTrack, CD_IO::Mode::CDDA); static constexpr auto AudioSectorMode = CD_IO::Mode::from(CD_IO::Mode::SingleSpeed, CD_IO::Mode::AutoPauseTrack, CD_IO::Mode::CDDA);
@ -42,7 +36,7 @@ namespace JabyEngine {
} }
static SectorBufferAllocator sector_allocator; static SectorBufferAllocator sector_allocator;
static Configuration cur_cfg; static File cur_file;
uint8_t cmd_interrupt_bit = 0; uint8_t cmd_interrupt_bit = 0;
State current_state = State::Ready; State current_state = State::Ready;
@ -52,11 +46,10 @@ namespace JabyEngine {
.verifier_function = IRQ::verifier .verifier_function = IRQ::verifier
}; };
// Requires Index0 static BCDTimeStamp send_read_cmd(uint32_t lba, CD_IO::Command::Desc desc) {
static CDTimeStamp send_read_cmd(uint32_t lba, CD_IO::Command::Desc desc) { const auto loc = BCDTimeStamp::from(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_wait<CD_IO::PortIndex0>(CD_IO::Command::SetLoc, loc.min, loc.sec, loc.sector);
Command::send<CD_IO::PortIndex0>(desc); Command::send<CD_IO::PortIndex0>(desc);
return loc; return loc;
} }
@ -86,7 +79,7 @@ namespace JabyEngine {
ReadSector(dst, bytes); ReadSector(dst, bytes);
} }
static void read_sector_to(uint32_t* dst, size_t bytes) { void read_sector_to(uint32_t* dst, size_t bytes) {
CD_IO::PortIndex0::Request.write(CD_IO::Request::want_data()); CD_IO::PortIndex0::Request.write(CD_IO::Request::want_data());
// We only support DMA rn // We only support DMA rn
@ -96,8 +89,8 @@ namespace JabyEngine {
// Doesn't seem to important when we can use DMA // Doesn't seem to important when we can use DMA
} }
static void resume_at(const CDTimeStamp& cd_time) { void resume_at(const BCDTimeStamp& cd_time) {
Command::send<CD_IO::PortIndex0>(CD_IO::Command::SetLoc, cd_time.get_min_cd(), cd_time.get_sec_cd(), cd_time.get_sector_cd()); Command::send<CD_IO::PortIndex0>(CD_IO::Command::SetLoc, cd_time.min, cd_time.sec, cd_time.sector);
CD_IO::PortIndex1::change_to(); CD_IO::PortIndex1::change_to();
while(CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlag) != CD_IO::Interrupt::Acknowledge); while(CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlag) != CD_IO::Interrupt::Acknowledge);
@ -137,7 +130,7 @@ namespace JabyEngine {
//Now obtain sector //Now obtain sector
read_sector_to(sector->data, CD_IO::DataSector::SizeBytes); read_sector_to(sector->data, CD_IO::DataSector::SizeBytes);
if(cur_cfg.file.done_processing()) { if(cur_file.done_processing()) {
current_state = State::Done; current_state = State::Done;
pause(); pause();
} }
@ -151,7 +144,7 @@ namespace JabyEngine {
case CD_IO::Interrupt::DataEnd: { case CD_IO::Interrupt::DataEnd: {
// TODO: Fix this!! This is a freaking static time // TODO: Fix this!! This is a freaking static time
resume_at(CDTimeStamp{.min = 0, .sec = 9, .sector = 0}); resume_at(BCDTimeStamp{.min = 0x0, .sec = 0x09, .sector = 0x0});
Command::send<CD_IO::PortIndex0>(CD_IO::Command::Play); Command::send<CD_IO::PortIndex0>(CD_IO::Command::Play);
} break; } break;
@ -162,22 +155,7 @@ namespace JabyEngine {
} }
else { else {
switch(cur_irq) { current_state = CDXA::interrupt_handler(cur_irq);
case CD_IO::Interrupt::DataReady: {
// The IRQ stack is 0x1000 bytes large so this should fit
RawXADataSector xa_file;
read_sector_to(reinterpret_cast<uint32_t*>(&xa_file), sizeof(RawXADataSector));
if(cur_cfg.xa.channel == xa_file.sub_header.channel_number) {
resume_at(cur_cfg.xa.start_time);
Command::send<CD_IO::PortIndex0>(CD_IO::Command::ReadS);
}
} break;
case CD_IO::Interrupt::DiskError: {
current_state = State::Error;
} break;
};
} }
// No masking required because we can only write bit 0 - 2 // No masking required because we can only write bit 0 - 2
@ -190,33 +168,24 @@ namespace JabyEngine {
} }
void read_file(AutoLBAEntry file_info, const SectorBufferAllocator& buffer_allocator) { void read_file(AutoLBAEntry file_info, const SectorBufferAllocator& buffer_allocator) {
cur_cfg.file.set_from(file_info); cur_file.set_from(file_info);
sector_allocator = buffer_allocator; sector_allocator = buffer_allocator;
Command::wait_completed(); Command::wait_completed();
Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::SetMode, DataSectorMode); Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::SetMode, DataSectorMode);
send_read_n(cur_cfg.file.cur_lba); send_read_n(cur_file.cur_lba);
} }
void read_xa(uint32_t lba, uint8_t channel) {
static constexpr uint8_t File = 1;
cur_cfg.xa.channel = channel;
Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::Filter, File, channel);
cur_cfg.xa.start_time = send_read_cmd(lba, CD_IO::Command::ReadS);
current_state = State::XAMode;
}
void continue_reading() { void continue_reading() {
if(current_state == State::BufferFull) { if(current_state == State::BufferFull) {
Command::wait_completed(); Command::wait_completed();
send_read_n(cur_cfg.file.cur_lba); send_read_n(cur_file.cur_lba);
} }
} }
CDTimeStamp get_lock() { BCDTimeStamp get_loc() {
Command::wait_completed(); Command::wait_completed();
Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::GetLocP); Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::GetLocP);
@ -226,11 +195,11 @@ namespace JabyEngine {
const auto ss = CD_IO::PortIndex0::ResponseFifo.read().raw; // second number within track (00h to 59h) const auto ss = CD_IO::PortIndex0::ResponseFifo.read().raw; // second number within track (00h to 59h)
const auto sect = CD_IO::PortIndex0::ResponseFifo.read().raw; // sector number within track (00h to 74h) const auto sect = CD_IO::PortIndex0::ResponseFifo.read().raw; // sector number within track (00h to 74h)
return CDTimeStamp{ return BCDTimeStamp::from_time(
.min = CD_IO::PortIndex0::ResponseFifo.read().raw, // minute number on entire disk (00h and up) CD_IO::PortIndex0::ResponseFifo.read().raw, // minute number on entire disk (00h and up)
.sec = CD_IO::PortIndex0::ResponseFifo.read().raw, // second number on entire disk (00h to 59h) CD_IO::PortIndex0::ResponseFifo.read().raw, // second number on entire disk (00h to 59h)
.sector = CD_IO::PortIndex0::ResponseFifo.read().raw, // sector number on entire disk (00h to 74h) CD_IO::PortIndex0::ResponseFifo.read().raw // sector number on entire disk (00h to 74h)
}; );
} }
void enable_CDDA() { void enable_CDDA() {
@ -246,6 +215,7 @@ namespace JabyEngine {
Command::wait_completed(); Command::wait_completed();
Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::SetMode, mode); Command::send_wait<CD_IO::PortIndex0>(CD_IO::Command::SetMode, mode);
current_state = State::XAMode;
} }
} }
} }