dma: more accurate ICR register handling
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / pcsxmem.c
index a526ac5..601a6ee 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) Gražvydas "notaz" Ignotas, 2010
+ * (C) Gražvydas "notaz" Ignotas, 2010-2011
  *
  * This work is licensed under the terms of GNU GPL version 2 or later.
  * See the COPYING file in the top-level directory.
@@ -15,6 +15,8 @@
 //#define memprintf printf
 #define memprintf(...)
 
+int pcsx_ram_is_ro;
+
 static void read_mem8()
 {
        memprintf("ari64_read_mem8  %08x @%08x %u\n", address, psxRegs.pc, psxRegs.cycle);
@@ -72,6 +74,10 @@ extern void ari_write_ram32();
 extern void ari_write_ram_mirror8();
 extern void ari_write_ram_mirror16();
 extern void ari_write_ram_mirror32();
+extern void ari_write_ram_mirror_ro32();
+extern void ari_read_bios8();
+extern void ari_read_bios16();
+extern void ari_read_bios32();
 extern void ari_read_io8();
 extern void ari_read_io16();
 extern void ari_read_io32();
@@ -86,6 +92,26 @@ void (*writemem[0x10000])();
 void (*writememb[0x10000])();
 void (*writememh[0x10000])();
 
+static void write_biu()
+{
+       memprintf("write_biu %08x, %08x @%08x %u\n", address, word, psxRegs.pc, psxRegs.cycle);
+
+       if (address != 0xfffe0130)
+               return;
+
+       switch (word) {
+       case 0x800: case 0x804:
+               pcsx_ram_is_ro = 1;
+               break;
+       case 0: case 0x1e988:
+               pcsx_ram_is_ro = 0;
+               break;
+       default:
+               memprintf("write_biu: unexpected val: %08x\n", word);
+               break;
+       }
+}
+
 /* IO handlers */
 static u32 io_read_sio16()
 {
@@ -134,7 +160,7 @@ static void io_write_imask16(u32 value)
 {
        psxHu16ref(0x1074) = value;
        if (psxHu16ref(0x1070) & value)
-               new_dyna_set_event(6, 1);
+               new_dyna_set_event(PSXINT_NEWDRC_CHECK, 1);
 }
 
 static void io_write_ireg32(u32 value)
@@ -148,13 +174,20 @@ static void io_write_imask32(u32 value)
 {
        psxHu32ref(0x1074) = value;
        if (psxHu32ref(0x1070) & value)
-               new_dyna_set_event(6, 1);
+               new_dyna_set_event(PSXINT_NEWDRC_CHECK, 1);
 }
 
 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) \
@@ -295,7 +328,7 @@ void new_dyna_pcsx_mem_init(void)
                writemem[i] = write_mem32;
 #if 1
                readmemb[i] = readmemh[i] = readmem[i] = read_mem_dummy;
-               readmemb[i] = readmemh[i] = readmem[i] = write_mem_dummy;
+               writememb[i] = writememh[i] = writemem[i] = write_mem_dummy;
 #endif
        }
 
@@ -310,14 +343,22 @@ void new_dyna_pcsx_mem_init(void)
                writemem[i]  = writemem [0x8000|i] = writemem [0xa000|i] = ari_write_ram_mirror32;
        }
 
+       // stupid BIOS RAM check
+       writemem[0] = ari_write_ram_mirror_ro32;
+       pcsx_ram_is_ro = 0;
+
        // RAM direct
        for (i = 0x8000; i < 0x8020; i++) {
                readmemb[i] = ari_read_ram8;
                readmemh[i] = ari_read_ram16;
                readmem[i] = ari_read_ram32;
-               writememb[i] = ari_write_ram8;
-               writememh[i] = ari_write_ram16;
-               writemem[i] = ari_write_ram32;
+       }
+
+       // BIOS and it's mirrors
+       for (i = 0x1fc0; i < 0x1fc8; i++) {
+               readmemb[i] = readmemb[0x8000|i] = readmemb[0xa000|i] = ari_read_bios8;
+               readmemh[i] = readmemh[0x8000|i] = readmemh[0xa000|i] = ari_read_bios16;
+               readmem[i]  = readmem[0x8000|i]  = readmem[0xa000|i]  = ari_read_bios32;
        }
 
        // I/O
@@ -328,7 +369,7 @@ void new_dyna_pcsx_mem_init(void)
        writememh[0x1f80] = ari_write_io16;
        writemem[0x1f80]  = ari_write_io32;
 
-       writemem[0xfffe] = write_mem32;
+       writemem[0xfffe] = write_biu;
 #endif
 
        // fill IO tables