Files
psxrecomp/runtime/include
Matthew Stanley 9306db59b3 cdrom: continuous disc clock — never freeze the read stream on INT ack
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>
2026-07-10 13:55:52 -07:00
..
2026-05-17 21:58:55 -07:00