feat: resolve console CD-DA routing (CD.DAT music_id → Red Book track); close Phase 3 #280
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "refs/pull/280/head"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Resolves CD-DA routing for the console-family ports, closing the last open
item in Phase 3 (
dm2-music). The Sega CD / Mac JP / PC-9821 / FM-Townseditions deliver their soundtrack as Red Book CD-DA tracks and route music
with a 40-byte
CD.DAT([DMWEB] Format 1); the parser already read thoserecords, and
dm2 convert --cddaalready extracted a track to WAV — butnothing connected a record's
music_idto the specific disc track it names.Finding:
music_idis the absolute Red Book CD audio-track number(
music_id == cd_track; the disc's audio session is TRACK 02–07). Threeindependent lines of evidence:
CD.DAT(byte-identical across everyconsole-family disc) references only
music_id ∈ {2, 3, 6}— all insidethe physical audio-track range
[2, 7], never the data track.CHECK_TRIGGER_MUSIC_FROM_PLAYER_POSITIONmatches the party's absoluteworld
(x, y, level)against the ten triggers (itstCDMusicMapstructis byte-for-byte
Format1Record) and callsREQUEST_PLAY_MUSIC(music_id),which resolves the track as
sprintf(path, "CD%02x.…", music_id)— thevalue is used directly as the CD track number, no table indirection.
music_id 2 → track02(theSkullkeep-exterior theme, 8 of 10 triggers),
3 → track03,6 → track06(the level-10 trigger). The measured durations rule out a 1-based index:
under absolute numbering
music_id 6is track06 (a full 291 s leveltheme), whereas 1-based would map it to track07 (a 15 s sting).
What landed
dm2-music—Format1Record::cd_track() -> u8(the absolute CD tracka trigger plays) and
Format1Routing::referenced_tracks() -> Vec<u8>(thesorted, deduped track set a table references —
[2, 3, 6]for retail).The
music_idfield doc now states the resolved mapping and its evidence.dm2-cli—dm2 dump <CD.DAT> --format music-mapemits the resolvedrouting as JSON: one entry per trigger (
level,x,y,music_id,cd_track,track_file) plus areferenced_trackssummary(
cd_track,track_file,trigger_count). It handles the 40-byteconsole Format-1 table; the 176-byte Amiga/Mac Format-2
CD.DAT(whichroutes to MODs /
'Midi', not CD-DA) gets a clear error.asserting
cd_track/referenced_tracksagainst the realCD.DATandthat each referenced track resolves to an actual audio fixture, and a
fixture-gated CLI test over
dump --format music-map. All skip cleanlywhere the gitignored game data is absent.
music.md§Red Book rewritten with the resolved mapping andevidence (and the stale appendix / routing-TODO closed);
ROADMAP.mdPhase 3 → ✅ (remaining Phase-3 items are intentional deferrals: AIFF
writer, compressed
'snd ', SMS pitch-bend/pan), plus the now-stalePhase 5 "convert paths pending" clause corrected.
Notes
track_filefollows the repo'strack{NN}.binnaming, which is exactlywhat
dm2 convert --cdda --allemits (trackNN.bin → trackNN.wav), soextraction and routing are consistent by construction — no extraction
changes were needed. Scope is deliberately the console Format-1 table only;
the Amiga/Mac Format-2 and DOS
songlist.datrouting already have their ownparsers and route to non-CD-DA assets.
Full-workspace
cargo testis green;cargo fmt --checkandcargo clippyare clean.