mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-27 18:52:11 -04:00
a0ae0c4f6a
psx_call_contract and the BIOS dispatch loop compared a return PC with the call's link physically ((a ^ b) & 0x1FFFFFFF). A PC carries a segment, and the link a call writes is in the segment of the body that made it (docs/SEGMENT_AWARE_CODE.md §5.5). A guest that returns to another segment's alias of the call site did not return to that body, so letting the suspended C continuation run there would execute it with the wrong segment's PCs. §5.5 deferred these checks to this PR so one call contract has one rule. All five are exact now: - psx_call_contract (cpu_state.h): the bail-resolve PC and the $ra check; - the emitted BIOS dispatch loop: the return boundary, the bail resolve, the wild-return test and the exception-stack straddle. Since B routes every baked link through runtime_pc() and C/D compile each body for the segment it runs in, a legitimate return always matches in full. The ledger gains the exact-return-contract guard: it compiles psx_call_contract and checks that another segment's alias starts a bail and resolves nothing, and that the emitted OpenBIOS dispatch has the four exact checks and no masked one. OpenBIOS and SCPH-1001 dispatch C change in those four lines; game C does not change. cpu_state.h is in the codegen hash. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>