diff --git a/include/PICA/gpu.hpp b/include/PICA/gpu.hpp index db61a0f9..7a80c633 100644 --- a/include/PICA/gpu.hpp +++ b/include/PICA/gpu.hpp @@ -47,9 +47,11 @@ class GPU { u32 index = paddr - PhysicalAddrs::FCRAM; return (T*)&fcram[index]; - } - else { - Helpers::panic("[PICA] Pointer to unimplemented paddr %08X", paddr); + } else if (paddr >= PhysicalAddrs::VRAM && paddr <= PhysicalAddrs::VRAMEnd) { + u32 index = paddr - PhysicalAddrs::VRAM; + return (T*)&vram[index]; + } else [[unlikely]] { + Helpers::panic("[GPU] Tried to access unknown physical address: %08X", paddr); } } @@ -102,6 +104,7 @@ public: void getGraphicsContext(); // Set up the graphics context for rendering void display(); // Display the screen contents onto our window + void fireDMA(u32 dest, u32 source, u32 size); void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control); void reset(); diff --git a/include/memory.hpp b/include/memory.hpp index a15adf0c..a3815534 100644 --- a/include/memory.hpp +++ b/include/memory.hpp @@ -11,6 +11,8 @@ namespace PhysicalAddrs { enum : u32 { + VRAM = 0x18000000, + VRAMEnd = VRAM + 0x005FFFFF, FCRAM = 0x20000000, FCRAMEnd = FCRAM + 0x07FFFFFF }; @@ -38,6 +40,7 @@ namespace VirtualAddrs { VramStart = 0x1F000000, VramSize = 0x00600000, + FcramTotalSize = 128_MB, DSPMemStart = 0x1FF00000 }; } diff --git a/src/core/PICA/gpu.cpp b/src/core/PICA/gpu.cpp index 7c109ad9..3e02280f 100644 --- a/src/core/PICA/gpu.cpp +++ b/src/core/PICA/gpu.cpp @@ -158,4 +158,25 @@ void GPU::drawArrays() { }; const auto shape = primTypes[primType]; drawVertices(shape, vertices, vertexCount); +} + +void GPU::fireDMA(u32 dest, u32 source, u32 size) { + printf("[GPU] DMA of %08X bytes from %08X to %08X\n", size, source, dest); + constexpr u32 vramStart = VirtualAddrs::VramStart; + constexpr u32 vramSize = VirtualAddrs::VramSize; + + const u32 fcramStart = mem.getLinearHeapVaddr(); + constexpr u32 fcramSize = VirtualAddrs::FcramTotalSize; + + if (dest - vramStart >= vramSize || size > (vramSize - (dest - vramStart))) [[unlikely]] { + Helpers::panic("GPU DMA does not target VRAM"); + } + + if (source - fcramStart >= fcramSize || size > (fcramSize - (dest - fcramStart))) { + Helpers::panic("GPU DMA does not have FCRAM as its source"); + } + + // Valid, optimized FCRAM->VRAM DMA. TODO: Is VRAM->VRAM DMA allowed? + u8* fcram = mem.getFCRAM(); + std::memcpy(&vram[dest - vramStart], &fcram[source - fcramStart], size); } \ No newline at end of file diff --git a/src/core/services/gsp_gpu.cpp b/src/core/services/gsp_gpu.cpp index 61c970ac..910f7aa9 100644 --- a/src/core/services/gsp_gpu.cpp +++ b/src/core/services/gsp_gpu.cpp @@ -278,7 +278,8 @@ void GPUService::triggerDMARequest(u32* cmd) { u32 size = cmd[3]; bool flush = cmd[7] == 1; - log("GSP::GPU::TriggerDMARequest (source = %08X, dest = %08X, size = %08X) (Unimplemented)\n", source, dest, size); + log("GSP::GPU::TriggerDMARequest (source = %08X, dest = %08X, size = %08X)\n", source, dest, size); + gpu.fireDMA(dest, source, size); requestInterrupt(GPUInterrupt::DMA); }