32x: fix some more timing problems
[picodrive.git] / pico / 32x / memory.c
index 2c62e11..45c192d 100644 (file)
@@ -213,7 +213,7 @@ static u32 p32x_reg_read16(u32 a)
   }
 
   if ((a & 0x30) == 0x30)
-    return p32x_pwm_read16(a, SekCyclesDoneT());
+    return p32x_pwm_read16(a, NULL, SekCyclesDoneT());
 
 out:
   return Pico32x.regs[a / 2];
@@ -237,15 +237,21 @@ static void p32x_reg_write8(u32 a, u32 d)
       r[0] = (r[0] & ~P32XS_nRES) | (d & P32XS_nRES);
       return;
     case 3: // irq ctl
-      if ((d & 1) && !(Pico32x.sh2irqi[0] & P32XI_CMD)) {
+      if ((d & 1) != !!(Pico32x.sh2irqi[0] & P32XI_CMD)) {
         p32x_sync_sh2s(SekCyclesDoneT());
-        Pico32x.sh2irqi[0] |= P32XI_CMD;
-        p32x_update_irls(NULL);
+        if (d & 1)
+          Pico32x.sh2irqi[0] |= P32XI_CMD;
+        else
+          Pico32x.sh2irqi[0] &= ~P32XI_CMD;
+        p32x_update_irls(NULL, SekCyclesDoneT2());
       }
-      if ((d & 2) && !(Pico32x.sh2irqi[1] & P32XI_CMD)) {
+      if (!!(d & 2) != !!(Pico32x.sh2irqi[1] & P32XI_CMD)) {
         p32x_sync_sh2s(SekCyclesDoneT());
-        Pico32x.sh2irqi[1] |= P32XI_CMD;
-        p32x_update_irls(NULL);
+        if (d & 2)
+          Pico32x.sh2irqi[1] |= P32XI_CMD;
+        else
+          Pico32x.sh2irqi[1] &= ~P32XI_CMD;
+        p32x_update_irls(NULL, SekCyclesDoneT2());
       }
       return;
     case 5: // bank
@@ -346,7 +352,7 @@ static void p32x_reg_write16(u32 a, u32 d)
   }
   // PWM
   else if ((a & 0x30) == 0x30) {
-    p32x_pwm_write16(a, d, SekCyclesDoneT());
+    p32x_pwm_write16(a, d, NULL, SekCyclesDoneT());
     return;
   }
 
@@ -456,7 +462,7 @@ static u32 p32x_sh2reg_read16(u32 a, int cpuid)
     return r[a / 2];
   }
   if ((a & 0x30) == 0x30) {
-    return p32x_pwm_read16(a, sh2_cycles_done_m68k(&sh2s[cpuid]));
+    return p32x_pwm_read16(a, &sh2s[cpuid], sh2_cycles_done_m68k(&sh2s[cpuid]));
   }
 
   return 0;
@@ -481,7 +487,7 @@ static void p32x_sh2reg_write8(u32 a, u32 d, int cpuid)
       Pico32x.sh2_regs[0] |= d & 0x80;
       if (d & 1)
         p32x_pwm_schedule_sh2(&sh2s[cpuid]);
-      p32x_update_irls(&sh2s[cpuid]);
+      p32x_update_irls(&sh2s[cpuid], 0);
       return;
     case 5: // H count
       d &= 0xff;
@@ -532,7 +538,7 @@ static void p32x_sh2reg_write16(u32 a, u32 d, int cpuid)
   }
   // PWM
   else if ((a & 0x30) == 0x30) {
-    p32x_pwm_write16(a, d, sh2_cycles_done_m68k(&sh2s[cpuid]));
+    p32x_pwm_write16(a, d, &sh2s[cpuid], sh2_cycles_done_m68k(&sh2s[cpuid]));
     return;
   }
 
@@ -555,11 +561,11 @@ static void p32x_sh2reg_write16(u32 a, u32 d, int cpuid)
   return;
 
 irls:
-  p32x_update_irls(&sh2s[cpuid]);
+  p32x_update_irls(&sh2s[cpuid], 0);
 }
 
 // ------------------------------------------------------------------
-// 32x handlers
+// 32x 68k handlers
 
 // after ADEN
 static u32 PicoRead8_32x_on(u32 a)
@@ -798,6 +804,45 @@ void PicoWrite16_32x(u32 a, u32 d)
   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
 }
 
+/* quirk: in both normal and overwrite areas only nonzero values go through */
+#define sh2_write8_dramN(n) \
+  if ((d & 0xff) != 0) { \
+    u8 *dram = (u8 *)Pico32xMem->dram[n]; \
+    dram[(a & 0x1ffff) ^ 1] = d; \
+  }
+
+static void m68k_write8_dram0_ow(u32 a, u32 d)
+{
+  sh2_write8_dramN(0);
+}
+
+static void m68k_write8_dram1_ow(u32 a, u32 d)
+{
+  sh2_write8_dramN(1);
+}
+
+#define sh2_write16_dramN(n, ret) \
+  u16 *pd = &Pico32xMem->dram[n][(a & 0x1ffff) / 2]; \
+  if (!(a & 0x20000)) { \
+    *pd = d; \
+    return ret; \
+  } \
+  /* overwrite */ \
+  if (!(d & 0xff00)) d |= *pd & 0xff00; \
+  if (!(d & 0x00ff)) d |= *pd & 0x00ff; \
+  *pd = d; \
+  return ret
+
+static void m68k_write16_dram0_ow(u32 a, u32 d)
+{
+  sh2_write16_dramN(0,);
+}
+
+static void m68k_write16_dram1_ow(u32 a, u32 d)
+{
+  sh2_write16_dramN(1,);
+}
+
 // -----------------------------------------------------------------
 
 // hint vector is writeable
@@ -987,22 +1032,16 @@ static int REGPARM(3) sh2_write8_cs0(u32 a, u32 d, int id)
   return sh2_write8_unmapped(a, d, id);
 }
 
-/* quirk: in both normal and overwrite areas only nonzero values go through */
-#define sh2_write8_dramN(n) \
-  if ((d & 0xff) != 0) { \
-    u8 *dram = (u8 *)Pico32xMem->dram[n]; \
-    dram[(a & 0x1ffff) ^ 1] = d; \
-  } \
-  return 0;
-
 static int REGPARM(3) sh2_write8_dram0(u32 a, u32 d, int id)
 {
   sh2_write8_dramN(0);
+  return 0;
 }
 
 static int REGPARM(3) sh2_write8_dram1(u32 a, u32 d, int id)
 {
   sh2_write8_dramN(1);
+  return 0;
 }
 
 static int REGPARM(3) sh2_write8_sdram(u32 a, u32 d, int id)
@@ -1065,26 +1104,14 @@ static int REGPARM(3) sh2_write16_cs0(u32 a, u32 d, int id)
   return sh2_write16_unmapped(a, d, id);
 }
 
-#define sh2_write16_dramN(n) \
-  u16 *pd = &Pico32xMem->dram[n][(a & 0x1ffff) / 2]; \
-  if (!(a & 0x20000)) { \
-    *pd = d; \
-    return 0; \
-  } \
-  /* overwrite */ \
-  if (!(d & 0xff00)) d |= *pd & 0xff00; \
-  if (!(d & 0x00ff)) d |= *pd & 0x00ff; \
-  *pd = d; \
-  return 0
-
 static int REGPARM(3) sh2_write16_dram0(u32 a, u32 d, int id)
 {
-  sh2_write16_dramN(0);
+  sh2_write16_dramN(0, 0);
 }
 
 static int REGPARM(3) sh2_write16_dram1(u32 a, u32 d, int id)
 {
-  sh2_write16_dramN(1);
+  sh2_write16_dramN(1, 0);
 }
 
 static int REGPARM(3) sh2_write16_sdram(u32 a, u32 d, int id)
@@ -1340,8 +1367,12 @@ void Pico32xSwapDRAM(int b)
 {
   cpu68k_map_set(m68k_read8_map,   0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
   cpu68k_map_set(m68k_read16_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
-  cpu68k_map_set(m68k_write8_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
-  cpu68k_map_set(m68k_write16_map, 0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
+  cpu68k_map_set(m68k_read8_map,   0x860000, 0x87ffff, Pico32xMem->dram[b], 0);
+  cpu68k_map_set(m68k_read16_map,  0x860000, 0x87ffff, Pico32xMem->dram[b], 0);
+  cpu68k_map_set(m68k_write8_map,  0x840000, 0x87ffff,
+                 b ? m68k_write8_dram1_ow : m68k_write8_dram0_ow, 1);
+  cpu68k_map_set(m68k_write16_map, 0x840000, 0x87ffff,
+                 b ? m68k_write16_dram1_ow : m68k_write16_dram0_ow, 1);
 
   // SH2
   sh2_read8_map[2].addr   = sh2_read8_map[6].addr   =