Ask the chip which decoder it is, and find four wrong axes where one was expected
ROADMAP P6a, on the machine. 68000 code programs HD63450 channel 3 with the IPL ROM's own ADPCM bytes -- dual address, 8-bit port, cycle steal, external request -- and feeds the MSM6258 a designed 1,678-nibble stream at the chip's own pace: 839 B in 0.1074 s = 7,811.4 B/s against the format's 7,812.5, CER=$00. That transport is P6b's, not scaffolding. Sixteen candidate decoder models, three capture decimations and a searched prologue are fitted to MAME's capture. Exactly one reproduces it sample-exact over all 1,678 samples, and every axis carries a negative control: flip it alone and the closest survivor disagrees on 826, 1,504, 156 and 1,522 samples. The chip runs 'terms', takes the LOW nibble of a byte first, clamps the accumulator at 10 bits and starts it at -2. tools/encoder/adpcm.py defaulted to the opposite of all four, and 65.2 named the wrong axis as the risk: the delta formula is worth -2.88 dB and the NIBBLE ORDER is worth -25.74 dB. 65.1's "high first, measured" was a measurement of ffmpeg, i.e. of the VOX file convention, which is a different question from what a chip does with a byte in its data register. The 10-bit clamp is free on the Singe window and only because that window peaks at 435 of 511 -- 1.4 dB of headroom on a -13.4 dBFS passage, 12.1 dB below where the encoder was clamping, and inside the recursion. So the audio level is an open choice again, downward, and the loudest passage on the disc is unmeasured. Session 33's silence had two ordinary causes: the PPI's port C is an input until control word $92 says otherwise, and $01 is COMMAND_STOP. And a rig fact worth the space: the 8 MHz ADPCM clock is CT1 in the YM2151's $1B, delivered on the sound system's schedule rather than at the store, so a transfer started in the same breath as the setup plays its first ~17 ms at the old clock and no model fits a stream that changed rate part way through. Name the layer: this is MAME 0.277's okim6258 device model measured end to end through the machine's real transport. It settles the rig and not the silicon. Also struck: 64.4's "no MAME source tree is on this machine" -- there is none on disk, but the machine has network and the upstream tag fetches. check.sh ALL GREEN before (tmp/check_s34_start.log) and after (tmp/check_s34_end.log), with one new stage. Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
Executable
+56
@@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
# ROADMAP P6a: ask the machine's own MSM6258V which decoder it is.
|
||||
#
|
||||
# tools/bench/adpcm_run.sh
|
||||
#
|
||||
# WHAT A GREEN RUN MEANS: 68000 code programmed HD63450 channel 3 exactly as the
|
||||
# IPL ROM programs it -- dual address, 8-bit port, cycle steal, EXTERNAL request
|
||||
# -- fed the chip a designed nibble stream at the chip's own pace, and exactly
|
||||
# ONE of sixteen candidate decoder models reproduces MAME's capture of the
|
||||
# result SAMPLE-EXACT, with every one of the four axes shown to matter.
|
||||
#
|
||||
# WHAT IT DOES NOT MEAN: anything about an MSM6258. This is MAME's device model
|
||||
# measured end to end through the machine's real transport. It settles the RIG.
|
||||
# The silicon stays on the hardware list.
|
||||
set -e
|
||||
cd "$(dirname "$0")/../.."
|
||||
|
||||
tools/vasm/vasmm68k_mot -Fbin -o tmp/adpcmgate.bin src/player/adpcmgate.s > /dev/null
|
||||
python3 tools/bench/prep_adpcm.py
|
||||
|
||||
# -samplerate 15625 is not a preference: it is the chip's own stream rate
|
||||
# (8 MHz / 512), and equal rates are what keep MAME's resampler from filtering
|
||||
# the thing being measured. The first cut of this ran at the default 48000 and
|
||||
# every reconstructed sample arrived as an interpolated pair.
|
||||
( cd tmp && SDL_VIDEODRIVER=dummy stdbuf -oL timeout -k 5 300 \
|
||||
mame x68000 -bios ipl10 -ramsize 2M -video soft -window \
|
||||
-samplerate 15625 -wavwrite adpcm.wav -nothrottle -plugins \
|
||||
-autoboot_script ../tools/bench/adpcm.lua \
|
||||
-seconds_to_run 12 > adpcm_run.log 2>&1 )
|
||||
grep -aq "^\[ADP\] done" tmp/adpcm_run.log || {
|
||||
echo "FAIL: the ADPCM gate did not finish -- no completion marker."
|
||||
tail -8 tmp/adpcm_run.log; exit 1; }
|
||||
grep -a "^\[ADP\]" tmp/adpcm_run.log | sed 's/^\[ADP\] / /'
|
||||
|
||||
fail() { echo "FAIL: $1"; exit 1; }
|
||||
if grep -aq "^\[ADP\] ERROR" tmp/adpcm_run.log; then
|
||||
fail "the channel reported an error or the gate timed out -- see CSR/CER above."
|
||||
fi
|
||||
grep -aq "bit7 clear = playing" tmp/adpcm_run.log || \
|
||||
fail "the chip never reported itself playing."
|
||||
# THE FEED RATE IS A GATE, not a note. The chip is the pacemaker: one byte per
|
||||
# #DRQ3 and #DRQ3 at half the sample rate. If the bytes went out at some other
|
||||
# rate then the channel was NOT being paced by the device, and every sample
|
||||
# below is of a stream that arrived faster or slower than it was consumed --
|
||||
# which is precisely the failure session 33 hit from Lua.
|
||||
RATE=$(sed -n 's/.*= \([0-9.]*\) B\/s .*/\1/p' tmp/adpcm_run.log | head -1)
|
||||
python3 - "$RATE" <<'PY' || fail "the feed was not paced by the chip (see above)."
|
||||
import sys
|
||||
r = float(sys.argv[1])
|
||||
want = 7812.5
|
||||
print(f" feed rate {r:,.1f} B/s against the chip's own {want:,.1f} B/s "
|
||||
f"({100*(r-want)/want:+.2f}%)")
|
||||
sys.exit(0 if abs(r - want) / want < 0.02 else 1)
|
||||
PY
|
||||
|
||||
python3 tools/bench/verify_adpcm_chip.py tmp/adpcm.wav tmp/adpcm_seq.json
|
||||
Reference in New Issue
Block a user