mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 18:25:35 -04:00
e88e9a0233
Before: only sector 0 read succeeded; sector ≥1 reads aborted at 2 bytes
because mc_flag was loaded from mc_slots[].flag on every 0x81 select but
never saved back. The clear in MC_CMD lived only in the working static, so
every reselect re-loaded the stale 0x08 ("new card / changed battery") init
value, and the BIOS bailed every multi-sector op as "card was just inserted,
re-init."
After: BIOS shell memcard menu reads the full 15-sector directory area for
both slots. Real save filenames decode (e.g. "BISLPS-01234SAVE00") and per
card icons render in the bottom panes — the Phase 4 success criterion.
Also bundled this session:
- debug_server: B9D0..B9F0 added to always-on wtrace ranges; fn_dump_parse
default window scoped to 1M most-recent entries (filter scans against the
full 128M ring used to freeze the debug server thread for many seconds).
- ISSUES.md + diagnostic tools/*.py written during the audit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
156 lines
5.5 KiB
Diff
156 lines
5.5 KiB
Diff
diff --git a/libretro.cpp b/libretro.cpp
|
|
index 476311b..efd9162 100644
|
|
--- a/libretro.cpp
|
|
+++ b/libretro.cpp
|
|
@@ -510,6 +510,10 @@ PS_SPU *PSX_SPU = NULL;
|
|
PS_CDC *PSX_CDC = NULL;
|
|
FrontIO *PSX_FIO = NULL;
|
|
|
|
+/* PSXRecomp oracle hooks: NULL when no listener attached. */
|
|
+psxrecomp_wtrace_cb_t g_psxrecomp_wtrace_cb = NULL;
|
|
+psxrecomp_fntrace_cb_t g_psxrecomp_fntrace_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..ea01b8b 100644
|
|
--- a/mednafen/psx/cpu.cpp
|
|
+++ b/mednafen/psx/cpu.cpp
|
|
@@ -1557,6 +1557,12 @@ pscpu_timestamp_t PS_CPU::RunReal(pscpu_timestamp_t timestamp_in)
|
|
|
|
DO_LDS();
|
|
|
|
+ /* PSXRecomp oracle hook: J retire (caller_pc, target). */
|
|
+ if (MDFN_UNLIKELY(g_psxrecomp_fntrace_cb)) {
|
|
+ uint32_t target_addr = (PC & 0xF0000000u) | ((target << 2) & 0x0FFFFFFFu);
|
|
+ g_psxrecomp_fntrace_cb(PC, target_addr, GPR[31], GPR[4], GPR[5], 1 /* J */);
|
|
+ }
|
|
+
|
|
DO_BRANCH(true, target << 2, 0xF0000000, false, 0);
|
|
END_OPF;
|
|
|
|
@@ -1572,6 +1578,12 @@ pscpu_timestamp_t PS_CPU::RunReal(pscpu_timestamp_t timestamp_in)
|
|
|
|
DO_LDS();
|
|
|
|
+ /* PSXRecomp oracle hook: JAL retire. parent_ra captured BEFORE link. */
|
|
+ if (MDFN_UNLIKELY(g_psxrecomp_fntrace_cb)) {
|
|
+ uint32_t target_addr = (PC & 0xF0000000u) | ((target << 2) & 0x0FFFFFFFu);
|
|
+ g_psxrecomp_fntrace_cb(PC, target_addr, GPR[31], GPR[4], GPR[5], 2 /* JAL */);
|
|
+ }
|
|
+
|
|
DO_BRANCH(true, target << 2, 0xF0000000, true, 31);
|
|
END_OPF;
|
|
|
|
@@ -1590,6 +1602,10 @@ pscpu_timestamp_t PS_CPU::RunReal(pscpu_timestamp_t timestamp_in)
|
|
|
|
DO_LDS();
|
|
|
|
+ /* PSXRecomp oracle hook: JALR retire. parent_ra captured BEFORE link. */
|
|
+ if (MDFN_UNLIKELY(g_psxrecomp_fntrace_cb))
|
|
+ g_psxrecomp_fntrace_cb(PC, tmp, GPR[31], GPR[4], GPR[5], 4 /* JALR */);
|
|
+
|
|
DO_BRANCH(true, tmp, 0, true, rd);
|
|
END_OPF;
|
|
|
|
@@ -1608,6 +1624,10 @@ pscpu_timestamp_t PS_CPU::RunReal(pscpu_timestamp_t timestamp_in)
|
|
|
|
DO_LDS();
|
|
|
|
+ /* PSXRecomp oracle hook: JR retire. */
|
|
+ if (MDFN_UNLIKELY(g_psxrecomp_fntrace_cb))
|
|
+ g_psxrecomp_fntrace_cb(PC, bt, GPR[31], GPR[4], GPR[5], 3 /* JR */);
|
|
+
|
|
DO_BRANCH(true, bt, 0, false, 0);
|
|
END_OPF;
|
|
|
|
@@ -2370,13 +2390,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 +2421,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 +2452,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..e16a230 100644
|
|
--- a/mednafen/psx/psx.h
|
|
+++ b/mednafen/psx/psx.h
|
|
@@ -137,4 +137,34 @@ 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;
|
|
+
|
|
+/* PSXRecomp oracle: function-call (JAL/JALR/J/JR) trace callback.
|
|
+ * Fired by PS_CPU on every J/JAL/JR/JALR retire, BEFORE the link write.
|
|
+ * Caller filters by target_pc to keep volume bounded.
|
|
+ * caller_pc = PC of the J/JAL/JR/JALR instruction
|
|
+ * target_pc = computed branch target
|
|
+ * parent_ra = GPR[31] at time of call (parent's return address)
|
|
+ * a0, a1 = argument registers at time of call
|
|
+ * kind = 1=J, 2=JAL, 3=JR, 4=JALR */
|
|
+typedef void (*psxrecomp_fntrace_cb_t)(uint32_t caller_pc, uint32_t target_pc,
|
|
+ uint32_t parent_ra, uint32_t a0,
|
|
+ uint32_t a1, uint8_t kind);
|
|
+extern psxrecomp_fntrace_cb_t g_psxrecomp_fntrace_cb;
|
|
+
|
|
#endif
|