32x, hacks for roms with caching related problems
authorkub <derkub@gmail.com>
Tue, 20 Dec 2022 21:32:24 +0000 (21:32 +0000)
committerkub <derkub@gmail.com>
Tue, 20 Dec 2022 21:32:24 +0000 (21:32 +0000)
cpu/sh2/compiler.c
pico/32x/memory.c
pico/32x/sh2soc.c
pico/cart.c
pico/carthw.cfg
pico/pico.h
pico/pico_int.h

index 360fcd0..76f6cd6 100644 (file)
@@ -537,12 +537,6 @@ void REGPARM(1) (*sh2_drc_restore_sr)(SH2 *sh2);
 #define MF_POLLING  0x20       // include polling check in read
 
 // address space stuff
-static int dr_is_rom(u32 a)
-{
-  // tweak for WWF Raw which writes data to some high ROM addresses
-  return (a & 0xc6000000) == 0x02000000 && (a & 0x3f0000) < 0x3e0000;
-}
-
 static int dr_ctx_get_mem_ptr(SH2 *sh2, u32 a, u32 *mask)
 {
   void *memptr;
@@ -2698,7 +2692,7 @@ static int emit_get_rom_data(SH2 *sh2, sh2_reg_e r, s32 offs, int size, u32 *val
   if (gconst_get(r, &a)) {
     a += offs;
     // check if rom is memory mapped (not bank switched), and address is in rom
-    if (dr_is_rom(a) && p32x_sh2_get_mem_ptr(a, &mask, sh2) == sh2->p_rom) {
+    if (p32x_sh2_mem_is_rom(a, sh2) && p32x_sh2_get_mem_ptr(a, &mask, sh2) == sh2->p_rom) {
       switch (size & MF_SIZEMASK) {
       case 0:   *val = (s8)p32x_sh2_read8(a, sh2s);   break;  // 8
       case 1:   *val = (s16)p32x_sh2_read16(a, sh2s); break;  // 16
@@ -3830,14 +3824,12 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
     case OP_LOAD_POOL:
 #if PROPAGATE_CONSTANTS
       if ((opd->imm && opd->imm >= base_pc && opd->imm < end_literals) ||
-          dr_is_rom(opd->imm))
+          p32x_sh2_mem_is_rom(opd->imm, sh2))
       {
         if (opd->size == 2)
           u = FETCH32(opd->imm);
         else
           u = (s16)FETCH_OP(opd->imm);
-        // tweak for Blackthorne: avoid stack overwriting
-        if (GET_Rn() == SHR_SP && u == 0x0603f800) u = 0x0603f900;
         gconst_new(GET_Rn(), u);
       }
       else
index 7a61e89..62c3122 100644 (file)
@@ -816,7 +816,7 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2)
       Pico32x.sh2_regs[0] &= ~0x80;
       Pico32x.sh2_regs[0] |= d & 0x80;
 
-      if ((d ^ old) & 1)
+      if ((old ^ d) & 1)
         p32x_pwm_schedule_sh2(sh2);
       if ((old ^ d) & 2)
         p32x_update_cmd_irq(sh2, 0);
@@ -1776,7 +1776,7 @@ static void REGPARM(3) sh2_write16_rom(u32 a, u32 d, SH2 *sh2)
   // Presumably the write goes to the CPU cache and is read back from there,
   // but it would be extremely costly to emulate cache behaviour. Just allow
   // writes to that region, hoping that the original ROM values are never used.
-  if ((a1 & 0x3e0000) == 0x3e0000)
+  if ((a1 & 0x3e0000) == 0x3e0000 && (PicoIn.quirks & PQUIRK_WWFRAW_HACK))
     ((u16 *)sh2->p_rom)[a1 / 2] = d;
   else
     sh2_write16_unmapped(a, d, sh2);
@@ -1951,6 +1951,16 @@ void *p32x_sh2_get_mem_ptr(u32 a, u32 *mask, SH2 *sh2)
   return ret;
 }
 
+int p32x_sh2_mem_is_rom(u32 a, SH2 *sh2)
+{
+  if ((a & 0xc6000000) == 0x02000000) {
+    // ROM, but mind tweak for WWF Raw
+    return !(PicoIn.quirks & PQUIRK_WWFRAW_HACK) || (a & 0x3f0000) < 0x3e0000;
+  }
+
+  return 0;
+}
+
 int p32x_sh2_memcpy(u32 dst, u32 src, int count, int size, SH2 *sh2)
 {
   u32 mask;
index f8bb4e7..0336b87 100644 (file)
@@ -137,15 +137,7 @@ static void dmac_memcpy(struct dma_chan *chan, SH2 *sh2)
 
   if (!up || chan->tcr < 4)
     return;
-#if MARS_CHECK_HACK
-  // XXX Mars Check Program copies 32K longwords (128KB) from a 64KB buffer in
-  // ROM or DRAM to SDRAM in 4-longword mode, overwriting an SDRAM comm area in
-  // turn, which crashes the test on emulators without CPU cache emulation.
-  // This may be a bug in Mars Check. As a kludge limit the transfer to 64KB,
-  // which is what the check program test uses for checking the result.
-  // A better way would clearly be to have a mechanism to patch the ROM...
-  if (size == 3 && chan->tcr == 32768 && chan->dar == 0x06020000) size = 1;
-#endif
+
   if (size == 3) size = 2;  // 4-word xfer mode still counts in words
   // XXX check TCR being a multiple of 4 in 4-word xfer mode?
   // XXX check alignment of sar/dar, generating a bus error if unaligned?
index 8f9b620..dad850b 100644 (file)
@@ -1201,6 +1201,12 @@ static void parse_carthw(const char *carthw_cfg, int *fill_sram,
         Pico.sv.flags &= ~SRF_EEPROM;\r
       else if (strcmp(p, "filled_sram") == 0)\r
         *fill_sram = 1;\r
+      else if (strcmp(p, "wwfraw_hack") == 0)\r
+        PicoIn.quirks |= PQUIRK_WWFRAW_HACK;\r
+      else if (strcmp(p, "blackthorne_hack") == 0)\r
+        PicoIn.quirks |= PQUIRK_BLACKTHORNE_HACK;\r
+      else if (strcmp(p, "marscheck_hack") == 0)\r
+        PicoIn.quirks |= PQUIRK_MARSCHECK_HACK;\r
       else if (strcmp(p, "force_6btn") == 0)\r
         PicoIn.quirks |= PQUIRK_FORCE_6BTN;\r
       else {\r
@@ -1335,6 +1341,45 @@ static void PicoCartDetect(const char *carthw_cfg)
   // Unusual region 'code'\r
   if (rom_strcmp(0x1f0, "EUROPE") == 0 || rom_strcmp(0x1f0, "Europe") == 0)\r
     *(u32 *) (Pico.rom + 0x1f0) = CPU_LE4(0x20204520);\r
+\r
+  // tweak for Blackthorne: master SH2 overwrites stack of slave SH2 being in PWM\r
+  // interrupt. On real hardware, nothing happens since slave fetches the values\r
+  // it has written from its cache, but picodrive doesn't emulate caching.\r
+  // move master memory area down by 0x100 bytes.\r
+  // XXX replace this abominable hack. It might cause other problems in the game!\r
+  if (PicoIn.quirks & PQUIRK_BLACKTHORNE_HACK) {\r
+    int i;\r
+    unsigned a = 0;\r
+    for (i = 0; i < Pico.romsize; i += 4) {\r
+      unsigned v = CPU_BE2(*(u32 *) (Pico.rom + i));\r
+      if (a && v == a + 0x400) { // patch if 2 pointers with offset 0x400 are found\r
+        printf("auto-patching @%06x: %08x->%08x\n", i, v, v - 0x100);\r
+        *(u32 *) (Pico.rom + i) = CPU_BE2(v - 0x100);\r
+      }\r
+      // detect a pointer into the incriminating area\r
+      a = 0;\r
+      if (v >> 12 == 0x0603f000 >> 12 && !(v & 3))\r
+        a = v;\r
+    }\r
+  }\r
+\r
+  // tweak for Mars Check Program: copies 32K longwords (128KB) from a 64KB buffer\r
+  // in ROM or DRAM to SDRAM with DMA in 4-longword mode, overwriting an SDRAM comm\r
+  // area in turn. This crashes the test on emulators without CPU cache emulation.\r
+  // This may be a bug in Mars Check, since it's only checking for the 64KB result.\r
+  // Patch the DMA transfers so that they transfer only 64KB.\r
+  if (PicoIn.quirks & PQUIRK_MARSCHECK_HACK) {\r
+    int i;\r
+    unsigned a = 0;\r
+    for (i = 0; i < Pico.romsize; i += 4) {\r
+      unsigned v = CPU_BE2(*(u32 *) (Pico.rom + i));\r
+      if (a == 0xffffff8c && v == 0x5ee1) { // patch if 4-long xfer written to CHCR\r
+        printf("auto-patching @%06x: %08x->%08x\n", i, v, v & ~0x800);\r
+        *(u32 *) (Pico.rom + i) = CPU_BE2(v & ~0x800); // change to half-sized xfer\r
+      }\r
+      a = v;\r
+    }\r
+  }\r
 }\r
 \r
 static void PicoCartDetectMS(void)\r
index 964efb4..ef50794 100644 (file)
@@ -52,6 +52,30 @@ hw = pico
 check_str = 0x100, "IMA IKUNO"
 hw = pico
 
+# X-Men proto
+[X-Men (prototype) - 32X]
+check_str = 0x120, "32X SAMPLE PROGRAM"
+check_str = 0x32b74c, "Bishop Level"
+prop = force_6btn
+
+# WWF Raw
+[WWF Raw - 32X]
+check_str = 0x100, "SEGA 32X"
+check_str = 0x150, "WWF RAW"
+prop = wwfraw_hack # reads back data written to high ROM adresses from cache
+
+# Blackthorne
+[Blackthorne - 32X]
+check_str = 0x100, "SEGA 32X"
+check_str = 0x120, "BLACKTHORNE"
+prop = blackthorne_hack # reads back data overwritten by 2nd CPU from cache
+
+# Mars check program
+[Mars Check - 32X]
+check_str = 0x100, "SEGA"
+check_str = 0x150, "MARS CHECK PROGRAM"
+prop = marscheck_hack # reads back data overwritten by DMA from cache
+
 # sram emulation triggers some protection for this one
 [Puggsy]
 check_str = 0x120, "PUGGSY"
@@ -71,12 +95,6 @@ prop = filled_sram
 check_str = 0x150, "  HardBall III"
 sram_range = 0x200000,0x20ffff
 
-# X-Men proto
-[X-Men (prototype)]
-check_str = 0x150, "32X SAMPLE PROGRAM"
-check_str = 0x32b74c, "Bishop Level"
-prop = force_6btn
-
 # The SSF2 mapper
 [Mega Everdrive]
 check_str = 0x100, "SEGA SSF"
index cb4ebb5..6882faa 100644 (file)
@@ -89,7 +89,10 @@ extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
 #define PHWS_SMS    2\r
 #define PHWS_SG     3\r
 \r
-#define PQUIRK_FORCE_6BTN   (1<<0)\r
+#define PQUIRK_FORCE_6BTN       (1<<0)\r
+#define PQUIRK_BLACKTHORNE_HACK (1<<1)\r
+#define PQUIRK_WWFRAW_HACK      (1<<2)\r
+#define PQUIRK_MARSCHECK_HACK   (1<<3)\r
 \r
 // the emulator is configured and some status is reported\r
 // through this global state (not saved in savestates)\r
index 0406dd5..55fb5ae 100644 (file)
@@ -1017,6 +1017,7 @@ u32 REGPARM(3) p32x_sh2_poll_memory8(u32 a, u32 d, SH2 *sh2);
 u32 REGPARM(3) p32x_sh2_poll_memory16(u32 a, u32 d, SH2 *sh2);\r
 u32 REGPARM(3) p32x_sh2_poll_memory32(u32 a, u32 d, SH2 *sh2);\r
 void *p32x_sh2_get_mem_ptr(u32 a, u32 *mask, SH2 *sh2);\r
+int p32x_sh2_mem_is_rom(u32 a, SH2 *sh2);\r
 void p32x_sh2_poll_detect(u32 a, SH2 *sh2, u32 flags, int maxcnt);\r
 void p32x_sh2_poll_event(SH2 *sh2, u32 flags, u32 m68k_cycles);\r
 int p32x_sh2_memcpy(u32 dst, u32 src, int count, int size, SH2 *sh2);\r