ROADMAP P6b, FINDINGS 67. DLXP2: a 64-byte header and then groups -- one
audio lump of A sectors, then F records -- so record i is at
off_frm + i*rec + (i//F)*A*512 and lump k at off_aud + k*(F*rec + A*512).
Still no index and still none needed, which is the packed branch's whole
claim surviving the one change that could have ended it. The player carries
the third term in six instructions once a frame and zero parsing, and 120 of
120 records are still pixel-exact off a real MB89352 volume with the
interleave in, against a silent control that says no picture byte moved.
The finding is what 65.3 called padding. A lump is 7,168 B of SPACE; eleven
frames of audio is 7,161.4583... B, so the payload alternates 7,161 and
7,162 and the rest is zero. A player that fed the chip the whole lump --
which is what "14 sectors every 11 frames" invites -- runs 0.09% fast, and
that is not waste, it is drift: 0.84 ms a group, 1.25 s of lip-sync over the
game's 22.8 minutes. What a player carries is one accumulator,
acc += 11*15625; n = acc//24; acc %= 24, which is clock.i's shape for
clock.i's reason and the third time this tree has met the pattern.
The four ADPCM axes ride in the header as fields rather than a version
number, and the gate flips each one to prove they earn it: nibble order
-31.99 dB, delta formula -24.86, clamp 0.00, accumulator -0.49. Nothing
parses a packed container, so the gate partitions the whole file -- 131
spans, no overlap, no gap -- and asserts what a cadence-blind player would
read: exactly records 11..119 wrong, and frames 0..10 identical either way,
which is how an off-by-one like that survives a rig that checks frame 0.
Wire 582.0 + 7.64 = 589.6 KB/s, 65.3's prediction to the tenth.
Green light ALL GREEN before (tmp/check_s35_start.log) and after
(tmp/check_s35_end.log), with the new stage in it.
Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
ROADMAP P6, everything in the item except the bus half session 20 closed.
tools/encoder/adpcm.py is an MSM6258 codec, tools/encoder/extract_audio.py
takes the same seconds of the same stream the frames come from,
tools/bench/verify_adpcm.py is the gate, tools/analysis/32_audio_wire.py the
container arithmetic.
There is no reference encoder -- ffmpeg has a decoder for this format and none
the other way -- so what is gated is the decoder the encoder runs INSIDE its
own nibble search, sample-exact against ffmpeg's over 4,268 nibbles. An
encoder that agrees with its own wrong decoder is what that catches. The Singe
window: 156,250 samples -> 78,125 B at 21.97 dB, which is 7,812.5 B/s to the
byte. Normalising the disc's -13.4 dBFS level moves the SNR 21.97 -> 21.97, so
the level is not a lever.
And the two published delta formulas are not the same codec. They differ by at
most 3 in 12-bit units; encode for one and decode on the other and the SNR
goes 21.97 -> -2.88 dB, the noise louder than the signal, because ADPCM is
recursive the way the video codec is temporally recursive. Which one the chip
runs is now P6a and it is a precondition on shipping any audio.
And audio is the first thing the packed branch's simplification has cost
anything for. A record has no index BY DESIGN, so audio cannot be per-record
without making records variable; it rides a fixed cadence (F, A), the obvious
F=1 wastes 57.3% of every audio sector, and the pick is F=11 A=14 -- 0.09%
padding, 14,336 B held, wire 582.0 -> 589.6 KB/s. The codec container, which
kept its index, pays zero.
The MAME experiment did not work and 65.5 says so: :okim6258 is there at
$E92001/$E92003, read out of the machine's own program map, and feeding it
from Lua recorded silence across control 0..3 x port C 0..15. The register
semantics were not guessed at further.
FINDINGS 65. check.sh ALL GREEN before and after, with a new stage.
Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6