+ 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_rom_68k(int b)
+{
+ unsigned int rs, bank, bank2;
+
+ if (Pico.m.ncart_in)
+ return;
+
+ bank = b << 20;
+ if ((Pico.m.sram_reg & SRR_MAPPED) && bank == Pico.sv.start) {
+ bank_map_handler();
+ return;
+ }
+
+ if (bank >= Pico.romsize) {
+ elprintf(EL_32X|EL_ANOMALY, "missing bank @ %06x", bank);
+ bank_map_handler();
+ return;
+ }
+
+ // 32X ROM (XXX: consider mirroring?)
+ rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
+ if (!carthw_ssf2_active) {
+ rs -= bank;
+ if (rs > 0x100000)
+ rs = 0x100000;
+ cpu68k_map_set(m68k_read8_map, 0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
+ cpu68k_map_set(m68k_read16_map, 0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
+ elprintf(EL_32X, "bank %06x-%06x -> %06x", 0x900000, 0x900000 + rs - 1, bank);
+ }
+ else {
+ bank = bank >> 19;
+ bank2 = carthw_ssf2_banks[bank + 0] << 19;
+ cpu68k_map_set(m68k_read8_map, 0x900000, 0x97ffff, Pico.rom + bank2, 0);
+ cpu68k_map_set(m68k_read16_map, 0x900000, 0x97ffff, Pico.rom + bank2, 0);
+ bank2 = carthw_ssf2_banks[bank + 1] << 19;
+ cpu68k_map_set(m68k_read8_map, 0x980000, 0x9fffff, Pico.rom + bank2, 0);
+ cpu68k_map_set(m68k_read16_map, 0x980000, 0x9fffff, Pico.rom + bank2, 0);
+ }
+}
+
+// -----------------------------------------------------------------
+// SH2
+// -----------------------------------------------------------------
+
+// read8
+static u32 sh2_read8_unmapped(u32 a, SH2 *sh2)
+{
+ elprintf_sh2(sh2, EL_32X, "unmapped r8 [%08x] %02x @%06x",
+ a, 0, sh2_pc(sh2));
+ return 0;
+}
+
+static u32 sh2_read8_cs0(u32 a, SH2 *sh2)
+{
+ u32 d = 0;
+
+ sh2_burn_cycles(sh2, 1*2);
+
+ // 0x3ffc0 is veridied
+ if ((a & 0x3ffc0) == 0x4000) {
+ d = p32x_sh2reg_read16(a, sh2);
+ goto out_16to8;
+ }
+
+ if ((a & 0x3fff0) == 0x4100) {
+ d = p32x_vdp_read16(a);
+ sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7);
+ goto out_16to8;
+ }
+
+ // TODO: mirroring?
+ if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m))
+ return Pico32xMem->sh2_rom_m.b[a ^ 1];
+ if (sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_s))
+ return Pico32xMem->sh2_rom_s.b[a ^ 1];
+
+ if ((a & 0x3fe00) == 0x4200) {
+ d = Pico32xMem->pal[(a & 0x1ff) / 2];
+ goto out_16to8;
+ }
+
+ return sh2_read8_unmapped(a, sh2);
+
+out_16to8:
+ if (a & 1)
+ d &= 0xff;
+ else
+ d >>= 8;
+
+ elprintf_sh2(sh2, EL_32X, "r8 [%08x] %02x @%06x",
+ a, d, sh2_pc(sh2));
+ return d;
+}
+
+static u32 sh2_read8_da(u32 a, SH2 *sh2)
+{
+ return sh2->data_array[(a & 0xfff) ^ 1];
+}
+
+// for ssf2
+static u32 sh2_read8_rom(u32 a, SH2 *sh2)
+{
+ u32 bank = carthw_ssf2_banks[(a >> 19) & 7] << 19;
+ return Pico.rom[(bank + (a & 0x7ffff)) ^ 1];
+}
+
+// read16
+static u32 sh2_read16_unmapped(u32 a, SH2 *sh2)
+{
+ elprintf_sh2(sh2, EL_32X, "unmapped r16 [%08x] %04x @%06x",
+ a, 0, sh2_pc(sh2));
+ return 0;
+}
+
+static u32 sh2_read16_cs0(u32 a, SH2 *sh2)
+{
+ u32 d = 0;
+
+ sh2_burn_cycles(sh2, 1*2);
+
+ 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 & 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 Pico32xMem->sh2_rom_m.w[a / 2];
+ if (sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_s))
+ return Pico32xMem->sh2_rom_s.w[a / 2];
+
+ if ((a & 0x3fe00) == 0x4200) {
+ d = Pico32xMem->pal[(a & 0x1ff) / 2];
+ goto out;
+ }
+
+ return sh2_read16_unmapped(a, sh2);
+
+out:
+ elprintf_sh2(sh2, EL_32X, "r16 [%08x] %04x @%06x",
+ a, d, sh2_pc(sh2));
+ return d;
+}
+
+static u32 sh2_read16_da(u32 a, SH2 *sh2)
+{
+ return ((u16 *)sh2->data_array)[(a & 0xfff) / 2];
+}
+
+static u32 sh2_read16_rom(u32 a, SH2 *sh2)
+{
+ u32 bank = carthw_ssf2_banks[(a >> 19) & 7] << 19;
+ return *(u16 *)(Pico.rom + bank + (a & 0x7fffe));
+}
+
+// writes
+static void REGPARM(3) sh2_write_ignore(u32 a, u32 d, SH2 *sh2)
+{
+}
+
+// write8
+static void REGPARM(3) sh2_write8_unmapped(u32 a, u32 d, SH2 *sh2)
+{
+ elprintf_sh2(sh2, EL_32X, "unmapped w8 [%08x] %02x @%06x",
+ a, d & 0xff, sh2_pc(sh2));
+}
+
+static void REGPARM(3) sh2_write8_cs0(u32 a, u32 d, SH2 *sh2)
+{
+ elprintf_sh2(sh2, EL_32X, "w8 [%08x] %02x @%06x",
+ a, d & 0xff, sh2_pc(sh2));
+
+ if (Pico32x.regs[0] & P32XS_FM) {
+ if ((a & 0x3fff0) == 0x4100) {
+ sh2->poll_addr = 0;
+ p32x_vdp_write8(a, d);
+ return;
+ }
+ }
+
+ if ((a & 0x3ffc0) == 0x4000) {
+ p32x_sh2reg_write8(a, d, sh2);
+ return;
+ }
+
+ sh2_write8_unmapped(a, d, sh2);
+}
+
+static void REGPARM(3) sh2_write8_dram0(u32 a, u32 d, SH2 *sh2)
+{
+ sh2_write8_dramN(0);
+}
+
+static void REGPARM(3) sh2_write8_dram1(u32 a, u32 d, SH2 *sh2)
+{
+ sh2_write8_dramN(1);
+}
+
+static void REGPARM(3) sh2_write8_sdram(u32 a, u32 d, SH2 *sh2)
+{
+ u32 a1 = a & 0x3ffff;
+#ifdef DRC_SH2
+ int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
+ if (t)
+ sh2_drc_wcheck_ram(a, t, sh2->is_slave);
+#endif
+ Pico32xMem->sdram[a1 ^ 1] = d;
+}
+
+static void REGPARM(3) sh2_write8_sdram_wt(u32 a, u32 d, SH2 *sh2)
+{
+ // xmen sync hack..
+ if (a < 0x26000200)
+ sh2_end_run(sh2, 32);
+
+ sh2_write8_sdram(a, d, sh2);
+}
+
+static void REGPARM(3) sh2_write8_da(u32 a, u32 d, SH2 *sh2)
+{
+ u32 a1 = a & 0xfff;
+#ifdef DRC_SH2
+ int id = sh2->is_slave;
+ int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
+ if (t)
+ sh2_drc_wcheck_da(a, t, id);
+#endif
+ sh2->data_array[a1 ^ 1] = d;
+}
+
+// write16
+static void REGPARM(3) sh2_write16_unmapped(u32 a, u32 d, SH2 *sh2)
+{
+ elprintf_sh2(sh2, EL_32X, "unmapped w16 [%08x] %04x @%06x",
+ a, d & 0xffff, sh2_pc(sh2));
+}
+
+static void REGPARM(3) sh2_write16_cs0(u32 a, u32 d, SH2 *sh2)
+{
+ if (((EL_LOGMASK & EL_PWM) || (a & 0x30) != 0x30)) // hide PWM
+ elprintf_sh2(sh2, EL_32X, "w16 [%08x] %04x @%06x",
+ a, d & 0xffff, sh2_pc(sh2));
+
+ if (Pico32x.regs[0] & P32XS_FM) {
+ if ((a & 0x3fff0) == 0x4100) {
+ sh2->poll_addr = 0;
+ p32x_vdp_write16(a, d, sh2);
+ return;
+ }
+
+ if ((a & 0x3fe00) == 0x4200) {
+ Pico32xMem->pal[(a & 0x1ff) / 2] = d;
+ Pico32x.dirty_pal = 1;
+ return;
+ }
+ }
+
+ if ((a & 0x3ffc0) == 0x4000) {
+ p32x_sh2reg_write16(a, d, sh2);
+ return;
+ }
+
+ sh2_write16_unmapped(a, d, sh2);
+}
+
+static void REGPARM(3) sh2_write16_dram0(u32 a, u32 d, SH2 *sh2)
+{
+ sh2_write16_dramN(0);
+}
+
+static void REGPARM(3) sh2_write16_dram1(u32 a, u32 d, SH2 *sh2)
+{
+ sh2_write16_dramN(1);
+}
+
+static void REGPARM(3) sh2_write16_sdram(u32 a, u32 d, SH2 *sh2)
+{
+ u32 a1 = a & 0x3ffff;
+#ifdef DRC_SH2
+ int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
+ if (t)
+ sh2_drc_wcheck_ram(a, t, sh2->is_slave);
+#endif
+ ((u16 *)Pico32xMem->sdram)[a1 / 2] = d;
+}
+
+static void REGPARM(3) sh2_write16_da(u32 a, u32 d, SH2 *sh2)
+{
+ u32 a1 = a & 0xfff;
+#ifdef DRC_SH2
+ int id = sh2->is_slave;
+ int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
+ if (t)
+ sh2_drc_wcheck_da(a, t, id);
+#endif
+ ((u16 *)sh2->data_array)[a1 / 2] = d;
+}
+
+
+typedef u32 (sh2_read_handler)(u32 a, SH2 *sh2);
+typedef void REGPARM(3) (sh2_write_handler)(u32 a, u32 d, SH2 *sh2);
+
+#define SH2MAP_ADDR2OFFS_R(a) \
+ ((u32)(a) >> SH2_READ_SHIFT)
+
+#define SH2MAP_ADDR2OFFS_W(a) \
+ ((u32)(a) >> SH2_WRITE_SHIFT)
+
+u32 REGPARM(2) p32x_sh2_read8(u32 a, SH2 *sh2)
+{
+ const sh2_memmap *sh2_map = sh2->read8_map;
+ uptr p;
+
+ sh2_map += SH2MAP_ADDR2OFFS_R(a);
+ p = sh2_map->addr;
+ if (map_flag_set(p))
+ return ((sh2_read_handler *)(p << 1))(a, sh2);
+ else
+ return *(u8 *)((p << 1) + ((a & sh2_map->mask) ^ 1));
+}
+
+u32 REGPARM(2) p32x_sh2_read16(u32 a, SH2 *sh2)
+{
+ const sh2_memmap *sh2_map = sh2->read16_map;
+ uptr p;
+
+ sh2_map += SH2MAP_ADDR2OFFS_R(a);
+ p = sh2_map->addr;
+ if (map_flag_set(p))
+ return ((sh2_read_handler *)(p << 1))(a, sh2);
+ else
+ return *(u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
+}
+
+u32 REGPARM(2) p32x_sh2_read32(u32 a, SH2 *sh2)
+{
+ const sh2_memmap *sh2_map = sh2->read16_map;
+ sh2_read_handler *handler;
+ u32 offs;
+ uptr p;
+
+ offs = SH2MAP_ADDR2OFFS_R(a);
+ sh2_map += offs;
+ p = sh2_map->addr;
+ if (!map_flag_set(p)) {
+ // XXX: maybe 32bit access instead with ror?
+ u16 *pd = (u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
+ return (pd[0] << 16) | pd[1];
+ }
+
+ if (offs == SH2MAP_ADDR2OFFS_R(0xffffc000))
+ return sh2_peripheral_read32(a, sh2);
+
+ handler = (sh2_read_handler *)(p << 1);
+ return (handler(a, sh2) << 16) | handler(a + 2, sh2);
+}
+
+void REGPARM(3) p32x_sh2_write8(u32 a, u32 d, SH2 *sh2)
+{
+ const void **sh2_wmap = sh2->write8_tab;
+ sh2_write_handler *wh;
+
+ wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
+ wh(a, d, sh2);
+}
+
+void REGPARM(3) p32x_sh2_write16(u32 a, u32 d, SH2 *sh2)
+{
+ const void **sh2_wmap = sh2->write16_tab;
+ sh2_write_handler *wh;
+
+ wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
+ wh(a, d, sh2);
+}
+
+void REGPARM(3) p32x_sh2_write32(u32 a, u32 d, SH2 *sh2)
+{
+ const void **sh2_wmap = sh2->write16_tab;
+ sh2_write_handler *wh;
+ u32 offs;
+
+ offs = SH2MAP_ADDR2OFFS_W(a);
+
+ if (offs == SH2MAP_ADDR2OFFS_W(0xffffc000)) {
+ sh2_peripheral_write32(a, d, sh2);
+ return;
+ }
+
+ wh = sh2_wmap[offs];
+ wh(a, d >> 16, sh2);
+ wh(a + 2, d, sh2);