From 1510e27b00e0627f9449c3b4aafac26134ddc60d Mon Sep 17 00:00:00 2001 From: jaby Date: Mon, 5 Sep 2022 20:58:33 +0200 Subject: [PATCH 1/4] Improve IOPort code --- include/PSX/System/IOPorts/DMA_IO.hpp | 20 ++-- include/PSX/System/IOPorts/IOPort.hpp | 119 +++++++++++++++--------- include/PSX/System/IOPorts/SPU_IO.hpp | 40 ++++---- src/Library/src/BootLoader/boot_spu.cpp | 5 +- 4 files changed, 106 insertions(+), 78 deletions(-) diff --git a/include/PSX/System/IOPorts/DMA_IO.hpp b/include/PSX/System/IOPorts/DMA_IO.hpp index 8b787ed6..b93961d7 100644 --- a/include/PSX/System/IOPorts/DMA_IO.hpp +++ b/include/PSX/System/IOPorts/DMA_IO.hpp @@ -3,14 +3,14 @@ #include "IOPort.hpp" namespace DMA { - struct __no_align MADR : public IOPort { - __io_port_inherit(MADR); + struct __no_align MADR : public ComplexBitMap { + __io_port_inherit_complex_bit_map(MADR); static constexpr BitRange MemoryAdr = BitRange::from_to(0, 23); }; - struct __no_align BCR : public IOPort { - __io_port_inherit(BCR); + struct __no_align BCR : public ComplexBitMap { + __io_port_inherit_complex_bit_map(BCR); struct __no_align SyncMode0 { static constexpr BitRange NumberOfWords = BitRange::from_to(0, 15); @@ -26,8 +26,8 @@ namespace DMA { }; }; - struct __no_align CHCHR : public IOPort { - __io_port_inherit(CHCHR); + struct __no_align CHCHR : public ComplexBitMap { + __io_port_inherit_complex_bit_map(CHCHR); enum _SyncMode { Sync0 = 0, //Start immediately, @@ -92,8 +92,8 @@ namespace DMA { static constexpr Priority HighestPriority = 0; static constexpr Priority LowestPriority = 7; - struct __no_align DMAControlRegister : public IOPort { - __io_port_inherit(DMAControlRegister); + struct __no_align DMAControlRegister : public ComplexBitMap { + __io_port_inherit_complex_bit_map(DMAControlRegister); static constexpr Bit OTCEnable = 27; static constexpr BitRange OTCPriority = BitRange::from_to(24, 26); @@ -117,8 +117,8 @@ namespace DMA { static constexpr BitRange MDECinPriority = BitRange::from_to(0, 2); }; - struct __no_align DMAInterruptRegister : public IOPort { - __io_port_inherit(DMAInterruptRegister); + struct __no_align DMAInterruptRegister : public ComplexBitMap { + __io_port_inherit_complex_bit_map(DMAInterruptRegister); static constexpr Bit MasterEnable = 31; static constexpr BitRange Flags = BitRange::from_to(24, 30); diff --git a/include/PSX/System/IOPorts/IOPort.hpp b/include/PSX/System/IOPorts/IOPort.hpp index d0777453..efa21bcc 100644 --- a/include/PSX/System/IOPorts/IOPort.hpp +++ b/include/PSX/System/IOPorts/IOPort.hpp @@ -54,18 +54,18 @@ static constexpr __always_inline BitRangeValue operator<<(const BitRange& } template -class __no_align IOPort { +class __no_align ComplexBitMap { private: T value = 0; public: - constexpr IOPort() = default; - constexpr IOPort(T value) : value(value) { + constexpr ComplexBitMap() = default; + constexpr ComplexBitMap(T value) : value(value) { } //Accesssing bits template - constexpr IOPort& set_bit(S bit) { + constexpr ComplexBitMap& set_bit(S bit) { this->value = bit::set(this->value, static_cast(bit)); return *this; } @@ -76,7 +76,7 @@ public: } template - constexpr IOPort& clear_bit(S bit) { + constexpr ComplexBitMap& clear_bit(S bit) { this->value = bit::clear(this->value, static_cast(bit)); return *this; } @@ -98,7 +98,7 @@ public: //Accessing values template - constexpr IOPort& set_value(S value, const BitRange& range) { + constexpr ComplexBitMap& set_value(S value, const BitRange& range) { this->value = bit::value::set_normalized(this->value, static_cast(value), range.begin, range.length); return *this; } @@ -109,7 +109,7 @@ public: } template - constexpr IOPort& clear_value(const BitRange& range) { + constexpr ComplexBitMap& clear_value(const BitRange& range) { this->value = bit::value::clear_normalized(this->value, range.begin, range.length); return *this; } @@ -129,6 +129,67 @@ public: return static_cast(bit::value::get_normalized(this->value, range.begin, range.length)); } + // For easier constructing + constexpr ComplexBitMap& set(const BitRange& range, T value) { + this->set_value(value, range); + return *this; + } + + constexpr ComplexBitMap& set(const BitRangeValue& value) { + this->set_value(value.value, value.range); + return *this; + } + + constexpr ComplexBitMap& set(const Bit& bit) { + this->set_bit(bit.value); + return *this; + } + + constexpr ComplexBitMap& set(const ClearBitValue& value) { + this->clear_bit(value.bit); + return *this; + } + + constexpr ComplexBitMap& operator|(const BitRangeValue& value) { + this->set_value(value.value, value.range); + return *this; + } + + constexpr ComplexBitMap& operator|(const Bit& bit) { + this->set_bit(bit.value); + return *this; + } + + constexpr ComplexBitMap& operator|(const ClearBitValue& value) { + this->clear_bit(value.bit); + return *this; + } + + //For raw access + constexpr operator T() const { + return this->value; + } + + constexpr operator T() const volatile { + return this->value; + } + + constexpr ComplexBitMap& operator=(T value) { + this->value = value; + return *this; + } + + constexpr void operator=(T value) volatile { + this->value = value; + } +}; + +template +class __no_align IOPort { +private: + T value; + +public: //For easy access constexpr T read() const { return const_cast*>(this)->value; @@ -141,45 +202,11 @@ public: constexpr volatile T& ref() { return const_cast*>(this)->value; } - - //For raw access - constexpr operator T() const { - return this->value; - } - - constexpr operator T() const volatile { - return this->value; - } - - constexpr IOPort& operator=(T value) { - this->value = value; - return *this; - } - - constexpr void operator=(T value) volatile { - this->value = value; - } - - // For easier constructing - constexpr IOPort& operator|(const BitRangeValue& value) { - this->set_value(value.value, value.range); - return *this; - } - - constexpr IOPort& operator|(const Bit& bit) { - this->set_bit(bit.value); - return *this; - } - - constexpr IOPort& operator|(const ClearBitValue& value) { - this->clear_bit(value.bit); - return *this; - } }; struct __no_align ubus32_t { - IOPort low; - IOPort high; + ComplexBitMap low; + ComplexBitMap high; constexpr ubus32_t(uint32_t value) { *this = value; @@ -210,10 +237,10 @@ static constexpr uintptr_t IO_Base_Adr = 0x10000000; #define __declare_io_port_global(type, name, adr) static __always_inline auto& name = *reinterpret_cast*>((IO_Base_Adr + (adr & ~IO_Base_Mask))) #define __declare_io_port_global_array(type, name, adr, size) static __always_inline auto& name = reinterpret_cast(*reinterpret_cast((IO_Base_Adr + (adr & ~IO_Base_Mask)))); -#define __io_port_inherit(name) \ - using IOPort::operator=; \ +#define __io_port_inherit_complex_bit_map(name) \ + using ComplexBitMap::operator=; \ constexpr name() = default; \ - constexpr name(IOPort value) : IOPort(value) { \ + constexpr name(ComplexBitMap value) : ComplexBitMap(value) { \ } #endif //!__JABYENGINE_IOPORT_HPP__ \ No newline at end of file diff --git a/include/PSX/System/IOPorts/SPU_IO.hpp b/include/PSX/System/IOPorts/SPU_IO.hpp index 03316642..f56a2aeb 100644 --- a/include/PSX/System/IOPorts/SPU_IO.hpp +++ b/include/PSX/System/IOPorts/SPU_IO.hpp @@ -26,19 +26,19 @@ namespace SPU { //0..3 = +7, +6, +5, +4 or -6, -7, -6, -5 typedef uint8_t Step; - struct __no_align SampleRate : public IOPort { - __io_port_inherit(SampleRate); + struct __no_align SampleRate : public ComplexBitMap { + __io_port_inherit_complex_bit_map(SampleRate); static constexpr SampleRate from_HZ(double freq) { //4096 == 44100Hz constexpr double Base = (4096.0 / 44100.0); - return IOPort(static_cast((freq*Base))); + return ComplexBitMap(static_cast((freq*Base))); } }; - struct __no_align SweepVolume : public IOPort { - __io_port_inherit(SweepVolume); + struct __no_align SweepVolume : public ComplexBitMap { + __io_port_inherit_complex_bit_map(SweepVolume); // For Volume Mode static constexpr Bit SweepEnable = 15; // 0 Volume Mode; 1 Sweep Mode @@ -52,8 +52,8 @@ namespace SPU { static constexpr BitRange SweepStep = BitRange::from_to(0, 1); }; - struct __no_align SR : public IOPort { - __io_port_inherit(SR); + struct __no_align SR : public ComplexBitMap { + __io_port_inherit_complex_bit_map(SR); static constexpr Bit SustainMode = (31 - 16); static constexpr Bit SustainDirection = (30 - 16); @@ -63,8 +63,8 @@ namespace SPU { static constexpr BitRange ReleaseShift = BitRange::from_to((16 - 16), (20 - 16)); }; - struct __no_align AD : public IOPort { - __io_port_inherit(AD); + struct __no_align AD : public ComplexBitMap { + __io_port_inherit_complex_bit_map(AD); static constexpr Bit AttackMode = 15; static constexpr BitRange AttackShift = BitRange::from_to(10, 14); @@ -74,9 +74,9 @@ namespace SPU { }; struct __no_align Voice { - SweepVolume volumeLeft; //Offset: 0x0 - SweepVolume volumeRight; //Offset: 0x2 - SampleRate sampleRate; //Offset: 0x4; + IOPort volumeLeft; //Offset: 0x0 + IOPort volumeRight; //Offset: 0x2 + IOPort sampleRate; //Offset: 0x4; IOPort adr; //Offset: 0x6 IOPort ad; //Offset: 0x8 IOPort sr; //Offset: 0xA @@ -84,8 +84,8 @@ namespace SPU { IOPort repeatAdr; //Offset: 0xE }; - struct __no_align ControlRegister : public IOPort { - __io_port_inherit(ControlRegister); + struct __no_align ControlRegister : public ComplexBitMap { + __io_port_inherit_complex_bit_map(ControlRegister); enum RAMTransferMode { Stop = 0, @@ -107,20 +107,20 @@ namespace SPU { static constexpr Bit CDAudioEnable = 0; }; - struct __no_align PitchModFlags : public IOPort { - __io_port_inherit(PitchModFlags); + struct __no_align PitchModFlags : public ComplexBitMap { + __io_port_inherit_complex_bit_map(PitchModFlags); static constexpr BitRange EnableBits = BitRange::from_to(1, 23); }; - struct __no_align NoiseGenerator : public IOPort { - __io_port_inherit(NoiseGenerator); + struct __no_align NoiseGenerator : public ComplexBitMap { + __io_port_inherit_complex_bit_map(NoiseGenerator); static constexpr BitRange NoiseBits = BitRange::from_to(0, 23); }; - struct __no_align EchoOn : public IOPort { - __io_port_inherit(EchoOn); + struct __no_align EchoOn : public ComplexBitMap { + __io_port_inherit_complex_bit_map(EchoOn); static constexpr BitRange EchoBits = BitRange::from_to(0, 23); }; diff --git a/src/Library/src/BootLoader/boot_spu.cpp b/src/Library/src/BootLoader/boot_spu.cpp index 4510aff8..833e94e8 100644 --- a/src/Library/src/BootLoader/boot_spu.cpp +++ b/src/Library/src/BootLoader/boot_spu.cpp @@ -10,7 +10,7 @@ namespace SPU { } static void clear_main_volume() { - static constexpr auto StartVol = SweepVolume() | !SweepVolume::SweepEnable | (SweepVolume::Volume << static_cast(I16_MAX >> 2)); + static constexpr auto StartVol = SweepVolume().set(!SweepVolume::SweepEnable).set(SweepVolume::Volume, I16_MAX >> 2); MainVolume::left.write(StartVol); MainVolume::right.write(StartVol); @@ -58,7 +58,7 @@ namespace SPU { } static void setup_control_register() { - static constexpr auto SetupValue = ControlRegister() | ControlRegister::Enable | ControlRegister::Unmute | ControlRegister::CDAudioEnable; + static constexpr auto SetupValue = ControlRegister().set(ControlRegister::Enable).set(ControlRegister::Unmute).set(ControlRegister::CDAudioEnable); Control.write(SetupValue); } @@ -84,5 +84,6 @@ namespace SPU { // Enable SPU DMA DPCR.write(DPCR.read() | DMAControlRegister::SPUEnable); + while(!DPCR.read().is_bit_set(DMAControlRegister::SPUEnable)); } } \ No newline at end of file From 907a04bc9abc6af3b7bbe7a2f41f7987acc833a2 Mon Sep 17 00:00:00 2001 From: jaby Date: Mon, 5 Sep 2022 21:05:51 +0200 Subject: [PATCH 2/4] Remove endless loop --- src/Library/src/BootLoader/boot_spu.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Library/src/BootLoader/boot_spu.cpp b/src/Library/src/BootLoader/boot_spu.cpp index 833e94e8..9a45204a 100644 --- a/src/Library/src/BootLoader/boot_spu.cpp +++ b/src/Library/src/BootLoader/boot_spu.cpp @@ -84,6 +84,5 @@ namespace SPU { // Enable SPU DMA DPCR.write(DPCR.read() | DMAControlRegister::SPUEnable); - while(!DPCR.read().is_bit_set(DMAControlRegister::SPUEnable)); } } \ No newline at end of file From 3448d3c1152a6a56b8b4008c22de57ed7c36d4ab Mon Sep 17 00:00:00 2001 From: jaby Date: Mon, 5 Sep 2022 22:35:38 +0200 Subject: [PATCH 3/4] Support 'with' --- include/PSX/System/IOPorts/IOPort.hpp | 38 +++++++++++++++++++------ src/Library/src/BootLoader/boot_spu.cpp | 4 +-- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/include/PSX/System/IOPorts/IOPort.hpp b/include/PSX/System/IOPorts/IOPort.hpp index efa21bcc..56c9760d 100644 --- a/include/PSX/System/IOPorts/IOPort.hpp +++ b/include/PSX/System/IOPorts/IOPort.hpp @@ -27,6 +27,13 @@ struct Bit { } }; +template +struct BitRangeValue { + T value; + size_t begin; + size_t length; +}; + template struct BitRange { typedef T ValueType; @@ -37,20 +44,15 @@ struct BitRange { static constexpr BitRange from_to(size_t start, size_t end) { return {start, (end - start + 1)}; } -}; -template -struct BitRangeValue { - T value; - BitRange range; - - constexpr BitRangeValue(BitRange range, T value) : value(value), range(range) { + constexpr BitRangeValue with(T value) const { + return {value, this->begin, this->length}; } }; template static constexpr __always_inline BitRangeValue operator<<(const BitRange& range, T value) { - return BitRangeValue(range, value); + return BitRangeValue{value, range.begin, range.length}; } template @@ -58,11 +60,26 @@ class __no_align ComplexBitMap { private: T value = 0; + template + constexpr ComplexBitMap& set_va(const S& value) { + return this->set(value); + } + + template + constexpr ComplexBitMap& set_va(const S& value, const ARGS&...args) { + return this->set_va(value).set_va(args...); + } + public: constexpr ComplexBitMap() = default; constexpr ComplexBitMap(T value) : value(value) { } + template + static constexpr ComplexBitMap with(ARGS...args) { + return ComplexBitMap().set_va(args...); + } + //Accesssing bits template constexpr ComplexBitMap& set_bit(S bit) { @@ -136,7 +153,7 @@ public: } constexpr ComplexBitMap& set(const BitRangeValue& value) { - this->set_value(value.value, value.range); + this->set_value(value.value, {value.begin, value.length}); return *this; } @@ -241,6 +258,9 @@ static constexpr uintptr_t IO_Base_Adr = 0x10000000; using ComplexBitMap::operator=; \ constexpr name() = default; \ constexpr name(ComplexBitMap value) : ComplexBitMap(value) { \ + }\ + template \ + constexpr name(ARGS...args) : ComplexBitMap(args...) {\ } #endif //!__JABYENGINE_IOPORT_HPP__ \ No newline at end of file diff --git a/src/Library/src/BootLoader/boot_spu.cpp b/src/Library/src/BootLoader/boot_spu.cpp index 9a45204a..4d2eac7e 100644 --- a/src/Library/src/BootLoader/boot_spu.cpp +++ b/src/Library/src/BootLoader/boot_spu.cpp @@ -10,7 +10,7 @@ namespace SPU { } static void clear_main_volume() { - static constexpr auto StartVol = SweepVolume().set(!SweepVolume::SweepEnable).set(SweepVolume::Volume, I16_MAX >> 2); + static constexpr auto StartVol = SweepVolume::with(!SweepVolume::SweepEnable, SweepVolume::Volume.with(I16_MAX >> 2)); MainVolume::left.write(StartVol); MainVolume::right.write(StartVol); @@ -58,7 +58,7 @@ namespace SPU { } static void setup_control_register() { - static constexpr auto SetupValue = ControlRegister().set(ControlRegister::Enable).set(ControlRegister::Unmute).set(ControlRegister::CDAudioEnable); + static constexpr auto SetupValue = ControlRegister::with(ControlRegister::Enable, ControlRegister::Unmute, ControlRegister::CDAudioEnable); Control.write(SetupValue); } From c9d4af93768bb64dd1c17cf09ce115d2787b1cba Mon Sep 17 00:00:00 2001 From: jaby Date: Wed, 7 Sep 2022 19:08:11 +0200 Subject: [PATCH 4/4] Final clean up of IOPort --- include/PSX/System/IOPorts/SPU_IO.hpp | 11 ++++++----- src/Library/src/BootLoader/boot_spu.cpp | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/PSX/System/IOPorts/SPU_IO.hpp b/include/PSX/System/IOPorts/SPU_IO.hpp index f56a2aeb..ea4ecf4a 100644 --- a/include/PSX/System/IOPorts/SPU_IO.hpp +++ b/include/PSX/System/IOPorts/SPU_IO.hpp @@ -41,8 +41,9 @@ namespace SPU { __io_port_inherit_complex_bit_map(SweepVolume); // For Volume Mode - static constexpr Bit SweepEnable = 15; // 0 Volume Mode; 1 Sweep Mode - static constexpr BitRange Volume = BitRange::from_to(0, 14); + static constexpr Bit SweepEnable = 15; // 0 Volume Mode; 1 Sweep Mode + static constexpr auto VolumeEnable = !SweepEnable; + static constexpr BitRange Volume = BitRange::from_to(0, 14); // For Sweep Mode static constexpr Bit SweepMode = 14; @@ -74,9 +75,9 @@ namespace SPU { }; struct __no_align Voice { - IOPort volumeLeft; //Offset: 0x0 - IOPort volumeRight; //Offset: 0x2 - IOPort sampleRate; //Offset: 0x4; + IOPort volumeLeft; //Offset: 0x0 + IOPort volumeRight; //Offset: 0x2 + IOPort sampleRate; //Offset: 0x4; IOPort adr; //Offset: 0x6 IOPort ad; //Offset: 0x8 IOPort sr; //Offset: 0xA diff --git a/src/Library/src/BootLoader/boot_spu.cpp b/src/Library/src/BootLoader/boot_spu.cpp index 4d2eac7e..8505efcd 100644 --- a/src/Library/src/BootLoader/boot_spu.cpp +++ b/src/Library/src/BootLoader/boot_spu.cpp @@ -10,7 +10,7 @@ namespace SPU { } static void clear_main_volume() { - static constexpr auto StartVol = SweepVolume::with(!SweepVolume::SweepEnable, SweepVolume::Volume.with(I16_MAX >> 2)); + static constexpr auto StartVol = SweepVolume::with(SweepVolume::VolumeEnable, SweepVolume::Volume.with(I16_MAX >> 2)); MainVolume::left.write(StartVol); MainVolume::right.write(StartVol);