mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-28 10:59:16 -04:00
cdrom: cancel stale INT2 on new command (PSX-CD-007)
Cancel the previous command's outstanding second-response interrupt when a new CD command is accepted (psx-spx command flow; DuckStation BeginCommand semantics). Without this, a Pause(0x09) INT2 survives into the guest's next Setmode/Setloc/ReadN sequence and fires mid-read as a stale COMPLETE — LIBDS drivers treat it as a read failure, corrupting the streamed resource chain. Cross-validated: C-12 Final Resistance mission 1 PC=0 null-callback termination disappeared after absorbing this fix (DEVLOG 2026-08-05). MOHU Mission 1 freeze in a DsRead FATAL/retry loop on single-sector marker reads. Also guard beetle SIGSTOP trap behind #ifndef _WIN32 (Windows has no SIGSTOP). (cherry picked from commit 2c43fc69c66242a86183156a6f1e60b2f81b1e47) (cherry picked from commit c03fe5ba3d49241dfaedb344db6ad9c977070722)
This commit is contained in:
@@ -75,7 +75,9 @@ static void cdcmd_trace_callback(uint8_t cmd, uint8_t nargs,
|
||||
uint32_t pc) {
|
||||
/* Symmetric self-stop trap (mirror of the runtime's PSX_CD_TRAP_CMD):
|
||||
* SIGSTOP on the Nth matching CD command so a debugger can freeze the
|
||||
* oracle at the exact boot point and diff its state against ours. */
|
||||
* oracle at the exact boot point and diff its state against ours.
|
||||
* POSIX-only, same guard as debug_server.c — Windows has no SIGSTOP. */
|
||||
#ifndef _WIN32
|
||||
{
|
||||
static long trap_cmd = -2, trap_nth = 1, hits = 0;
|
||||
if (trap_cmd == -2) {
|
||||
@@ -86,6 +88,7 @@ static void cdcmd_trace_callback(uint8_t cmd, uint8_t nargs,
|
||||
}
|
||||
if ((long)cmd == trap_cmd && ++hits == trap_nth) raise(SIGSTOP);
|
||||
}
|
||||
#endif
|
||||
BeetleCdcmdEntry *e = &s_cdcmd_trace[s_cdcmd_idx];
|
||||
e->seq = s_cdcmd_seq++; e->pc = pc; e->cmd = cmd; e->nargs = nargs;
|
||||
e->a0 = a0; e->a1 = a1; e->a2 = a2;
|
||||
|
||||
@@ -264,6 +264,7 @@ static uint8_t cd_muted;
|
||||
#define XA_SUBMODE_REALTIME 0x40
|
||||
#define CDROM_SECTOR_MODE2 0x02
|
||||
|
||||
|
||||
#define CDROM_SKIP_NONE 0
|
||||
#define CDROM_SKIP_XA_AUDIO_REALTIME 1
|
||||
#define CDROM_REQUEST_BFRD 0x80u
|
||||
@@ -2004,6 +2005,26 @@ static void exec_command(uint8_t cmd) {
|
||||
trace_cdrom('C', 0, cmd, 0);
|
||||
/* ENQUEUE: a CD command was issued (aux = command byte). */
|
||||
event_ring_record_aux(EV_ENQ, (uint8_t)SRC_CD_CMD, (uint32_t)cmd);
|
||||
/* A new command CANCELS the previous command's outstanding second
|
||||
* response (psx-spx command flow; DuckStation BeginCommand "command
|
||||
* cancellation"). The sub-CPU runs one transaction at a time: once a
|
||||
* new command is accepted, the superseded command's INT2 is never
|
||||
* delivered. Two-phase handlers below already overwrite `pending`;
|
||||
* this clears it for single-phase commands (GetStat/Setmode/Setloc/…)
|
||||
* and for ReadN/ReadS, which do not use `pending` at all.
|
||||
*
|
||||
* Without this, a Pause(0x09) INT2 scheduled ~1.1M cycles out (see
|
||||
* pause_complete_delay_cycles) survives into the guest's next
|
||||
* Setmode/Setloc/ReadN sequence and fires MID-READ as a stale
|
||||
* COMPLETE. LIBDS drivers treat that as a read failure: MOHU Mission 1
|
||||
* wedged in a phase-locked DsRead FATAL/retry loop on its single-sector
|
||||
* marker reads, corrupting the streamed resource chain
|
||||
* (medal-of-honor-underground DEVLOG 2026-08-05). GT1 race loading
|
||||
* shows the same stale-Pause overlap during ReadS streaming. */
|
||||
if (pending.pending) {
|
||||
trace_cdrom('X', 0, pending.cmd, 0);
|
||||
pending.pending = 0;
|
||||
}
|
||||
/* Snapshot the param FIFO before handlers consume it, so the
|
||||
* command-history record at the end sees the original params. */
|
||||
uint8_t cmd_params[PARAM_FIFO_SIZE];
|
||||
|
||||
Reference in New Issue
Block a user