dma: more accurate ICR register handling
authornotaz <notasas@gmail.com>
Wed, 29 Jun 2011 16:55:38 +0000 (19:55 +0300)
committernotaz <notasas@gmail.com>
Thu, 7 Jul 2011 21:15:20 +0000 (00:15 +0300)
based on tests on ther real thing.

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

index 8b6714b..601a6ee 100644 (file)
@@ -179,8 +179,15 @@ static void io_write_imask32(u32 value)
 
 static void io_write_dma_icr32(u32 value)
 {
 
 static void io_write_dma_icr32(u32 value)
 {
-       u32 tmp = ~value & HW_DMA_ICR;
-       HW_DMA_ICR = ((tmp ^ value) & 0xffffff) ^ tmp;
+       u32 tmp = value & 0x00ff803f;
+       tmp |= (SWAPu32(HW_DMA_ICR) & ~value) & 0x7f000000;
+       if ((tmp & HW_DMA_ICR_GLOBAL_ENABLE && tmp & 0x7f000000)
+           || tmp & HW_DMA_ICR_BUS_ERROR) {
+               if (!(SWAPu32(HW_DMA_ICR) & HW_DMA_ICR_IRQ_SENT))
+                       psxHu32ref(0x1070) |= SWAP32(8);
+               tmp |= HW_DMA_ICR_IRQ_SENT;
+       }
+       HW_DMA_ICR = SWAPu32(tmp);
 }
 
 #define make_dma_func(n) \
 }
 
 #define make_dma_func(n) \
index 8069c07..54e03f6 100644 (file)
@@ -25,6 +25,9 @@
 #include "mdec.h"
 #include "cdrom.h"
 
 #include "mdec.h"
 #include "cdrom.h"
 
+//#undef PSXHW_LOG
+//#define PSXHW_LOG printf
+
 void psxHwReset() {
        if (Config.Sio) psxHu32ref(0x1070) |= SWAP32(0x80);
        if (Config.SpuIrq) psxHu32ref(0x1070) |= SWAP32(0x200);
 void psxHwReset() {
        if (Config.Sio) psxHu32ref(0x1070) |= SWAP32(0x80);
        if (Config.SpuIrq) psxHu32ref(0x1070) |= SWAP32(0x200);
@@ -658,8 +661,15 @@ void psxHwWrite32(u32 add, u32 value) {
                        PSXHW_LOG("DMA ICR 32bit write %x\n", value);
 #endif
                {
                        PSXHW_LOG("DMA ICR 32bit write %x\n", value);
 #endif
                {
-                       u32 tmp = (~value) & SWAPu32(HW_DMA_ICR);
-                       HW_DMA_ICR = SWAPu32(((tmp ^ value) & 0xffffff) ^ tmp);
+                       u32 tmp = value & 0x00ff803f;
+                       tmp |= (SWAPu32(HW_DMA_ICR) & ~value) & 0x7f000000;
+                       if ((tmp & HW_DMA_ICR_GLOBAL_ENABLE && tmp & 0x7f000000)
+                           || tmp & HW_DMA_ICR_BUS_ERROR) {
+                               if (!(SWAPu32(HW_DMA_ICR) & HW_DMA_ICR_IRQ_SENT))
+                                       psxHu32ref(0x1070) |= SWAP32(8);
+                               tmp |= HW_DMA_ICR_IRQ_SENT;
+                       }
+                       HW_DMA_ICR = SWAPu32(tmp);
                        return;
                }
 
                        return;
                }
 
index cd4e928..1d1822f 100644 (file)
@@ -57,11 +57,21 @@ extern "C" {
 #define HW_DMA_PCR   (psxHu32ref(0x10f0))
 #define HW_DMA_ICR   (psxHu32ref(0x10f4))
 
 #define HW_DMA_PCR   (psxHu32ref(0x10f0))
 #define HW_DMA_ICR   (psxHu32ref(0x10f4))
 
-#define        DMA_INTERRUPT(n) \
-       if (SWAPu32(HW_DMA_ICR) & (1 << (16 + n))) {    \
-               HW_DMA_ICR |= SWAP32(1 << (24 + n));        \
-               psxHu32ref(0x1070) |= SWAP32(8);            \
-       }
+#define HW_DMA_ICR_BUS_ERROR     (1<<15)
+#define HW_DMA_ICR_GLOBAL_ENABLE (1<<23)
+#define HW_DMA_ICR_IRQ_SENT      (1<<31)
+
+#define DMA_INTERRUPT(n) { \
+       u32 icr = SWAPu32(HW_DMA_ICR); \
+       if (icr & (1 << (16 + n))) { \
+               icr |= 1 << (24 + n); \
+               if (icr & HW_DMA_ICR_GLOBAL_ENABLE && !(icr & HW_DMA_ICR_IRQ_SENT)) { \
+                       psxHu32ref(0x1070) |= SWAP32(8); \
+                       icr |= HW_DMA_ICR_IRQ_SENT; \
+               } \
+               HW_DMA_ICR = SWAP32(icr); \
+       } \
+}
 
 void psxHwReset();
 u8 psxHwRead8(u32 add);
 
 void psxHwReset();
 u8 psxHwRead8(u32 add);