Support CD IO and start removing old IOPort

This commit is contained in:
jaby 2023-09-22 18:52:31 +02:00
parent 2aaa41302f
commit 32682aa2f0
5 changed files with 101 additions and 213 deletions

View File

@ -31,7 +31,7 @@ namespace JabyEngine {
static constexpr uint8_t Max = 0xFF; static constexpr uint8_t Max = 0xFF;
}; };
__declare_io_type(Mode, uint8_t, __new_declare_io_value(Mode, uint8_t) {
static constexpr auto DoubleSpeed = Bit(7); static constexpr auto DoubleSpeed = Bit(7);
static constexpr auto SingleSpeed = !DoubleSpeed; static constexpr auto SingleSpeed = !DoubleSpeed;
static constexpr auto XADPCM = Bit(6); static constexpr auto XADPCM = Bit(6);
@ -41,9 +41,13 @@ namespace JabyEngine {
static constexpr auto AudioPlayIRQ = Bit(2); static constexpr auto AudioPlayIRQ = Bit(2);
static constexpr auto AutoPauseTrack = Bit(1); static constexpr auto AutoPauseTrack = Bit(1);
static constexpr auto CDDA = Bit(0); static constexpr auto CDDA = Bit(0);
);
__declare_io_type(IndexStatus, uint8_t, operator uint8_t() const {
return this->raw;
}
};
__new_declare_io_value(IndexStatus, uint8_t) {
static constexpr auto PortIndex = BitRange::from_to(0, 1); static constexpr auto PortIndex = BitRange::from_to(0, 1);
static constexpr auto HasXAFifoData = Bit(2); static constexpr auto HasXAFifoData = Bit(2);
static constexpr auto IsParameterFifoEmpty = Bit(3); static constexpr auto IsParameterFifoEmpty = Bit(3);
@ -51,30 +55,31 @@ namespace JabyEngine {
static constexpr auto HasResponseFifoData = Bit(5); static constexpr auto HasResponseFifoData = Bit(5);
static constexpr auto HasDataFifoData = Bit(6); static constexpr auto HasDataFifoData = Bit(6);
static constexpr auto IsTransmissionBusy = Bit(7); static constexpr auto IsTransmissionBusy = Bit(7);
); };
__declare_io_type(InterruptEnable, uint8_t, __new_declare_io_value(InterruptEnable, uint8_t) {
static constexpr auto InterruptTypValue = BitRange::from_to(0, 2); static constexpr auto InterruptTypValue = BitRange::from_to(0, 2);
static constexpr auto InterruptExtended = BitRange::from_to(0, 4); static constexpr auto InterruptExtended = BitRange::from_to(0, 4);
static constexpr auto UnknownIRQ = Bit(3); static constexpr auto UnknownIRQ = Bit(3);
static constexpr auto CommandStartIRQ = Bit(4); static constexpr auto CommandStartIRQ = Bit(4);
); };
typedef InterruptEnable_v InterruptFlag_v; using InterruptFlag = InterruptEnable;
__declare_io_type(Request, uint8_t,
__new_declare_io_value(Request, uint8_t) {
static constexpr auto WantCommandStartIRQ = Bit(5); static constexpr auto WantCommandStartIRQ = Bit(5);
static constexpr auto WantData = Bit(7); static constexpr auto WantData = Bit(7);
void want_data() { static Request want_data() {
this->raw_value = static_cast<uint8_t>(Self::WantData); return Request{static_cast<uint8_t>(Request::WantData)};
} }
void reset() { static Request reset() {
this->raw_value = 0; return Request{0};
} }
); };
__declare_io_type(SoundMapCoding, uint8_t, __new_declare_io_value(SoundMapCoding, uint8_t) {
static constexpr auto Stereo = Bit(0); static constexpr auto Stereo = Bit(0);
static constexpr auto Mono = !Stereo; static constexpr auto Mono = !Stereo;
static constexpr auto SampleRate_18900hz = Bit(2); static constexpr auto SampleRate_18900hz = Bit(2);
@ -82,23 +87,33 @@ namespace JabyEngine {
static constexpr auto BitsPerSample8 = Bit(4); static constexpr auto BitsPerSample8 = Bit(4);
static constexpr auto BitsPerSample4 = !BitsPerSample8; static constexpr auto BitsPerSample4 = !BitsPerSample8;
static constexpr auto Emphasis = Bit(6); static constexpr auto Emphasis = Bit(6);
); };
__declare_io_type(AudioVolumeApply, uint8_t, __new_declare_io_value(AudioVolumeApply, uint8_t) {
static constexpr auto Mute = Bit(0); static constexpr auto Mute = Bit(0);
static constexpr auto ApplyChanges = Bit(5); static constexpr auto ApplyChanges = Bit(5);
); };
__declare_io_type(ResponseFifo, uint8_t,); __new_declare_io_value(ResponseFifo, uint8_t) {
__declare_io_type(CommandFifo, uint8_t,); };
__declare_io_type(DataFifo, uint8_t,); __new_declare_io_value(CommandFifo, uint8_t) {
__declare_io_type(DataFifo16, uint16_t,); };
__declare_io_type(ParameterFifo, uint8_t,); __new_declare_io_value(DataFifo, uint8_t) {
__declare_io_type(SoundMapDataOut, uint8_t,); };
__declare_io_type(LeftCD2LeftSPU, CDDAVolume::Type,); __new_declare_io_value(DataFifo16, uint16_t) {
__declare_io_type(LeftCD2RightSPU, CDDAVolume::Type,); };
__declare_io_type(RightCD2RightSPU,CDDAVolume::Type,); __new_declare_io_value(ParameterFifo, uint8_t) {
__declare_io_type(RightCD2LeftSPU, CDDAVolume::Type,); };
__new_declare_io_value(SoundMapDataOut, uint8_t) {
};
__new_declare_io_value(LeftCD2LeftSPU, CDDAVolume::Type) {
};
__new_declare_io_value(LeftCD2RightSPU, CDDAVolume::Type) {
};
__new_declare_io_value(RightCD2RightSPU, CDDAVolume::Type) {
};
__new_declare_io_value(RightCD2LeftSPU, CDDAVolume::Type) {
};
struct Interrupt { struct Interrupt {
enum Type : uint8_t { enum Type : uint8_t {
@ -110,24 +125,24 @@ namespace JabyEngine {
DiskError = 5 DiskError = 5
}; };
static void enable(InterruptEnable_v& port) { static void enable(New::IOPort<InterruptEnable>& port) {
port.set(InterruptEnable_t::InterruptTypValue.range_max<uint8_t>()); port.write(port.read().set2(InterruptEnable::InterruptTypValue.range_max<uint8_t>()));
} }
static void enable_extended(InterruptEnable_v& port) { static void enable_extended(New::IOPort<InterruptEnable>& port) {
port = InterruptEnable_t::from(InterruptEnable_t::InterruptTypValue.range_max<uint8_t>(), InterruptEnable_t::UnknownIRQ, InterruptEnable_t::CommandStartIRQ); port.write(InterruptEnable::from(InterruptEnable::InterruptTypValue.range_max<uint8_t>(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ));
} }
static Type get_type(const InterruptFlag_v& port) { static Type get_type(const New::IOPort<InterruptFlag>& port) {
return static_cast<Type>(port.get(InterruptFlag_v::InterruptTypValue)); return static_cast<Type>(port.read().get2(InterruptFlag::InterruptTypValue));
} }
static void ack(InterruptFlag_v& port) { static void ack(New::IOPort<InterruptFlag>& port) {
port.set(InterruptFlag_v::InterruptTypValue.range_max<uint8_t>()); port.write(port.read().set2(InterruptFlag::InterruptTypValue.range_max<uint8_t>()));
} }
static void ack_extended(InterruptFlag_v& port) { static void ack_extended(New::IOPort<InterruptFlag>& port) {
port = InterruptFlag_v::from(InterruptFlag_v::InterruptTypValue.range_max<uint8_t>(), InterruptEnable_v::UnknownIRQ, InterruptEnable_v::CommandStartIRQ); port.write(InterruptFlag::from(InterruptFlag::InterruptTypValue.range_max<uint8_t>(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ));
} }
}; };
@ -149,71 +164,71 @@ namespace JabyEngine {
static constexpr auto IORegister2Adr = 0x1F801802; static constexpr auto IORegister2Adr = 0x1F801802;
static constexpr auto IORegister3Adr = 0x1F801803; static constexpr auto IORegister3Adr = 0x1F801803;
__declare_new_io_port(IndexStatus, 0x1F801800); __new_declare_io_port(, IndexStatus, 0x1F801800);
#define __declare_index_io_port(type, name, adr) __cast_io_adr_with_type(inline, type, name, adr) //#define __declare_index_io_port(type, name, adr) __cast_io_adr_with_type(inline, type, name, adr)
#define __declare_index_io_port_const(type, name, adr) __cast_io_adr_with_type(const inline, type, name, adr) //#define __declare_index_io_port_const(type, name, adr) __cast_io_adr_with_type(const inline, type, name, adr)
struct PortIndex0 { struct PortIndex0 {
__declare_new_const_io_port(ResponseFifo, IORegister1Adr); __new_declare_io_port(inline const, ResponseFifo, IORegister1Adr);
__declare_new_io_port(CommandFifo, IORegister1Adr); __new_declare_io_port(inline, CommandFifo, IORegister1Adr);
__declare_new_const_io_port(DataFifo, IORegister2Adr); __new_declare_io_port(inline const, DataFifo, IORegister2Adr);
__declare_new_const_io_port(DataFifo16, IORegister2Adr); __new_declare_io_port(inline const, DataFifo16, IORegister2Adr);
__declare_new_io_port(ParameterFifo, IORegister2Adr); __new_declare_io_port(inline, ParameterFifo, IORegister2Adr);
__declare_new_const_io_port(InterruptEnable, IORegister3Adr); __new_declare_io_port(inline const, InterruptEnable, IORegister3Adr);
__declare_new_io_port(Request, IORegister3Adr); __new_declare_io_port(inline, Request, IORegister3Adr);
static void change_to() { static void change_to() {
IndexStatus = Index::Index0; IndexStatus.write({Index::Index0});
} }
}; };
struct PortIndex1 { struct PortIndex1 {
__declare_new_const_io_port(ResponseFifo, IORegister1Adr); __new_declare_io_port(inline const, ResponseFifo, IORegister1Adr);
__declare_new_io_port(SoundMapDataOut, IORegister1Adr); __new_declare_io_port(inline, SoundMapDataOut, IORegister1Adr);
__declare_new_const_io_port(DataFifo, IORegister2Adr); __new_declare_io_port(inline const, DataFifo, IORegister2Adr);
__declare_new_const_io_port(DataFifo16, IORegister2Adr); __new_declare_io_port(inline const, DataFifo16, IORegister2Adr);
__declare_new_io_port(InterruptEnable, IORegister2Adr); __new_declare_io_port(inline, InterruptEnable, IORegister2Adr);
__declare_new_io_port(InterruptFlag, IORegister3Adr); __new_declare_io_port_w_type(inline, struct InterruptEnable, InterruptFlag, IORegister3Adr);
static void change_to() { static void change_to() {
IndexStatus = Index::Index1; IndexStatus.write({Index::Index1});
} }
}; };
struct PortIndex2 { struct PortIndex2 {
__declare_new_const_io_port(ResponseFifo, IORegister1Adr); __new_declare_io_port(inline const, ResponseFifo, IORegister1Adr);
__declare_new_io_port(SoundMapCoding, IORegister1Adr); __new_declare_io_port(inline, SoundMapCoding, IORegister1Adr);
__declare_new_const_io_port(DataFifo, IORegister2Adr); __new_declare_io_port(inline const, DataFifo, IORegister2Adr);
__declare_new_const_io_port(DataFifo16, IORegister2Adr); __new_declare_io_port(inline const, DataFifo16, IORegister2Adr);
__declare_new_io_port(LeftCD2LeftSPU, IORegister2Adr); __new_declare_io_port(inline, LeftCD2LeftSPU, IORegister2Adr);
__declare_new_const_io_port(InterruptEnable, IORegister3Adr); __new_declare_io_port(inline const, InterruptEnable, IORegister3Adr);
__declare_new_io_port(LeftCD2RightSPU, IORegister3Adr); __new_declare_io_port(inline, LeftCD2RightSPU, IORegister3Adr);
static void change_to() { static void change_to() {
IndexStatus = Index::Index2; IndexStatus.write({Index::Index2});
} }
}; };
struct PortIndex3 { struct PortIndex3 {
__declare_new_const_io_port(ResponseFifo, IORegister1Adr); __new_declare_io_port(inline const, ResponseFifo, IORegister1Adr);
__declare_new_io_port(RightCD2RightSPU, IORegister1Adr); __new_declare_io_port(inline, RightCD2RightSPU, IORegister1Adr);
__declare_new_const_io_port(DataFifo, IORegister2Adr); __new_declare_io_port(inline const, DataFifo, IORegister2Adr);
__declare_new_const_io_port(DataFifo16, IORegister2Adr); __new_declare_io_port(inline const, DataFifo16, IORegister2Adr);
__declare_new_io_port(RightCD2LeftSPU, IORegister1Adr); __new_declare_io_port(inline, RightCD2LeftSPU, IORegister1Adr);
__declare_new_const_io_port(InterruptFlag, IORegister3Adr); __new_declare_io_port_w_type(inline const, struct InterruptEnable, InterruptFlag, IORegister3Adr);
__declare_new_io_port(AudioVolumeApply, IORegister3Adr); __new_declare_io_port(inline, AudioVolumeApply, IORegister3Adr);
static void change_to() { static void change_to() {
IndexStatus = Index::Index3; IndexStatus.write({Index::Index3});
} }
}; };

View File

@ -185,6 +185,9 @@ namespace JabyEngine {
} }
}; };
__new_declare_io_value(GPUREAD, uint32_t) {
};
__new_declare_io_value(GPUSTAT, uint32_t) { __new_declare_io_value(GPUSTAT, uint32_t) {
static constexpr auto DrawingOddLinesInterlaced = Bit(31); static constexpr auto DrawingOddLinesInterlaced = Bit(31);
static constexpr auto DMADirectionValue = BitRange::from_to(29, 30); static constexpr auto DMADirectionValue = BitRange::from_to(29, 30);

View File

@ -110,22 +110,6 @@ namespace JabyEngine {
#define __new_declare_io_port_array(cv, name, size, adr) __new_declare_array_at(cv, struct name, name, size, adr) #define __new_declare_io_port_array(cv, name, size, adr) __new_declare_array_at(cv, struct name, name, size, adr)
} }
namespace IOPort {
struct IOValueType {
template<typename T>
struct Normal {
typedef T Value;
typedef T UnderlyingValue;
};
template<typename T>
struct Volatile {
typedef volatile T Value;
typedef T UnderlyingValue;
};
};
}
namespace IOAdress { namespace IOAdress {
constexpr uintptr_t patch_adr(uintptr_t adr) { constexpr uintptr_t patch_adr(uintptr_t adr) {
constexpr uintptr_t Mask = 0xF0000000; constexpr uintptr_t Mask = 0xF0000000;
@ -134,119 +118,5 @@ namespace JabyEngine {
return (Base + (adr & ~Mask)); return (Base + (adr & ~Mask));
} }
} }
#define __declare_new_named_io_port(type, name, adr) \
static inline auto& name = *reinterpret_cast<type##_v*>(IOAdress::patch_adr(adr))
#define __declare_new_io_port(name, adr) \
__declare_new_named_io_port(name, name, adr)
#define __declare_new_const_io_port(name, adr) \
__declare_new_named_io_port(const name, name, adr)
#define __declare_new_io_port_array(name, adr, size) \
static inline auto& name = reinterpret_cast<name##_v(&)[size]>(*reinterpret_cast<name##_v*>(adr))
// We need this construct to ensure the types end up being a POD - Inheritance doesn't qualify for a POD
#define __declare_io_type(name, type, ...) \
template<template<typename> typename T> \
struct name##_io_base { \
typedef T<type>::UnderlyingValue UnderlyingValue; \
typedef name##_io_base Self; \
\
T<type>::Value raw_value = 0; \
\
__VA_ARGS__ \
\
template<typename...ARGS> \
static constexpr Self from(const ARGS&...args) { \
return Self().set_va(args...); \
} \
\
constexpr Self& set(Bit bit) { \
this->raw_value = bit::set(this->raw_value, bit); \
return *this; \
} \
\
constexpr Self& set(ClearBit bit) { \
this->raw_value = bit::set(this->raw_value, bit); \
return *this; \
} \
\
constexpr Self& set(BitRange bits, UnderlyingValue value) { \
this->raw_value = bit::value::set_normalized(this->raw_value, bits, value); \
return *this; \
} \
\
template<typename S> \
constexpr Self& set(const BitRange::RangeValuePair<S>& value) { \
this->raw_value = bit::value::set_normalized(this->raw_value, value); \
return *this; \
} \
\
template<typename S> \
constexpr Self& set_va(const S& head) { \
return this->set(head); \
} \
\
template<typename S, typename...ARGS> \
constexpr Self& set_va(const S& head, const ARGS&...tail) { \
return this->set(head).set_va(tail...); \
} \
\
constexpr UnderlyingValue get(BitRange bits) const { \
return bit::value::get_normalized(this->raw_value, bits.pos, bits.length); \
} \
\
constexpr Self& clear(Bit bit) { \
this->raw_value = bit::clear(this->raw_value, bit); \
return *this; \
} \
\
constexpr bool is_set(Bit bit) const { \
return bit::is_set(this->raw_value, bit); \
} \
\
constexpr void operator=(UnderlyingValue value) { \
this->raw_value = value; \
} \
\
constexpr operator UnderlyingValue() const { \
return this->raw_value; \
} \
}; \
\
typedef name##_io_base<IOPort::IOValueType::Volatile> name##_v; \
typedef name##_io_base<IOPort::IOValueType::Normal> name##_t
#pragma pack(push, 1)
struct ubus32_t {
__declare_io_type(uint16_t, uint16_t,);
uint16_t_v low;
uint16_t_v high;
constexpr ubus32_t(uint32_t value) : low{0}, high{0} {
*this = value;
}
constexpr void write(uint32_t value) {
*this = value;
}
constexpr operator uint32_t() const {
const uint32_t high = this->high;
const uint32_t low = this->low;
return ((high << 16) | low);
}
constexpr ubus32_t& operator=(uint32_t value) {
this->low = (value & 0xFFFF);
this->high = (value >> 16);
return *this;
}
};
#pragma pack(pop)
} }
#endif //!__JABYENGINE_IOPORT_HPP__ #endif //!__JABYENGINE_IOPORT_HPP__

View File

@ -15,11 +15,11 @@ namespace JabyEngine {
} }
template<typename...ARGS> template<typename...ARGS>
static void send(CD_IO::CommandFifo_v& cmd_fifo, CD_IO::ParameterFifo_v& parameter_fifo, CD_IO::Command::Desc cmd, ARGS...args) { static void send(New::IOPort<CD_IO::CommandFifo>& cmd_fifo, New::IOPort<CD_IO::ParameterFifo>& parameter_fifo, CD_IO::Command::Desc cmd, ARGS...args) {
while(CD_IO::IndexStatus.is_set(CD_IO::IndexStatus_t::IsTransmissionBusy)); while(CD_IO::IndexStatus.read().is_set2(CD_IO::IndexStatus::IsTransmissionBusy));
((parameter_fifo = args),...); ((parameter_fifo.write(CD_IO::ParameterFifo{args})),...);
cmd_fifo = cmd.id; cmd_fifo.write(CD_IO::CommandFifo{cmd.id});
cmd_interrupt_bit = bit::set(0, cmd.complete_irq); cmd_interrupt_bit = bit::set(0, cmd.complete_irq);
} }
@ -29,7 +29,7 @@ namespace JabyEngine {
} }
template<typename...ARGS> template<typename...ARGS>
static void send_wait(CD_IO::CommandFifo_v& cmd_fifo, CD_IO::ParameterFifo_v& parameter_fifo, CD_IO::Command::Desc cmd, ARGS...args) { static void send_wait(New::IOPort<CD_IO::CommandFifo>& cmd_fifo, New::IOPort<CD_IO::ParameterFifo>& parameter_fifo, CD_IO::Command::Desc cmd, ARGS...args) {
send(cmd_fifo, parameter_fifo, cmd, args...); send(cmd_fifo, parameter_fifo, cmd, args...);
wait_completed(); wait_completed();
} }

View File

@ -6,7 +6,7 @@
namespace JabyEngine { namespace JabyEngine {
namespace CD { namespace CD {
namespace internal { namespace internal {
static constexpr auto DataSectorMode = CD_IO::Mode_t::from(CD_IO::Mode_t::DoubleSpeed, CD_IO::Mode_t::DataSector); static constexpr auto DataSectorMode = CD_IO::Mode::from(CD_IO::Mode::DoubleSpeed, CD_IO::Mode::DataSector);
static InterruptVerifierResult interrupt_verifier(); static InterruptVerifierResult interrupt_verifier();
static void interrupt_handler(uint32_t); static void interrupt_handler(uint32_t);
@ -40,7 +40,7 @@ namespace JabyEngine {
static void read_sector_dma(CD_IO::DataSector& sector) { static void read_sector_dma(CD_IO::DataSector& sector) {
static const auto WaitSectorReady = []() { static const auto WaitSectorReady = []() {
while(!CD_IO::IndexStatus.is_set(CD_IO::IndexStatus_t::HasDataFifoData)); while(!CD_IO::IndexStatus.read().is_set2(CD_IO::IndexStatus::HasDataFifoData));
}; };
static const auto ReadSector = [](uint32_t* dst) { static const auto ReadSector = [](uint32_t* dst) {
@ -50,7 +50,7 @@ namespace JabyEngine {
DMA_IO::CDROM.wait(); DMA_IO::CDROM.wait();
CD_IO::PortIndex0::Request.reset(); CD_IO::PortIndex0::Request.write(CD_IO::Request::reset());
}; };
WaitSectorReady(); WaitSectorReady();
@ -59,7 +59,7 @@ namespace JabyEngine {
static void read_sector_to(CD_IO::DataSector& sector) { static void read_sector_to(CD_IO::DataSector& sector) {
CD_IO::PortIndex0::change_to(); CD_IO::PortIndex0::change_to();
CD_IO::PortIndex0::Request.want_data(); CD_IO::PortIndex0::Request.write(CD_IO::Request::want_data());
// We only support DMA rn // We only support DMA rn
read_sector_dma(sector); read_sector_dma(sector);
@ -79,7 +79,7 @@ namespace JabyEngine {
} }
static void interrupt_handler(uint32_t) { static void interrupt_handler(uint32_t) {
const uint8_t old_status = CD_IO::IndexStatus; const auto old_status = CD_IO::IndexStatus.read();
CD_IO::PortIndex1::change_to(); CD_IO::PortIndex1::change_to();
const auto cur_irq = CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlag); const auto cur_irq = CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlag);
@ -112,7 +112,7 @@ namespace JabyEngine {
} }
// No masking required because we can only write bit 0 - 2 // No masking required because we can only write bit 0 - 2
CD_IO::IndexStatus = old_status; CD_IO::IndexStatus.write(old_status);
Interrupt::ack_irq(Interrupt::CDROM); Interrupt::ack_irq(Interrupt::CDROM);
__syscall_ReturnFromException(); __syscall_ReturnFromException();
} }