mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-27 10:38:46 -04:00
55120e102e
Jackie Chan Stuntmaster (SLUS-00684) hard-blackscreens after the intro logos: the game's exception dispatcher is re-entrant by design. Its stage-1 handler saves SR/EPC to a single save slot, then executes mtc0 CAUSE,0x100 + mtc0 SR,0x101 and relies on the resulting COP0 SOFTWARE interrupt (CAUSE.IP0 & SR.IM0 & IEc) to vector into its stage-2, which acks the CD INT at the controller, delivers events, and restores the saved SR. The runtime only ever considered the INTC line (i_stat & i_mask) gated by SR.IM2, so the sw-int was never taken: stage-2 never ran, CD INT3 stayed unacked (process_pending freezes the completion countdown while irq_flag != 0), and the machine deadlocked with the display disabled and SR parked at 0x101 (IM2 stripped -> all hardware interrupts dead). Three changes, all architectural (no per-game logic): 1. interrupts.c psx_check_interrupts(): a pending software interrupt (CAUSE & SR & 0x0300, plus IEc) is now a deliverable source. The fast path, the pending check, and the SR gate each consider it; the INTC path still requires IM2, the sw path only its own IM bit. Exception entry sets CAUSE.IP2 only when the hardware line is what is being delivered, so a pure sw-int presents the guest-written IP0/IP1 bits unmodified (the dispatcher discriminates its stages by exactly these bits). 2. interrupts.c: save/restore exception_jmpbuf across delivery. The sw-int nests inside the hardware-interrupt handler window; the nested setjmp used to overwrite the single global jmpbuf, so the OUTER handler's later RFE longjmp'd into the exited inner frame (host stack corruption, SIGSEGV). 3. dirty_ram_interp.c: deliver immediately after an interpreted MTC0 to CAUSE or SR that makes a sw-int deliverable, with EPC = the committed next pc. Hardware vectors within the next instruction; waiting for the next block boundary opened a window in which a second hardware IRQ re-entered the (legitimately non-reentrant) guest dispatcher and destroyed its saved SR. precise_irq_deliverable gains the same sw-pending condition. Verified on SLUS-00684: boots through BIOS/logos/FMV into rendered 3D gameplay at 60 fps, SR observed at the canonical 0x40000401, CD irq_flag acked, MDEC decoding. BIOS-only boot unaffected. Known scope limit: compiled (static) MTC0 sites do not yet trigger the immediate check; the raising writes observed in the wild live in the BIOS-installed, dirty-RAM-interpreted trampoline, which this covers.