mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
9306db59b3
The read stream froze read_delay whenever the guest had an unacked controller INT (and while the sector buffer was undrained). Real drives never pause: measured on MMX4's attract/title XA music, the freeze accumulated ~1M guest cycles/second (~3% of disc time), every XA sector arrived 32-92 samples late, and the XA->SPU cd_ring starved ~147 samples 5-6x per second — audible as a 6 Hz crackle/dropout flutter in all XA-streamed music (user report: MMX4 Zero ice-stage attract demo). Faithful model, mirrored from the in-tree Beetle oracle (cdc.cpp HandleSectorRead / SetAIP / CheckAIP / ClearAIP): - Disc time NEVER pauses while reading; sectors are read on exact cycle schedule. XA-ADPCM realtime audio flows to the SPU decoder unconditionally (this alone removes the crackle). - A data sector that comes due while the guest still has an unacked INT overwrites the sector buffer on schedule (hardware clobbers its FIFO the same way) and its data-ready INT1 pends ONE deep, presented the moment the guest fully acks (Beetle CheckAIP). A newer sector replacing an unpresented notification is counted + traced 'P' (Beetle "Previous notification skipped"). - Drive-state changes (Read/Play/Pause/Stop/Seek paths through start/stop_read_stream) cancel the pended notification (ClearAIP). - The active-DMA refill path (deliver without new INT while a multi-sector CD DMA drains) is unchanged. Verification on MMX4 (SLUS-00561) title/attract XA: - CD_PUSH guest-cycle spacing: exactly 1,806,336 cycles (8 sectors at 2x), min == max over 148 pushes (was 1.83-1.88M, systematically late). - read_hold_cycles == 0 (was ~30.8M per 30 s) — kept as an always-on regression tripwire in cdrom_state. - int1_pended == 0 during music: X4 acks fast; the pending path only arms for genuinely slow acks. - spu_out/host tap rings: 6 Hz zero-gap storm (86-144 gaps/95 s of 147-265 samples) eliminated; only real content silences remain. - cd_underflow_frames stays 0 during playback. Always-on observability added (ring-buffer doctrine): - XA zero-run scanner in the decode path -> AUDIO_EV_XA_ZERO events (stage 0 = post-ADPCM, stage 1 = post-resample+volume, with LBA). - CD_PUSH audio events now stamp the global guest-cycle clock (the spu_out sample stamp is pump-quantized and cannot measure cadence). - cdrom_state: read_hold_cycles/read_hold_events (must stay 0), int1_pended / int1_lost / int1_pending_now. - Savestate: pending_dataready fields appended to CDROM_SNAP_FIELDS. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>