Commit Graph

6 Commits

Author SHA1 Message Date
Matt Stanley 0cbd435349 Merge pull request #271 from Alexbeav/pr/stale-static-guards
codegen+runtime: stop executing stale static code when a game overlays its own text
2026-08-30 20:52:11 -07:00
Alexandros Mandravillis 4d9060a54e codegen: stale-static guard on inter-piece host transfers
A game that overlays its own text at runtime (CMR2 streams transform-
loop variants with patched projection constants over the boot EXE)
kept executing the stale static translation through inter-piece host
transfers: dispatch validates an entry's emitted ranges, but split
function pieces chain via direct host calls (fallthrough to split
piece / next function, legacy non-CPS split branch/jump/continuation
transfers, non-CPS direct jal) with no revalidation. A clean entry
piece falls through natively into a stale sibling whose live bytes an
overlay replaced -- the CMR2 attract/gameplay wedge corruption
(first divergence: one ADDI immediate, screen-center 160 static vs
256 live, at 0x800199D4, retirement 3,203,596,289, frame ~11963).

Emit at every such transfer:
  if (!psx_game_text_native_ok(T)) { cpu->pc = T; return; }
publishing the PC and unwinding to the trampoline, whose dispatch
takes the sanctioned dirty-RAM-interpreter fallback over live bytes.
The non-CPS direct jal falls back to call_by_address instead.

dirty_ram_text_native_ok_ranges_from gains a page-clean fast path
(skip the memcmp when no touched page is guard-modified or runtime-
dirty) so the guards are near-free on pristine pages.

cosim.py: print full A/B cpu dumps in cpudiff mode (values, not just
diffs).
2026-08-30 18:14:32 +03:00
Alexandros Mandravillis 4aebb349da cosim: key checkpoints on retired-instruction count, not guest cycles
The cycle-keyed design hashed+parked at the first cosim_instr boundary
AFTER the stride cycle was crossed; the two backends can reach that
crossing at different retirement positions, so the oracle compared
different architectural states (observed as a +5-cycle park skew and
phantom CPU-register divergences mid-CPS).

Checkpoints are now taken inside cosim_instr, keyed on the retirement
count itself (a branch and its delay slot retire as one event in both
backends). Checkpoint k = state after k*stride retirements in BOTH
instances by construction. The guest-cycle clock stays inside the state
hash, so real cycle-accounting drift is still detected -- now pinned to
an exact instruction window instead of corrupting the alignment.

cosim.py: stride/--max/--start-cycle now in retirement units; the cycle
skew warning is now reported as a real timing divergence. launch() gives
instance B its own exe (the mods root is exe-dir-relative, so a shared
exe races on mods/state.toml publish regardless of cwd separation) and
refuses a stale COSIM_CWD_B exe.

Gates on CMR2 (SLUS-01222): compiled/compiled and interp/interp both
clean over 100M retirements with identical cross-pair chains; injected
1-bit RAM fault detected at the next checkpoint.
2026-08-30 18:14:24 +03:00
Matthew Stanley 60801820fd cleanup: genericize hardcoded dev-machine paths in tracked docs/tools
Replace absolute F:/C: paths with repo-relative (../TombaRecomp, bios/, beetle-psx/)
or placeholders (<desktop>/<psxref>/<nesrecomp>/<psxrecomp-v4>) across accuracy docs,
WIDESCREEN/SHADOW/RECURSION_BUG/config_schema/ISSUES/README, and tools/*.py|.ps1.
Removed a personal C:\Users\Matthew\Desktop path (ISSUES.md). Left CLAUDE.md/PLAN.md
sibling-project + version-history paths intact (intentional layout documentation).
2026-07-06 11:51:36 -07:00
Matthew Stanley c78eeb72cc overlay ABI v9: route faithful-timing runtime fns through OverlayCallbacks
The cycle-accuracy emitter emits calls to 12 timing runtime functions
(psx_cyc_load_*, psx_icache_fetch, psx_muldiv_*, psx_gte_*, psx_slice_block,
...) + debug_server_cyc_observe + g_debug_last_store_pc. Overlay DLLs never
got these symbols, so every overlay failed to link -> 0 native shards ->
100% interpreter (unplayable). Fix (option A): expose the 12 via the overlay
callback ABI.

- overlay_api.h: +12 timing callbacks in OverlayCallbacks, ABI 8 -> 9.
- overlay_loader.c: populate the 12; add warn_on_cgtag_mismatch() (loud
  warning when shards exist under the wrong cg-hash).
- compile_overlays.py: 12 preamble forwarders + local g_debug_last_store_pc
  + -DPSX_NO_DEBUG_TOOLS.
- cosim.c/main.cpp: input-cosim setpad + held pad (deterministic input).
- cosim.py: env-overridable COSIM_EXE/CWD/GAME.

KNOWN REGRESSION (patched on a follow-up branch): Tomba pause menu (triangle)
wedges. Root-caused: an IRQ taken mid-block resumes at the function entry
leader instead of the interrupted PC, re-zeroing the menu's VSync wait
counter (scratchpad 0x1F8001E8) every frame so it never reaches its target.
Not the scheduler (LLE reproduces) and not timing math -- interrupt-resume
re-entry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 14:31:59 -07:00
Matthew Stanley 553d9933d1 fix mmx6 timing divergences with cosim oracle 2026-07-01 09:28:50 -07:00