libpcsxcore: Add database for Lightrec hacks
authorPaul Cercueil <paul@crapouillou.net>
Sun, 10 Sep 2023 18:58:02 +0000 (20:58 +0200)
committerPaul Cercueil <paul@crapouillou.net>
Sun, 10 Sep 2023 18:58:09 +0000 (20:58 +0200)
And add entries for the infamous Formula One games.

These games do tricks with the instruction cache that are hard to
emulate properly in an interpreter, and almost impossible in a dynamic
recompiler.

Funnily enough, emulating the CPU less accurately by only invalidating
cached code on DMA writes and never on CPU writes make these games work.

These hacks will also make Lightrec generate faster code, but they are
unsafe by nature, and that's why they are conditionally enabled.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
libpcsxcore/database.c
libpcsxcore/lightrec/plugin.c

index 5edb961..ed959ea 100644 (file)
@@ -1,10 +1,16 @@
 #include "misc.h"
 #include "sio.h"
 #include "new_dynarec/new_dynarec.h"
+#include "lightrec/plugin.h"
 
 /* It's duplicated from emu_if.c */
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
 
+/* Corresponds to LIGHTREC_OPT_INV_DMA_ONLY of lightrec.h */
+#define LIGHTREC_HACK_INV_DMA_ONLY (1 << 0)
+
+u32 lightrec_hacks;
+
 static const char * const MemorycardHack_db[] =
 {
        /* Lifeforce Tenka, also known as Codename Tenka */
@@ -75,6 +81,35 @@ cycle_multiplier_overrides[] =
        { "SLES02064", 222 },
 };
 
+static const struct
+{
+       const char * const id;
+       u32 hacks;
+}
+lightrec_hacks_db[] =
+{
+       /* Formula One Arcade */
+       { "SCES03886", LIGHTREC_HACK_INV_DMA_ONLY },
+
+       /* Formula One '99 */
+       { "SLUS00870", LIGHTREC_HACK_INV_DMA_ONLY },
+       { "SCPS10101", LIGHTREC_HACK_INV_DMA_ONLY },
+       { "SCES01979", LIGHTREC_HACK_INV_DMA_ONLY },
+       { "SLES01979", LIGHTREC_HACK_INV_DMA_ONLY },
+
+       /* Formula One 2000 */
+       { "SLUS01134", LIGHTREC_HACK_INV_DMA_ONLY },
+       { "SCES02777", LIGHTREC_HACK_INV_DMA_ONLY },
+       { "SCES02778", LIGHTREC_HACK_INV_DMA_ONLY },
+       { "SCES02779", LIGHTREC_HACK_INV_DMA_ONLY },
+
+       /* Formula One 2001 */
+       { "SCES03404", LIGHTREC_HACK_INV_DMA_ONLY },
+       { "SCES03423", LIGHTREC_HACK_INV_DMA_ONLY },
+       { "SCES03424", LIGHTREC_HACK_INV_DMA_ONLY },
+       { "SCES03524", LIGHTREC_HACK_INV_DMA_ONLY },
+};
+
 /* Function for automatic patching according to GameID. */
 void Apply_Hacks_Cdrom()
 {
@@ -122,4 +157,15 @@ void Apply_Hacks_Cdrom()
                        break;
                }
        }
+
+       lightrec_hacks = 0;
+
+       for (i = 0; drc_is_lightrec() && i < ARRAY_SIZE(lightrec_hacks_db); i++) {
+               if (strcmp(CdromId, lightrec_hacks_db[i].id) == 0)
+               {
+                       lightrec_hacks = lightrec_hacks_db[i].hacks;
+                       SysPrintf("using lightrec_hacks: 0x%x\n", lightrec_hacks);
+                       break;
+               }
+       }
 }
index 7248c17..d3e4b33 100644 (file)
@@ -66,6 +66,8 @@ static bool use_lightrec_interpreter;
 static bool use_pcsx_interpreter;
 static bool block_stepping;
 
+extern u32 lightrec_hacks;
+
 enum my_cp2_opcodes {
        OP_CP2_RTPS             = 0x01,
        OP_CP2_NCLIP            = 0x06,
@@ -468,6 +470,8 @@ static int lightrec_plugin_init(void)
                        lightrec_map, ARRAY_SIZE(lightrec_map),
                        &lightrec_ops);
 
+       lightrec_set_unsafe_opt_flags(lightrec_state, lightrec_hacks);
+
        // fprintf(stderr, "M=0x%lx, P=0x%lx, R=0x%lx, H=0x%lx\n",
        //              (uintptr_t) psxM,
        //              (uintptr_t) psxP,