fix(cd): paused/stopped/seeking drive delivers I2S silence, holds position

The SSI head streamed disc data unconditionally: through Pause/Stop,
during seeks, and past track ends into data sectors.  A game with its
DSP CD mix enabled plays those data sectors as full-scale noise --
device-reported as "loud clipped static" under music and SFX (Primal
Rage, Baldies, Iron Soldier 2 garbage-audio loop).

A real drive outputs silence and holds position while paused, stopped,
or seeking; the I2S bit clock keeps running.  Gate the sample fetch on
cdPlaying / seekDelay: deliver zeros without advancing the head, but
keep the DSP SSI interrupt firing (the synth engine is clocked off it
in slave mode).

Verified: make test green, HLE sweep 6/9 and BIOS sweep 8/9 at
baseline, Primal Rage attract music timeline unchanged.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
Joseph MattielloandClaude Fable 5 committed 2026-07-16 17:48:20 -04:00
1 parent 0e30eed16c
commit 874330f4ce
1 file changed
+14
+14
View File
@@ -1706,6 +1706,20 @@ void SetSSIWordsXmittedFromButch(void)
if (ssiXmitCount <= 5 || (ssiXmitCount % 10000) == 0)
CD_LOG("SSI xmit #%u: ssiBufPtr=%u ssiBlock=%u cdPlaying=%d\n",
ssiXmitCount, ssiBufPtr, ssiBlock, cdPlaying);
/* A paused/stopped/seeking drive outputs silence and holds position;
* the I2S bit clock keeps running (the DSP synth is clocked off these
* interrupts in slave mode) but no disc data moves. Without this
* gate the head streamed forever -- through pauses and past track
* ends into data sectors, which a game with its CD mix enabled plays
* as full-scale noise ("loud clipped static"). */
if (!cdPlaying || seekDelay > 0)
{
lrxd = 0;
rrxd = 0;
return;
}
// Advance by 4 bytes (one stereo sample: 2 bytes L + 2 bytes R).
// Uses the SSI head's own cursor -- see ssiBuf declaration for why
// this must not share cdBufPtr with the FIFO read path.