Sound-driver path-string cluster Confirmed
The game's executable still carries the file extensions its sound tooling used during development - .dpk, .spk, .MAP, .PCH - as a little cluster of path strings the sound subsystem appends when building asset paths. This page decodes that cluster and answers the question it raises: are these exotic sound formats to reverse? Mostly no.
The retail .dpk / sound_data2 payload turns out to be a chunked VAB + SEQ bundle - the ordinary instrument-bank + music-sequence pair (see the final section) - and the .MAP / .PCH PsyQ intermediates are dev-side tool outputs the retail disc does not carry at all.
Cluster layout
The cluster lives in SCUS_942.54 (the game's main executable) at RAM 0x8007B380 (file offset 0x6BB80):
| Offset | Bytes | Meaning |
|---|---|---|
0x8007B380 |
12 bytes | Per-extension flag/mode metadata table: 00 01 FF FF FF FF 00 00 00 02 00 00. |
0x8007B38C |
"sound\" |
Path prefix for streaming-asset loads. |
0x8007B394 |
".spk" |
SPU sample bank. |
0x8007B39C |
".LZS" |
Compressed wrapper (per-file). |
0x8007B3A4 |
8 bytes | Not sound data. The per-character equipment-swap selector bytes (3 equip-condition offsets at 0x8007B3A4 + 3 group indices at 0x8007B3A8) read by the graphics-side FUN_8001EBEC - see character-mesh. Adjacent to the path cluster in BSS but unrelated to it. |
0x8007B3AC |
"bse.dat" |
Master sound-bank file name (loaded once at sound-init). |
0x8007B3B4 |
".dpk" |
Per-scene sound pack - the format FUN_8001FA88 loads. |
0x8007B3BC |
".MAP" |
Sound bank map (PsyQ SoundArtist output). |
0x8007B3C4 |
".PCH" |
Patch / instrument data (PsyQ output). |
0x8007B3CC |
".LZS" |
Duplicate, fallback. |
0x8007B3D4 |
".pac" |
Per-scene generic pack. |
0x8007B3DC |
"STR" |
Streaming audio (raw PSX .STR containers). |
Consumers
Two SCUS functions touch the cluster (located via ghidra/scripts/find_sound_path_builders.py):
| Function | Role | Touch points |
|---|---|---|
FUN_8001FA88 |
Sound subsystem init / .dpk loader. Allocates a 0x1800-byte buffer at _DAT_8007B8D0. Loads bse.dat via the path-based opener. Then assembles h:\main\bg\domepack\<name>.dpk (template at 0x800105C8 + extension at 0x8007B3B4) and opens it. |
0x8007B3AC (bse.dat), 0x8007B3B4 (.dpk) |
FUN_8001FC00 |
Streaming-asset loader. Builds paths under the sound\ prefix; the XA / .pac / STR consumer. |
0x8007B38C (sound\) |
Trap: FUN_8001EBEC looks like a third consumer (it reads _DAT_8007B824 + the tables at 0x8007B3A4/0x8007B3A8) but is not a sound function - it is the character-TMD equipment-conditional group-transform swap (it reads the loaded battle-character TMD pointers from DAT_8007C018[_DAT_8007B824 + 0..2], where _DAT_8007B824 is the party base index, and copies group transforms). The 0x8007B3A4/0x8007B3A8 bytes are its per-character selector tables, not sound-extension descriptors. See character-mesh.
Dev-build vs retail-build paths
Both FUN_8001FA88 and FUN_8001FC00 carry a _DAT_8007B8C2 (debug-flag) carve-out:
- Dev branch (
_DAT_8007B8C2 != 0) loads sound data via PROT indices.FUN_8001FA88's dev branch loads index0x37A(=sound_data2) plusparam_1 + 5for per-scene variations, via the index-based loader (FUN_8003EB98). - Retail branch (
_DAT_8007B8C2 == 0) loads via dev-style paths through the path-based opener (FUN_8003E6BC), which resolvesh:\main\bg\domepack\…into the appropriate PROT entry through the CDNAME-driven name map.
Both paths land at the same files; only the indirection differs. The same dev/retail split appears in FUN_800255B8, so it's a pattern that repeats across asset-loading subsystems.
The .dpk / sound_data2 payload is a VAB + SEQ bundle
The sound-side chunk payload is a VAB followed by a SEQ, not a novel .MAP/.PCH/.spk layout:
| Chunk type | Payload | Magic |
|---|---|---|
0 | VAB header section | pBAV (0x5641_4270 LE) |
1 | VAB sample section (SPU-ADPCM / VAG waveform pool) | - (raw samples) |
2 | SEQ (the stream terminator) | pQES |
The decisive invariant: type-0 + type-1 reconstitute one contiguous VAB whose header total_size (+0x0C) equals chunk[0].size + chunk[1].size. Byte-verified across 0877–0885 (e.g. 0877: 0x2820 + 0x1BA90 == 0x1E2B0); the reconstituted VAB parses with legaia_vab and the terminator SEQ with legaia_seq.
The type-1 chunk payload depends on the consumer: on the graphics battle-init walk, FUN_8001FE70's type-1 handler is the TIM/CLUT upload (FUN_800198E0); a sound pack's type-1 is the VAB's sample pool. The content shape matches the scene_vab_stream BGM wrapper (VAB + SEQ); only the container differs. Decoder: legaia_asset::sound_pack (extract returns the reconstituted VAB + SEQ); disc-gated sound_pack_vab_seq_real test.
The .MAP / .PCH PsyQ SoundArtist intermediates are the dev-side inputs that produce this VAB, not separate on-disc retail chunks - the retail disc does not carry them.