#pragma once #include "cd_types.hpp" #include #include #include namespace JabyEngine { namespace CD { namespace internal { enum struct State { Ready = 0, Done = 0, XAMode, Reading, BufferFull, Error, }; extern State current_state; struct NewCommand { struct Internal { static void wait_completed(CD_IO::Interrupt::Type irq) { static const auto get_next_irq = []() -> CD_IO::Interrupt::Type { CD_IO::Interrupt::Type cur_irq = CD_IO::Interrupt::None; do { cur_irq = CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlag); } while(cur_irq == CD_IO::Interrupt::None); cur_irq = CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlag); // ^ Stabilize interrupt CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag); return cur_irq; }; CD_IO::PortIndex1::change_to(); while(get_next_irq() != irq); CD_IO::PortIndex0::change_to(); } template static void send(CD_IO::Command::Desc cmd, bool sync, ARGS...args) { while(CD_IO::IndexStatus.read().is_set(CD_IO::IndexStatus::IsTransmissionBusy)); CD_IO::PortIndex0::change_to(); ((CD_IO::PortIndex0::ParameterFifo.write(CD_IO::ParameterFifo{args})),...); CD_IO::PortIndex0::CommandFifo.write(CD_IO::CommandFifo{cmd.id}); if(sync) while(CD_IO::IndexStatus.read().is_set(CD_IO::IndexStatus::IsTransmissionBusy)); } }; // Requires Index 0 template static void send(CD_IO::Command::Desc cmd, ARGS...args) { Internal::send(cmd, true, args...); } template static void sendX(CD_IO::Command::Desc cmd, ARGS...args) { Internal::send(cmd, false, args...); } // Requires Index 0 template static void send_wait_response(CD_IO::Command::Desc cmd, ARGS...args) { Interrupt::disable_irq(Interrupt::CDROM); Internal::send(cmd, true, args...); Internal::wait_completed(cmd.complete_irq); Interrupt::enable_irq(Interrupt::CDROM); } }; namespace IRQ { void data_ready_handler(uint32_t data); 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); } void read_file(AutoLBAEntry file_info, const SectorBufferAllocator& buffer_allocator); void end_read_file(); void continue_reading(); BCDTimeStamp get_loc(); void enable_CD(); void enable_CDDA(); void enable_CDXA(bool double_speed); static void pause() { CD_IO::PortIndex0::change_to(); NewCommand::send(CD_IO::Command::Pause); } } } }