Merge branch 'dev'
[picodrive.git] / pico / 32x / memory.c
index 5d882e3..fd902dd 100644 (file)
@@ -187,7 +187,7 @@ static u32 p32x_reg_read16(u32 a)
 #else
   if ((a & 0x30) == 0x20) {
     static u32 dr2 = 0;
-    unsigned int cycles = SekCyclesDoneT();
+    unsigned int cycles = SekCyclesDone();
     int comreg = 1 << (a & 0x0f) / 2;
 
     // evil X-Men proto polls in a dbra loop and expects it to expire..
@@ -195,8 +195,10 @@ static u32 p32x_reg_read16(u32 a)
       m68k_poll.cnt = 0;
     dr2 = SekDar(2);
 
-    if (cycles - msh2.m68krcycles_done > 500)
+    if (cycles - msh2.m68krcycles_done > 244
+        || (Pico32x.comm_dirty_68k & comreg))
       p32x_sync_sh2s(cycles);
+
     if (Pico32x.comm_dirty_sh2 & comreg)
       Pico32x.comm_dirty_sh2 &= ~comreg;
     else if (m68k_poll_detect(a, cycles, P32XF_68KCPOLL)) {
@@ -209,14 +211,14 @@ static u32 p32x_reg_read16(u32 a)
 #endif
 
   if (a == 2) { // INTM, INTS
-    unsigned int cycles = SekCyclesDoneT();
+    unsigned int cycles = SekCyclesDone();
     if (cycles - msh2.m68krcycles_done > 64)
       p32x_sync_sh2s(cycles);
-    return ((Pico32x.sh2irqi[0] & P32XI_CMD) >> 4) | ((Pico32x.sh2irqi[1] & P32XI_CMD) >> 3);
+    goto out;
   }
 
   if ((a & 0x30) == 0x30)
-    return p32x_pwm_read16(a, NULL, SekCyclesDoneT());
+    return p32x_pwm_read16(a, NULL, SekCyclesDone());
 
 out:
   return Pico32x.regs[a / 2];
@@ -239,7 +241,7 @@ static void dreq0_write(u16 *r, u32 d)
       r[6 / 2] &= ~P32XS_68S;
 
     if ((Pico32x.dmac0_fifo_ptr & 3) == 0) {
-      p32x_sync_sh2s(SekCyclesDoneT());
+      p32x_sync_sh2s(SekCyclesDone());
       p32x_dreq0_trigger();
     }
   }
@@ -269,21 +271,11 @@ static void p32x_reg_write8(u32 a, u32 d)
     case 0x02: // ignored, always 0
       return;
     case 0x03: // irq ctl
-      if ((d & 1) != !!(Pico32x.sh2irqi[0] & P32XI_CMD)) {
-        p32x_sync_sh2s(SekCyclesDoneT());
-        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)) {
-        p32x_sync_sh2s(SekCyclesDoneT());
-        if (d & 2)
-          Pico32x.sh2irqi[1] |= P32XI_CMD;
-        else
-          Pico32x.sh2irqi[1] &= ~P32XI_CMD;
-        p32x_update_irls(NULL, SekCyclesDoneT2());
+      if ((d ^ r[0x02 / 2]) & 3) {
+        int cycles = SekCyclesDone();
+        p32x_sync_sh2s(cycles);
+        r[0x02 / 2] = d & 3;
+        p32x_update_cmd_irq(NULL, cycles);
       }
       return;
     case 0x04: // ignored, always 0
@@ -360,12 +352,15 @@ static void p32x_reg_write8(u32 a, u32 d)
     case 0x31: // PWM control
       REG8IN16(r, a) &= ~0x0f;
       REG8IN16(r, a) |= d & 0x0f;
+      d = r[0x30 / 2];
       goto pwm_write;
     case 0x32: // PWM cycle
       REG8IN16(r, a) = d & 0x0f;
+      d = r[0x32 / 2];
       goto pwm_write;
     case 0x33:
       REG8IN16(r, a) = d;
+      d = r[0x32 / 2];
       goto pwm_write;
     // PWM pulse regs.. Only writes to odd address send a value
     // to FIFO; reads are 0 (except status bits)
@@ -377,8 +372,8 @@ static void p32x_reg_write8(u32 a, u32 d)
     case 0x35:
     case 0x37:
     case 0x39:
-      d = (REG8IN16(r, a) << 8) | (d & 0xff);
-      REG8IN16(r, a) = 0;
+      d = (REG8IN16(r, a ^ 1) << 8) | (d & 0xff);
+      REG8IN16(r, a ^ 1) = 0;
       goto pwm_write;
     case 0x3a: // ignored, always 0
     case 0x3b:
@@ -388,12 +383,12 @@ static void p32x_reg_write8(u32 a, u32 d)
     case 0x3f:
       return;
     pwm_write:
-      p32x_pwm_write16(a & ~1, r[a / 2], NULL, SekCyclesDoneT());
+      p32x_pwm_write16(a & ~1, d, NULL, SekCyclesDone());
       return;
   }
 
   if ((a & 0x30) == 0x20) {
-    int cycles = SekCyclesDoneT();
+    int cycles = SekCyclesDone();
     int comreg;
     
     if (REG8IN16(r, a) == d)
@@ -450,11 +445,16 @@ static void p32x_reg_write16(u32 a, u32 d)
     case 0x1a: // TV + mystery bit
       r[a / 2] = d & 0x0101;
       return;
+    case 0x30: // PWM control
+      d = (r[a / 2] & ~0x0f) | (d & 0x0f);
+      r[a / 2] = d;
+      p32x_pwm_write16(a, d, NULL, SekCyclesDone());
+      return;
   }
 
   // comm port
   if ((a & 0x30) == 0x20) {
-    int cycles = SekCyclesDoneT();
+    int cycles = SekCyclesDone();
     int comreg;
     
     if (r[a / 2] == d)
@@ -475,7 +475,7 @@ static void p32x_reg_write16(u32 a, u32 d)
   }
   // PWM
   else if ((a & 0x30) == 0x30) {
-    p32x_pwm_write16(a, d, NULL, SekCyclesDoneT());
+    p32x_pwm_write16(a, d, NULL, SekCyclesDone());
     return;
   }
 
@@ -571,7 +571,7 @@ static void p32x_vdp_write16(u32 a, u32 d, SH2 *sh2)
 static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2)
 {
   u16 *r = Pico32x.regs;
-  a &= 0xfe; // ?
+  a &= 0x3e;
 
   switch (a) {
     case 0x00: // adapter/irq ctl
@@ -619,32 +619,42 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2)
     return p32x_pwm_read16(a, sh2, sh2_cycles_done_m68k(sh2));
 
   elprintf_sh2(sh2, EL_32X|EL_ANOMALY, 
-    "unhandled sysreg r16 [%06x] @%06x", a, SekPc);
+    "unhandled sysreg r16 [%02x] @%08x", a, sh2_pc(sh2));
   return 0;
 }
 
 static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2)
 {
-  a &= 0xff;
+  u16 *r = Pico32x.regs;
+  u32 old;
 
+  a &= 0x3f;
   sh2->poll_addr = 0;
 
   switch (a) {
-    case 0: // FM
-      Pico32x.regs[0] &= ~P32XS_FM;
-      Pico32x.regs[0] |= (d << 8) & P32XS_FM;
+    case 0x00: // FM
+      r[0] &= ~P32XS_FM;
+      r[0] |= (d << 8) & P32XS_FM;
       return;
-    case 1: // HEN/irq masks
+    case 0x01: // HEN/irq masks
+      old = Pico32x.sh2irq_mask[sh2->is_slave];
+      if ((d ^ old) & 1)
+        p32x_pwm_sync_to_sh2(sh2);
+
       Pico32x.sh2irq_mask[sh2->is_slave] = d & 0x0f;
       Pico32x.sh2_regs[0] &= ~0x80;
       Pico32x.sh2_regs[0] |= d & 0x80;
-      if (d & 1)
+
+      if ((d ^ old) & 1)
         p32x_pwm_schedule_sh2(sh2);
-      if (d & 4)
+      if ((old ^ d) & 2)
+        p32x_update_cmd_irq(sh2, 0);
+      if ((old ^ d) & 4)
         p32x_schedule_hint(sh2, 0); 
-      p32x_update_irls(sh2, 0);
       return;
-    case 5: // H count
+    case 0x04: // ignored?
+      return;
+    case 0x05: // H count
       d &= 0xff;
       if (Pico32x.sh2_regs[4 / 2] != d) {
         Pico32x.sh2_regs[4 / 2] = d;
@@ -653,15 +663,53 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2)
         sh2_end_run(sh2, 4);
       }
       return;
+    case 0x30:
+      REG8IN16(r, a) = d & 0x0f;
+      d = r[0x30 / 2];
+      goto pwm_write;
+    case 0x31: // PWM control
+      REG8IN16(r, a) = d & 0x8f;
+      d = r[0x30 / 2];
+      goto pwm_write;
+    case 0x32: // PWM cycle
+      REG8IN16(r, a) = d & 0x0f;
+      d = r[0x32 / 2];
+      goto pwm_write;
+    case 0x33:
+      REG8IN16(r, a) = d;
+      d = r[0x32 / 2];
+      goto pwm_write;
+    // PWM pulse regs.. Only writes to odd address send a value
+    // to FIFO; reads are 0 (except status bits)
+    case 0x34:
+    case 0x36:
+    case 0x38:
+      REG8IN16(r, a) = d;
+      return;
+    case 0x35:
+    case 0x37:
+    case 0x39:
+      d = (REG8IN16(r, a ^ 1) << 8) | (d & 0xff);
+      REG8IN16(r, a ^ 1) = 0;
+      goto pwm_write;
+    case 0x3a: // ignored, always 0?
+    case 0x3b:
+    case 0x3c:
+    case 0x3d:
+    case 0x3e:
+    case 0x3f:
+      return;
+    pwm_write:
+      p32x_pwm_write16(a & ~1, d, sh2, 0);
+      return;
   }
 
   if ((a & 0x30) == 0x20) {
-    u8 *r8 = (u8 *)Pico32x.regs;
     int comreg;
-    if (r8[a ^ 1] == d)
+    if (REG8IN16(r, a) == d)
       return;
 
-    r8[a ^ 1] = d;
+    REG8IN16(r, a) = d;
     p32x_m68k_poll_event(P32XF_68KCPOLL);
     p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL,
       sh2_cycles_done_m68k(sh2));
@@ -669,11 +717,14 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2)
     Pico32x.comm_dirty_sh2 |= comreg;
     return;
   }
+
+  elprintf(EL_32X|EL_ANOMALY,
+    "unhandled sysreg w8  [%02x] %02x @%08x", a, d, sh2_pc(sh2));
 }
 
 static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2)
 {
-  a &= 0xfe;
+  a &= 0x3e;
 
   sh2->poll_addr = 0;
 
@@ -702,12 +753,22 @@ static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2)
       Pico32x.regs[0] &= ~P32XS_FM;
       Pico32x.regs[0] |= d & P32XS_FM;
       break;
-    case 0x14: Pico32x.sh2irqs &= ~P32XI_VRES; goto irls;
-    case 0x16: Pico32x.sh2irqs &= ~P32XI_VINT; goto irls;
-    case 0x18: Pico32x.sh2irqs &= ~P32XI_HINT; goto irls;
-    case 0x1a: Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_CMD; goto irls;
+    case 0x14:
+      Pico32x.sh2irqs &= ~P32XI_VRES;
+      goto irls;
+    case 0x16:
+      Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_VINT;
+      goto irls;
+    case 0x18:
+      Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_HINT;
+      goto irls;
+    case 0x1a:
+      Pico32x.regs[2 / 2] &= ~(1 << sh2->is_slave);
+      p32x_update_cmd_irq(sh2, 0);
+      return;
     case 0x1c:
-      Pico32x.sh2irqs &= ~P32XI_PWM;
+      p32x_pwm_sync_to_sh2(sh2);
+      Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_PWM;
       p32x_pwm_schedule_sh2(sh2);
       goto irls;
   }
@@ -809,6 +870,8 @@ static void PicoWrite8_32x_on(u32 a, u32 d)
 
   if ((a & 0xfc00) != 0x5000) {
     PicoWrite8_io(a, d);
+    if (a == 0xa130f1)
+      bank_switch(Pico32x.regs[4 / 2]);
     return;
   }
 
@@ -842,6 +905,8 @@ static void PicoWrite16_32x_on(u32 a, u32 d)
 
   if ((a & 0xfc00) != 0x5000) {
     PicoWrite16_io(a, d);
+    if (a == 0xa130f0)
+      bank_switch(Pico32x.regs[4 / 2]);
     return;
   }
 
@@ -1007,7 +1072,8 @@ static void PicoWrite8_hint(u32 a, u32 d)
     return;
   }
 
-  elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
+  elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x",
+    a, d & 0xff, SekPc);
 }
 
 static void PicoWrite16_hint(u32 a, u32 d)
@@ -1017,7 +1083,64 @@ static void PicoWrite16_hint(u32 a, u32 d)
     return;
   }
 
-  elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
+  elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x",
+    a, d & 0xffff, SekPc);
+}
+
+// normally not writable, but somebody could make a RAM cart
+static void PicoWrite8_cart(u32 a, u32 d)
+{
+  elprintf(EL_UIO, "m68k w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
+
+  a &= 0xfffff;
+  m68k_write8(a, d);
+}
+
+static void PicoWrite16_cart(u32 a, u32 d)
+{
+  elprintf(EL_UIO, "m68k w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
+
+  a &= 0xfffff;
+  m68k_write16(a, d);
+}
+
+// same with bank, but save ram is sometimes here
+static u32 PicoRead8_bank(u32 a)
+{
+  a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
+  return m68k_read8(a);
+}
+
+static u32 PicoRead16_bank(u32 a)
+{
+  a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
+  return m68k_read16(a);
+}
+
+static void PicoWrite8_bank(u32 a, u32 d)
+{
+  if (!(Pico.m.sram_reg & SRR_MAPPED))
+    elprintf(EL_UIO, "m68k w8  [%06x]   %02x @%06x",
+      a, d & 0xff, SekPc);
+
+  a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
+  m68k_write8(a, d);
+}
+
+static void PicoWrite16_bank(u32 a, u32 d)
+{
+  if (!(Pico.m.sram_reg & SRR_MAPPED))
+    elprintf(EL_UIO, "m68k w16 [%06x] %04x @%06x",
+      a, d & 0xffff, SekPc);
+
+  a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
+  m68k_write16(a, d);
+}
+
+static void bank_map_handler(void)
+{
+  cpu68k_map_set(m68k_read8_map,   0x900000, 0x9fffff, PicoRead8_bank, 1);
+  cpu68k_map_set(m68k_read16_map,  0x900000, 0x9fffff, PicoRead16_bank, 1);
 }
 
 static void bank_switch(int b)
@@ -1025,8 +1148,14 @@ static void bank_switch(int b)
   unsigned int rs, bank;
 
   bank = b << 20;
+  if ((Pico.m.sram_reg & SRR_MAPPED) && bank == SRam.start) {
+    bank_map_handler();
+    return;
+  }
+
   if (bank >= Pico.romsize) {
     elprintf(EL_32X|EL_ANOMALY, "missing bank @ %06x", bank);
+    bank_map_handler();
     return;
   }
 
@@ -1065,13 +1194,13 @@ static u32 sh2_read8_cs0(u32 a, SH2 *sh2)
 
   sh2_burn_cycles(sh2, 1*2);
 
-  // 0x3ff00 is veridied
-  if ((a & 0x3ff00) == 0x4000) {
+  // 0x3ffc0 is veridied
+  if ((a & 0x3ffc0) == 0x4000) {
     d = p32x_sh2reg_read16(a, sh2);
     goto out_16to8;
   }
 
-  if ((a & 0x3ff00) == 0x4100) {
+  if ((a & 0x3fff0) == 0x4100) {
     d = p32x_vdp_read16(a);
     sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7);
     goto out_16to8;
@@ -1079,9 +1208,9 @@ static u32 sh2_read8_cs0(u32 a, SH2 *sh2)
 
   // TODO: mirroring?
   if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m))
-    return Pico32xMem->sh2_rom_m[a ^ 1];
+    return Pico32xMem->sh2_rom_m.b[a ^ 1];
   if (sh2->is_slave  && a < sizeof(Pico32xMem->sh2_rom_s))
-    return Pico32xMem->sh2_rom_s[a ^ 1];
+    return Pico32xMem->sh2_rom_s.b[a ^ 1];
 
   if ((a & 0x3fe00) == 0x4200) {
     d = Pico32xMem->pal[(a & 0x1ff) / 2];
@@ -1120,23 +1249,23 @@ static u32 sh2_read16_cs0(u32 a, SH2 *sh2)
 
   sh2_burn_cycles(sh2, 1*2);
 
-  if ((a & 0x3ff00) == 0x4000) {
+  if ((a & 0x3ffc0) == 0x4000) {
     d = p32x_sh2reg_read16(a, sh2);
     if (!(EL_LOGMASK & EL_PWM) && (a & 0x30) == 0x30) // hide PWM
       return d;
     goto out;
   }
 
-  if ((a & 0x3ff00) == 0x4100) {
+  if ((a & 0x3fff0) == 0x4100) {
     d = p32x_vdp_read16(a);
     sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7);
     goto out;
   }
 
   if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m))
-    return *(u16 *)(Pico32xMem->sh2_rom_m + a);
+    return Pico32xMem->sh2_rom_m.w[a / 2];
   if (sh2->is_slave  && a < sizeof(Pico32xMem->sh2_rom_s))
-    return *(u16 *)(Pico32xMem->sh2_rom_s + a);
+    return Pico32xMem->sh2_rom_s.w[a / 2];
 
   if ((a & 0x3fe00) == 0x4200) {
     d = Pico32xMem->pal[(a & 0x1ff) / 2];
@@ -1174,14 +1303,14 @@ static void REGPARM(3) sh2_write8_cs0(u32 a, u32 d, SH2 *sh2)
     a, d & 0xff, sh2_pc(sh2));
 
   if (Pico32x.regs[0] & P32XS_FM) {
-    if ((a & 0x3ff00) == 0x4100) {
+    if ((a & 0x3fff0) == 0x4100) {
       sh2->poll_addr = 0;
       p32x_vdp_write8(a, d);
       return;
     }
   }
 
-  if ((a & 0x3ff00) == 0x4000) {
+  if ((a & 0x3ffc0) == 0x4000) {
     p32x_sh2reg_write8(a, d, sh2);
     return;
   }
@@ -1245,7 +1374,7 @@ static void REGPARM(3) sh2_write16_cs0(u32 a, u32 d, SH2 *sh2)
       a, d & 0xffff, sh2_pc(sh2));
 
   if (Pico32x.regs[0] & P32XS_FM) {
-    if ((a & 0x3ff00) == 0x4100) {
+    if ((a & 0x3fff0) == 0x4100) {
       sh2->poll_addr = 0;
       p32x_vdp_write16(a, d, sh2);
       return;
@@ -1258,7 +1387,7 @@ static void REGPARM(3) sh2_write16_cs0(u32 a, u32 d, SH2 *sh2)
     }
   }
 
-  if ((a & 0x3ff00) == 0x4000) {
+  if ((a & 0x3ffc0) == 0x4000) {
     p32x_sh2reg_write16(a, d, sh2);
     return;
   }
@@ -1351,7 +1480,7 @@ u32 REGPARM(2) p32x_sh2_read32(u32 a, SH2 *sh2)
     return (pd[0] << 16) | pd[1];
   }
 
-  if (offs == 0x1f)
+  if (offs == SH2MAP_ADDR2OFFS_R(0xffffc000))
     return sh2_peripheral_read32(a, sh2);
 
   handler = (sh2_read_handler *)(p << 1);
@@ -1396,6 +1525,21 @@ void REGPARM(3) p32x_sh2_write32(u32 a, u32 d, SH2 *sh2)
 
 // -----------------------------------------------------------------
 
+static void z80_md_bank_write_32x(unsigned int a, unsigned char d)
+{
+  unsigned int addr68k;
+
+  addr68k = Pico.m.z80_bank68k << 15;
+  addr68k += a & 0x7fff;
+  if ((addr68k & 0xfff000) == 0xa15000)
+    Pico32x.emu_flags |= P32XF_Z80_32X_IO;
+
+  elprintf(EL_Z80BNK, "z80->68k w8 [%06x] %02x", addr68k, d);
+  m68k_write8(addr68k, d);
+}
+
+// -----------------------------------------------------------------
+
 static const u16 msh2_code[] = {
   // trap instructions
   0xaffe, // bra <self>
@@ -1475,17 +1619,17 @@ static void get_bios(void)
   // MSH2
   if (p32x_bios_m != NULL) {
     elprintf(EL_STATUS|EL_32X, "32x: using supplied master SH2 BIOS");
-    Byteswap(Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m));
+    Byteswap(&Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m));
   }
   else {
-    pl = (u32 *)Pico32xMem->sh2_rom_m;
+    pl = (u32 *)&Pico32xMem->sh2_rom_m;
 
     // fill exception vector table to our trap address
     for (i = 0; i < 128; i++)
       pl[i] = HWSWAP(0x200);
 
     // startup code
-    memcpy(Pico32xMem->sh2_rom_m + 0x200, msh2_code, sizeof(msh2_code));
+    memcpy(&Pico32xMem->sh2_rom_m.b[0x200], msh2_code, sizeof(msh2_code));
 
     // reset SP
     pl[1] = pl[3] = HWSWAP(0x6040000);
@@ -1496,17 +1640,17 @@ static void get_bios(void)
   // SSH2
   if (p32x_bios_s != NULL) {
     elprintf(EL_STATUS|EL_32X, "32x: using supplied slave SH2 BIOS");
-    Byteswap(Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s));
+    Byteswap(&Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s));
   }
   else {
-    pl = (u32 *)Pico32xMem->sh2_rom_s;
+    pl = (u32 *)&Pico32xMem->sh2_rom_s;
 
     // fill exception vector table to our trap address
     for (i = 0; i < 128; i++)
       pl[i] = HWSWAP(0x200);
 
     // startup code
-    memcpy(Pico32xMem->sh2_rom_s + 0x200, ssh2_code, sizeof(ssh2_code));
+    memcpy(&Pico32xMem->sh2_rom_s.b[0x200], ssh2_code, sizeof(ssh2_code));
 
     // reset SP
     pl[1] = pl[3] = HWSWAP(0x603f800);
@@ -1572,6 +1716,8 @@ void PicoMemSetup32x(void)
     rs = 0x80000;
   cpu68k_map_set(m68k_read8_map,   0x880000, 0x880000 + rs - 1, Pico.rom, 0);
   cpu68k_map_set(m68k_read16_map,  0x880000, 0x880000 + rs - 1, Pico.rom, 0);
+  cpu68k_map_set(m68k_write8_map,  0x880000, 0x880000 + rs - 1, PicoWrite8_cart, 1);
+  cpu68k_map_set(m68k_write16_map, 0x880000, 0x880000 + rs - 1, PicoWrite16_cart, 1);
 #ifdef EMU_F68K
   // setup FAME fetchmap
   PicoCpuFM68k.Fetch[0] = (unsigned long)Pico32xMem->m68k_rom;
@@ -1581,6 +1727,8 @@ void PicoMemSetup32x(void)
 
   // 32X ROM (banked)
   bank_switch(0);
+  cpu68k_map_set(m68k_write8_map,  0x900000, 0x9fffff, PicoWrite8_bank, 1);
+  cpu68k_map_set(m68k_write16_map, 0x900000, 0x9fffff, PicoWrite16_bank, 1);
 
   // SYS regs
   cpu68k_map_set(m68k_read8_map,   0xa10000, 0xa1ffff, PicoRead8_32x_on, 1);
@@ -1648,6 +1796,9 @@ void PicoMemSetup32x(void)
 
   sh2_drc_mem_setup(&msh2);
   sh2_drc_mem_setup(&ssh2);
+
+  // z80 hack
+  z80_map_set(z80_write_map, 0x8000, 0xffff, z80_md_bank_write_32x, 1);
 }
 
 void Pico32xMemStateLoaded(void)