dma: handle PCR writes
authornotaz <notasas@gmail.com>
Sat, 22 Feb 2025 23:10:09 +0000 (01:10 +0200)
committernotaz <notasas@gmail.com>
Sun, 23 Feb 2025 00:15:04 +0000 (02:15 +0200)
no commercial game needs this, so was missing
notaz/pcsx_rearmed#354

libpcsxcore/new_dynarec/pcsxmem.c
libpcsxcore/psxdma.c
libpcsxcore/psxhw.c
libpcsxcore/psxhw.h

index 151fb4b..67a6531 100644 (file)
@@ -267,7 +267,6 @@ make_forcew32_func(10a0)
 make_forcew32_func(10b0)
 make_forcew32_func(10c0)
 make_forcew32_func(10e0)
-make_forcew32_func(10f0)
 
 void new_dyna_pcsx_mem_load_state(void)
 {
@@ -421,6 +420,7 @@ void new_dyna_pcsx_mem_init(void)
        map_item(&mem_iowtab[IOMEM32(0x10cc)], psxHwWriteChcr4, 1);
        map_item(&mem_iowtab[IOMEM32(0x10e8)], psxHwWriteChcr6, 1);
        map_item(&mem_iowtab[IOMEM32(0x10ec)], psxHwWriteChcr6, 1);
+       map_item(&mem_iowtab[IOMEM32(0x10f0)], psxHwWriteDmaPcr32, 1);
        map_item(&mem_iowtab[IOMEM32(0x10f4)], psxHwWriteDmaIcr32, 1);
        map_item(&mem_iowtab[IOMEM32(0x1100)], io_rcnt_write_count0, 1);
        map_item(&mem_iowtab[IOMEM32(0x1104)], io_rcnt_write_mode0, 1);
@@ -463,7 +463,7 @@ void new_dyna_pcsx_mem_init(void)
        map_item(&mem_iowtab[IOMEM16(0x10e0)], io_write_force32_10e0, 1);
        map_item(&mem_iowtab[IOMEM16(0x10e8)], psxHwWriteChcr6, 1);
        map_item(&mem_iowtab[IOMEM16(0x10ec)], psxHwWriteChcr6, 1);
-       map_item(&mem_iowtab[IOMEM16(0x10f0)], io_write_force32_10f0, 1);
+       map_item(&mem_iowtab[IOMEM16(0x10f0)], psxHwWriteDmaPcr32, 1);
        map_item(&mem_iowtab[IOMEM16(0x10f4)], psxHwWriteDmaIcr32, 1);
        map_item(&mem_iowtab[IOMEM16(0x1100)], io_rcnt_write_count0, 1);
        map_item(&mem_iowtab[IOMEM16(0x1104)], io_rcnt_write_mode0, 1);
index e17cba3..6dc5d63 100644 (file)
@@ -143,7 +143,7 @@ void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU
        madr &= ~3;
        switch (chcr) {
                case 0x01000200: // vram2mem
-                       PSXDMA_LOG("*** DMA2 GPU - vram2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
+                       PSXDMA_LOG("*** DMA2 GPU - vram2mem *** %x addr = %x size = %x\n", chcr, madr, bcr);
                        ptr = getDmaRam(madr, &words_max);
                        if (ptr == INVALID_PTR) {
                                log_unhandled("bad dma2 madr %x\n", madr);
@@ -167,7 +167,7 @@ void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU
                        return;
 
                case 0x01000201: // mem2vram
-                       PSXDMA_LOG("*** DMA 2 - GPU mem2vram *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
+                       PSXDMA_LOG("*** DMA 2 - GPU mem2vram *** %x addr = %x size = %x\n", chcr, madr, bcr);
                        words = words_left = (bcr >> 16) * (bcr & 0xffff);
                        while (words_left > 0) {
                                ptr = getDmaRam(madr, &words_max);
@@ -190,7 +190,7 @@ void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU
                        return;
 
                case 0x01000401: // dma chain
-                       PSXDMA_LOG("*** DMA 2 - GPU dma chain *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
+                       PSXDMA_LOG("*** DMA 2 - GPU dma chain *** %x addr = %x size = %x\n", chcr, madr, bcr);
                        // when not emulating walking progress, end immediately
                        // (some games abort the dma and read madr so break out of that logic)
                        madr_next = 0xffffff;
index b96db97..c487b02 100644 (file)
@@ -26,6 +26,7 @@
 #include "mdec.h"
 #include "cdrom.h"
 #include "gpu.h"
+#include "../include/compiler_features.h"
 
 void psxHwReset() {
        memset(psxH, 0, 0x10000);
@@ -74,7 +75,7 @@ void psxHwWriteChcr##n(u32 value) \
        if ((value ^ old) & 0x01000000) { \
                if (!(value & 0x01000000)) \
                        abort_func; \
-               else if (SWAPu32(HW_DMA_PCR) & (8u << (n * 4))) \
+               else if (HW_DMA_PCR & SWAPu32(8u << (n * 4))) \
                        psxDma##n(SWAPu32(HW_DMA##n##_MADR), SWAPu32(HW_DMA##n##_BCR), value); \
        } \
 }
@@ -86,6 +87,27 @@ make_dma_func(3,)
 make_dma_func(4,)
 make_dma_func(6,)
 
+void psxHwWriteDmaPcr32(u32 value)
+{
+       // todo: can this also pause/stop live dma?
+       u32 on = (SWAPu32(HW_DMA_PCR) ^ value) & value & 0x08888888;
+       u32 chcr;
+       HW_DMA_PCR = SWAPu32(value);
+       if (likely(!on))
+               return;
+       #define DO(n) \
+       chcr = SWAPu32(HW_DMA##n##_CHCR); \
+       if ((on & (8u << 4*n)) && (chcr & 0x01000000)) \
+               psxDma##n(SWAPu32(HW_DMA##n##_MADR), SWAPu32(HW_DMA##n##_BCR), chcr)
+       DO(0);
+       DO(1);
+       DO(2);
+       DO(3);
+       DO(4);
+       DO(6);
+       #undef DO
+}
+
 void psxHwWriteDmaIcr32(u32 value)
 {
        u32 tmp = value & 0x00ff803f;
@@ -336,6 +358,7 @@ void psxHwWrite16(u32 add, u32 value) {
        case 0x10cc: psxHwWriteChcr4(value); return;
        case 0x10e8: // DMA6 chcr (OT clear)
        case 0x10ec: psxHwWriteChcr6(value); return;
+       case 0x10f0: psxHwWriteDmaPcr32(value); return;
        case 0x10f4: psxHwWriteDmaIcr32(value); return;
 
        // forced write32 with no immediate effect:
@@ -348,7 +371,6 @@ void psxHwWrite16(u32 add, u32 value) {
        case 0x10c0:
        case 0x10d0:
        case 0x10e0:
-       case 0x10f0:
                psxHu32ref(add) = SWAPu32(value);
                return;
 
@@ -394,6 +416,7 @@ void psxHwWrite32(u32 add, u32 value) {
        case 0x10cc: psxHwWriteChcr4(value); return;
        case 0x10e8: // DMA6 chcr (OT clear)
        case 0x10ec: psxHwWriteChcr6(value); return;
+       case 0x10f0: psxHwWriteDmaPcr32(value); return;
        case 0x10f4: psxHwWriteDmaIcr32(value); return;
 
        case 0x1810: GPU_writeData(value); return;
index d55936b..501dd7a 100644 (file)
@@ -91,6 +91,7 @@ void psxHwWriteChcr2(u32 value);
 void psxHwWriteChcr3(u32 value);
 void psxHwWriteChcr4(u32 value);
 void psxHwWriteChcr6(u32 value);
+void psxHwWriteDmaPcr32(u32 value);
 void psxHwWriteDmaIcr32(u32 value);
 void psxHwWriteGpuSR(u32 value);
 u32  psxHwReadGpuSR(void);