mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
1a0213ec5e
The kernel's inline RestoreState (at BFC1094C inside the exception handler func_00000C80) restored all registers and did `jr $ra`, but the generated `return;` went back to psx_check_interrupts instead of dispatching to the restored $ra (0xBFC421D8 — the VSync callback loop). Then psx_check_interrupts overwrote all GPRs from the pre-exception save, wiping RestoreState's changes. VSync counter was permanently stuck at 0. Fix has three parts: 1. runtime/src/interrupts.c: Add psx_restore_state_escape() which longjmps with code 2 (vs code 1 for ReturnFromException). psx_check_interrupts now loops: code 2 re-dispatches to cpu->pc (still in exception context), code 1 exits, code 0 is normal. 2. recompiler full_function_emitter: Broaden longjmp-return detection from first-instruction-only to scanning ALL instructions for the exact encoding 0x8C9F0000 (lw $ra, 0($a0)). This catches both standalone RestoreState (func_1FC0227C) and the kernel inline copy (func_00000C80 at BFC10964). 3. Generated jr $ra terminators in matched functions now emit: cpu->pc = cpu->gpr[31]; psx_restore_state_escape(); return; Result: VSync counter increments steadily (~256/vblank), zero crashes, shell renders Memory Card / CD Player screen with no ADEL faults. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>