mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-28 02:56:36 -04:00
3b6986827e
A region-truncated final block that runs off the end of its function fell off the C function body when no in-image fallthrough function existed: the entry-switch prologue had consumed cpu->pc to 0, so the dispatcher returned "handled" with pc==0 and the top-level trampoline read it as "program ended". Witnessed live in the WipEout 3 ntsc120full8 static bake: the 0xD5000 region variant's block_800D7FC0 ends at the region edge (continuation 0x800D8004 lies outside the image); the moment CD streaming loaded content matching that variant's identity ranges the dispatcher routed 0x800D7FC0 into the truncated block and the run died — the deterministic "execution completed, PC=0" at ~10 s into boot, ~frame 1221, byte-for-byte reproducible. Both code_generator tail sites (plain functions and alias hosts) now emit `cpu->pc = <end+4>; return;` when the last live block runs off the image edge — the CPS tail-transfer the full_function_emitter already emits for in-image fallthroughs. The dispatcher routes the published continuation to whoever owns it (a neighboring region variant, AOT text, or the interpreter). Faithful and class-level: no per-game anything. Diagnosis chain that cornered it (all landed as permanent tooling): - pc0 escape journal site 14 (trampoline top-level exit) named the last dispatched target: 0x800D7FC0. - site 15 (dirty-dispatch handled-with-pc0 tripwire, now journaled with a route tag) proved the producer was route 3 = the static overlay dispatcher, first occurrence, not in exception context. - Return-shape census of every candidate variant body showed no return-with-pc==0 path — forcing the discovery that the dispatch case for 0x800D7FC0 routes FIRST to the 0xD5000 variant, whose truncated tail block falls off the end. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>