diff --git a/include/PSX/Auxiliary/complex_bitmap.hpp b/include/PSX/Auxiliary/complex_bitmap.hpp index 5d5b38a7..725d8176 100644 --- a/include/PSX/Auxiliary/complex_bitmap.hpp +++ b/include/PSX/Auxiliary/complex_bitmap.hpp @@ -79,40 +79,79 @@ public: //Accesssing bits template - constexpr __always_inline ComplexBitMap& set_bit(S bit) { + constexpr ComplexBitMap& set_bit(S bit) { this->raw = bit::set(this->raw, static_cast(bit)); return *this; } template - constexpr __always_inline ComplexBitMap& clear_bit(S bit) { + constexpr void set_bit(S bit) volatile { + this->raw = bit::set(this->raw, static_cast(bit)); + } + + template + constexpr ComplexBitMap& clear_bit(S bit) { this->raw = bit::clear(this->raw, static_cast(bit)); return *this; } template - constexpr __always_inline bool is_bit_set(S bit) { + constexpr void clear_bit(S bit) volatile { + this->raw = bit::clear(this->raw, static_cast(bit)); + } + + template + constexpr bool is_bit_set(S bit) { + return bit::is_set(this->raw, static_cast(bit)); + } + + template + constexpr bool is_bit_set(S bit) const volatile { return bit::is_set(this->raw, static_cast(bit)); } //Accessing values template - constexpr __always_inline ComplexBitMap& set_value(S value, const BitRange& range) { + constexpr ComplexBitMap& set_value(S value, const BitRange& range) { this->raw = bit::value::set_normalized(this->raw, static_cast(value), range.begin, range.length); return *this; } template - constexpr __always_inline ComplexBitMap& clear_value(const BitRange& range) { + constexpr void set_value(S value, const BitRange& range) volatile { + this->raw = bit::value::set_normalized(this->raw, static_cast(value), range.begin, range.length); + } + + template + constexpr ComplexBitMap& clear_value(const BitRange& range) { this->raw = bit::value::clear_normalized(this->raw, range.begin, range.length); return *this; } template - constexpr __always_inline S get_value(const BitRange& range) { + constexpr void clear_value(const BitRange& range) volatile { + this->raw = bit::value::clear_normalized(this->raw, range.begin, range.length); + } + + template + constexpr S get_value(const BitRange& range) { return static_cast(bit::value::get_normalized(this->raw, range.begin, range.length)); } + template + constexpr S get_value(const BitRange& range) volatile { + return static_cast(bit::value::get_normalized(this->raw, range.begin, range.length)); + } + + //For easier checking + constexpr bool is(Bit bit) const { + return ComplexBitMap::is_bit_set(bit); + } + + constexpr bool is(Bit bit) const volatile { + return ComplexBitMap::is_bit_set(bit); + } + // For easier constructing constexpr __always_inline ComplexBitMap& set(const BitRange& range, T value) { this->set_value(value, range); diff --git a/include/PSX/System/IOPorts/DMA_IO.hpp b/include/PSX/System/IOPorts/DMA_IO.hpp index e179e973..88c10af2 100644 --- a/include/PSX/System/IOPorts/DMA_IO.hpp +++ b/include/PSX/System/IOPorts/DMA_IO.hpp @@ -18,9 +18,11 @@ namespace DMA { static constexpr auto CD_OneBlock = Bit(16); }; - struct __no_align SyncMode1 { - static constexpr auto BlockSize = BitRange::from_to(0, 15); - static constexpr auto BlockAmount = BitRange::from_to(16, 31); + struct __no_align SyncMode1 : public ComplexBitMap { + __io_port_inherit_complex_bit_map(SyncMode1); + + static constexpr auto BlockSize = BitRange::from_to(0, 15); + static constexpr auto BlockAmount = BitRange::from_to(16, 31); }; struct __no_align SyncMode2 { @@ -83,9 +85,9 @@ namespace DMA { }; struct __no_align Registers { - MADR adr; - BCR block_ctrl; - CHCHR channel_ctrl; + IOPort adr; + IOPort block_ctrl; + IOPort channel_ctrl; }; //0: Highest, 7: Lowest @@ -130,7 +132,7 @@ namespace DMA { __declare_io_port_global(Registers, MDECin, 0x1F801080); __declare_io_port_global(Registers, MDECout, 0x1F801090); - __declare_io_port_global(Registers, GPU, 0x1F8010A0); + __declare_io_port_global_struct(Registers, GPU, 0x1F8010A0); __declare_io_port_global(Registers, CDROM, 0x1F8010B0); __declare_io_port_global(Registers, SPU, 0x1F8010C0); __declare_io_port_global(Registers, PIO, 0x1F8010D0); diff --git a/include/PSX/System/IOPorts/GPU_IO.hpp b/include/PSX/System/IOPorts/GPU_IO.hpp index f53927aa..8c075f78 100644 --- a/include/PSX/System/IOPorts/GPU_IO.hpp +++ b/include/PSX/System/IOPorts/GPU_IO.hpp @@ -32,7 +32,7 @@ namespace GPU { enum struct DMADirection { Off = 0, - Unknown = 1, + Fifo = 1, CPU2GPU = 2, GPU2CPU = 3, }; @@ -50,6 +50,10 @@ namespace GPU { return ComplexBitMap{(0x02 << 24) | color.raw()}; } + static constexpr GP0 CPU2VRAM_Blitting() { + return ComplexBitMap{(0b101u << 29)}; + } + static constexpr GP0 TopLeftPosition(uint16_t x, uint16_t y) { return ComplexBitMap{static_cast((y << 16u) | x)}; } @@ -70,9 +74,17 @@ namespace GPU { return ComplexBitMap{0}; } + static constexpr GP1 ResetCMDBufer() { + return ComplexBitMap{construct_cmd(0x01, 0)}; + } + static constexpr GP1 SetDisplayState(DisplayState state) { return ComplexBitMap{construct_cmd(0x03, static_cast(state))}; } + + static constexpr GP1 DMADirection(DMADirection dir) { + return ComplexBitMap{construct_cmd(0x04, static_cast(dir))}; + } }; } diff --git a/include/PSX/System/IOPorts/IOPort.hpp b/include/PSX/System/IOPorts/IOPort.hpp index cb095762..427b7ced 100644 --- a/include/PSX/System/IOPorts/IOPort.hpp +++ b/include/PSX/System/IOPorts/IOPort.hpp @@ -20,6 +20,10 @@ public: constexpr volatile T& ref() { return const_cast*>(this)->value; } + + constexpr const volatile T& ref() const { + return const_cast*>(this)->value; + } }; struct __no_align ubus32_t { @@ -52,11 +56,15 @@ struct __no_align ubus32_t { }; static constexpr uintptr_t IO_Base_Mask = 0xF0000000; static constexpr uintptr_t IO_Base_Adr = 0x10000000; -#define __declare_io_port_global_raw(cv, type, name, adr) static __always_inline cv auto& name = *reinterpret_cast*>((IO_Base_Adr + (adr & ~IO_Base_Mask))) + +#define __io_port_adr(adr) (IO_Base_Adr + (adr & ~IO_Base_Mask)) +#define __declare_io_port_global_raw(cv, type, name, adr) static __always_inline cv auto& name = *reinterpret_cast*>(__io_port_adr(adr)) #define __declare_io_port_global(type, name, adr) __declare_io_port_global_raw(, type, name, adr) #define __declare_io_port_global_const(type, name, adr) __declare_io_port_global_raw(const, type, name, adr) -#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 __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 __declare_io_port_global_struct(type, name, adr) static __always_inline auto& name = *reinterpret_cast(__io_port_adr(adr)) + #define __io_port_inherit_complex_bit_map(name) \ constexpr __always_inline name() = default; \ constexpr __always_inline name(ComplexBitMap value) : ComplexBitMap(value) { \ diff --git a/src/Library/include/GPU/GPU.h b/src/Library/include/GPU/GPU.h index 6c59609b..aef04f50 100644 --- a/src/Library/include/GPU/GPU.h +++ b/src/Library/include/GPU/GPU.h @@ -1,6 +1,7 @@ #ifndef __JABYENGINE_INTERNAL_GPU_HPP__ #define __JABYENGINE_INTERNAL_GPU_HPP__ #include +#include #include namespace GPU { @@ -9,6 +10,51 @@ namespace GPU { Port::GP0.write(Port::Command::GP0::TopLeftPosition(pos.x, pos.y)); Port::GP0.write(Port::Command::GP0::WidthHeight(size.width, size.height)); } + + static void reset_cmd_buffer() { + Port::GP1.write(Port::Command::GP1::ResetCMDBufer()); + } + + static void wait_ready_for_CMD() { + while(!Port::GPUSTAT.ref().is(Port::GPUStatusRegister::GP0ReadyForCMD)); + } + + namespace DMA { + static void wait() { + while(::DMA::Port::GPU.channel_ctrl.ref().is(::DMA::Port::CHCHR::Busy)); + } + + static void end() { + reset_cmd_buffer(); + } + + namespace Receive { + static void prepare() + { + Port::GP1.write(Port::Command::GP1::DMADirection(Port::DMADirection::CPU2GPU)); + reset_cmd_buffer(); + } + + static void set_src(uintptr_t adr) { + ::DMA::Port::GPU.adr.ref().set_value(static_cast(adr), ::DMA::Port::MADR::MemoryAdr); + } + + static void set_dst(const PositionU16& position, const SizeU16& size) { + + wait_ready_for_CMD(); + Port::GP0.write(Port::Command::GP0::CPU2VRAM_Blitting()); + Port::GP0.write(Port::Command::GP0::TopLeftPosition(position.x, position.y)); + Port::GP0.write(Port::Command::GP0::WidthHeight(size.width, size.height)); + } + + static void start(uint16_t blockCount, uint16_t wordsPerBlock = 0x10) { + typedef ::DMA::Port::BCR::SyncMode1 SyncMode1; + + ::DMA::Port::GPU.block_ctrl.write(SyncMode1::with(SyncMode1::BlockSize.with(wordsPerBlock), SyncMode1::BlockAmount.with(blockCount))); + ::DMA::Port::GPU.channel_ctrl.write(::DMA::Port::CHCHR::StartGPUReceive()); + } + } + } } #endif //!__JABYENGINE_INTERNAL_GPU_HPP__ \ No newline at end of file diff --git a/src/Library/src/BootLoader/gpu_boot.cpp b/src/Library/src/BootLoader/gpu_boot.cpp index 129aa5ee..742b27c6 100644 --- a/src/Library/src/BootLoader/gpu_boot.cpp +++ b/src/Library/src/BootLoader/gpu_boot.cpp @@ -20,6 +20,18 @@ namespace GPU { void display_logo() { Display::disable(); quick_fill_fast(Color24(0x0, 0x80, 0x80), PositionU16(0, 0), SizeU16(640, 480)); + + //DMA Start + DMA::Receive::prepare(); + DMA::Receive::set_dst(PositionU16(0, 0), SizeU16(12, 12)); + DMA::Receive::set_src(reinterpret_cast(&TestSequence)); + + DMA::Receive::start(12, (12*sizeof(Color))/sizeof(uint32_t)); + + DMA::wait(); + DMA::end(); + //DMA End + Display::enable(); } diff --git a/src/Library/src/BootLoader/spu_boot.cpp b/src/Library/src/BootLoader/spu_boot.cpp index 6c07ea53..fc7772ac 100644 --- a/src/Library/src/BootLoader/spu_boot.cpp +++ b/src/Library/src/BootLoader/spu_boot.cpp @@ -95,8 +95,5 @@ namespace SPU { setup_data_transfer_control(); setup_control_register(); - - // Enable SPU DMA - DPCR.write(DPCR.read() | DMAControlRegister::SPUEnable); } } \ No newline at end of file diff --git a/src/Library/src/BootLoader/start_boot.cpp b/src/Library/src/BootLoader/start_boot.cpp index 272d4ed1..cd5a2d21 100644 --- a/src/Library/src/BootLoader/start_boot.cpp +++ b/src/Library/src/BootLoader/start_boot.cpp @@ -1,12 +1,19 @@ #include "BootLoader/boot_loader.hpp" +#include #include +using namespace DMA::Port; + namespace JabyEngine { + static void enable_DMA() { + DPCR.write(DPCR.read() | DMAControlRegister::SPUEnable | DMAControlRegister::GPUEnable); + } + void start() { printf("Hello Planschbecken\n"); + enable_DMA(); SPU::stop_voices(); - GPU::display_logo(); //Load picture here //Pause??