mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
f8841ead30
Adds a RAM-write trace hook to mednafen-PSX (SB/SH/SW handlers fire g_psxrecomp_wtrace_cb after each write), a ring buffer + TCP commands in psx-beetleoracle, and verification scripts that drive CROSS in both Beetle and recomp and diff the gate-byte writers. Conclusion (docs/CASE_A_AOT_GAP.md): the [0x7568+slot] LSB-clear writers are at RAM PCs 0x5EF4 / 0x5FA8 (and 0x4F54 sets BUSY). Recomp never dispatches any of those PCs, never executes the 0x4F00..0x4FFF or 0x5800..0x5FFF RAM windows, and never writes the gate. Selective coverage pattern (interp reaches 0xCF0/0x52xx/0x6xxx but not 0x4Fxx/0x5xxx) is install/dispatch path gap, not interpreter bug. PLAN.md:941 already names this work as a hard gate. Beetle-side modifications live inside the vendored beetle-psx/ git clone; docs/beetle_wtrace_hook.patch captures the diff so they survive a re-clone. Memcard symptom debugging stops here. Next: trace-generated AOT RAM-code manifest + recompiler ingestion (Phases B–F). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
94 lines
3.2 KiB
Diff
94 lines
3.2 KiB
Diff
diff --git a/libretro.cpp b/libretro.cpp
|
|
index 476311b..801915c 100644
|
|
--- a/libretro.cpp
|
|
+++ b/libretro.cpp
|
|
@@ -510,6 +510,9 @@ PS_SPU *PSX_SPU = NULL;
|
|
PS_CDC *PSX_CDC = NULL;
|
|
FrontIO *PSX_FIO = NULL;
|
|
|
|
+/* PSXRecomp oracle hook: NULL when no listener attached. */
|
|
+psxrecomp_wtrace_cb_t g_psxrecomp_wtrace_cb = NULL;
|
|
+
|
|
MultiAccessSizeMem<512 * 1024, uint32, false> *BIOSROM = NULL;
|
|
MultiAccessSizeMem<65536, uint32, false> *PIOMem = NULL;
|
|
MultiAccessSizeMem<2048 * 1024, uint32, false> *MainRAM = NULL;
|
|
diff --git a/mednafen/psx/cpu.cpp b/mednafen/psx/cpu.cpp
|
|
index f11e243..a8e01e2 100644
|
|
--- a/mednafen/psx/cpu.cpp
|
|
+++ b/mednafen/psx/cpu.cpp
|
|
@@ -2370,13 +2370,17 @@ pscpu_timestamp_t PS_CPU::RunReal(pscpu_timestamp_t timestamp_in)
|
|
|
|
WriteMemory<uint8>(timestamp, address, GPR[rt]);
|
|
|
|
+ /* PSXRecomp oracle hook: capture (addr, val, PC, ra, size) for wtrace. */
|
|
+ if (MDFN_UNLIKELY(g_psxrecomp_wtrace_cb))
|
|
+ g_psxrecomp_wtrace_cb(address, GPR[rt] & 0xFFu, PC, GPR[31], 1);
|
|
+
|
|
if (PGXP_GetModes() & PGXP_MODE_MEMORY)
|
|
PGXP_CPU_SB(instr, GPR[rt], address);
|
|
|
|
DO_LDS();
|
|
END_OPF;
|
|
|
|
- //
|
|
+ //
|
|
// SH - Store Halfword
|
|
//
|
|
BEGIN_OPF(SH);
|
|
@@ -2397,13 +2401,17 @@ pscpu_timestamp_t PS_CPU::RunReal(pscpu_timestamp_t timestamp_in)
|
|
else
|
|
WriteMemory<uint16>(timestamp, address, GPR[rt]);
|
|
|
|
+ /* PSXRecomp oracle hook: SH (only if no alignment exception). */
|
|
+ if (MDFN_UNLIKELY(g_psxrecomp_wtrace_cb) && !(address & 0x1))
|
|
+ g_psxrecomp_wtrace_cb(address, GPR[rt] & 0xFFFFu, PC, GPR[31], 2);
|
|
+
|
|
if (PGXP_GetModes() & PGXP_MODE_MEMORY)
|
|
PGXP_CPU_SH(instr, GPR[rt], address);
|
|
|
|
DO_LDS();
|
|
END_OPF;
|
|
|
|
- //
|
|
+ //
|
|
// SW - Store Word
|
|
//
|
|
BEGIN_OPF(SW);
|
|
@@ -2424,6 +2432,10 @@ pscpu_timestamp_t PS_CPU::RunReal(pscpu_timestamp_t timestamp_in)
|
|
else
|
|
WriteMemory<uint32>(timestamp, address, GPR[rt]);
|
|
|
|
+ /* PSXRecomp oracle hook: SW (only if no alignment exception). */
|
|
+ if (MDFN_UNLIKELY(g_psxrecomp_wtrace_cb) && !(address & 0x3))
|
|
+ g_psxrecomp_wtrace_cb(address, GPR[rt], PC, GPR[31], 4);
|
|
+
|
|
if (PGXP_GetModes() & PGXP_MODE_MEMORY)
|
|
PGXP_CPU_SW(instr, GPR[rt], address);
|
|
|
|
diff --git a/mednafen/psx/psx.h b/mednafen/psx/psx.h
|
|
index 704c0a1..93446e8 100644
|
|
--- a/mednafen/psx/psx.h
|
|
+++ b/mednafen/psx/psx.h
|
|
@@ -137,4 +137,21 @@ extern unsigned psx_gpu_overclock_shift;
|
|
extern uint8_t analog_combo[2];
|
|
extern uint8_t analog_combo_hold;
|
|
|
|
+/* PSXRecomp oracle: SIO byte trace callback.
|
|
+ * Fired by FrontIO when a complete byte exchange finishes. */
|
|
+class FrontIO;
|
|
+extern FrontIO *PSX_FIO;
|
|
+typedef void (*psxrecomp_sio_trace_cb_t)(uint8_t tx, uint8_t rx, uint16_t ctrl);
|
|
+
|
|
+/* PSXRecomp oracle: RAM write trace callback.
|
|
+ * Fired by PS_CPU::SB/SH/SW after the write completes.
|
|
+ * addr = virtual address (caller masks for physical filter)
|
|
+ * value = stored value (sized by `size`)
|
|
+ * pc = PC of the executing store instruction
|
|
+ * ra = $ra (GPR[31]) at time of store, for one frame of caller context
|
|
+ * size = 1, 2, or 4 (byte / halfword / word) */
|
|
+typedef void (*psxrecomp_wtrace_cb_t)(uint32_t addr, uint32_t value,
|
|
+ uint32_t pc, uint32_t ra, uint8_t size);
|
|
+extern psxrecomp_wtrace_cb_t g_psxrecomp_wtrace_cb;
|
|
+
|
|
#endif
|