4.3 KiB
Music and sound
Sound is the least explored part of the game. This page separates what is verified from what is only a guess. Custom music or sound effects are not supported yet by any LlamaMod tool.
Music
| Fact | Status |
|---|---|
Music tracks are files music/<NAME>.asf on the CD (33 files) |
certain |
| A level does not reference music files directly: environment zones carry a music id, and the start zone's id plays when the level begins | certain |
Music ids map to names through a table in groove.exe at 0x578960 (20 bytes per entry, name pointer at +8), played by FUN_00546b70; id 0 stops the music |
certain |
ASF here is Argonaut's own format (not Microsoft ASF): 4-bit ADPCM, 44.1 kHz stereo, 17-byte blocks, decoded by asfcodec.adl in the game folder |
certain (decoder reimplemented) |
| A second zone field (u16 at +0x56) is probably the ambience setting | likely |
The id table, as used by the editor's zone inspector
(EnvMath.MUSIC):
| Id | Track | Id | Track | Id | Track | Id | Track |
|---|---|---|---|---|---|---|---|
| 0 | (stop) | 10 | GAMEOVER | 20 | SNKJUNG | 30 | TUNE1 |
| 1 | VILLAGE | 11 | TALLY | 21 | FROG | 31 | CHACHA |
| 2 | JUNGLE1 | 12 | TURRACE | 22 | KRONK | 32 | JJUNGLE2 |
| 3 | RIVER | 13 | PACHASNK | 23 | KIDLLAMA | 33 | TUNE9 |
| 4 | JUNGLE2 | 14 | MOUNT2 | 24 | TUNE8 | 34 | TUNE6 |
| 5 | MOUNTAIN | 15 | BALLOON | 25 | ROLLER | 35 | VICTORY |
| 6 | CITY | 16 | JUNGSPID | 26 | BUNNY | 36 | PUZZLE2 |
| 7 | CATACOMB | 17 | JAGCHASE | 27 | BLOCK | 37 | PLATFORM |
| 8 | LAB | 18 | RIVER | 28 | TUNE5 | 38 | (none) |
| 9 | TITLE | 19 | RIVRACE | 29 | CITYPUZZ | 39 | ENDGAME |
Four names (GAMEOVER, TALLY, PUZZLE2, PLATFORM) have no .asf file on the German CD; what the
game plays for them (probably nothing) was not checked.
Changing the music of a level works today: pick another id for the start zone (or any zone) in the editor's Environment panel (manual: Environment, tutorial: Edit an original level).
Listening to the tracks: tools/asf2wav.py in.asf out.wav
decodes a track exactly like the game's codec (filter 0: s = s1 + (n << shift), filter 1:
s = 2·s1 − s2 + (n << shift), 16-bit wrap-around instead of clipping – FFmpeg's decoder clips and
drifts).
New music – open: there is no encoder yet. Writing one (the inverse of asf2wav.py) and
replacing a track file through a mod would be the natural next step; the header fields after the
block count (rate, flags with bit 1 = stereo) are read by the decoder, the others are unknown.
Sound effects
| Fact | Status |
|---|---|
Each level has its own sample bank, chunk SMPC: u32 n, n × {u32 "cvg " tag, u32 length, data} |
certain (SoundMerge.java) |
Strats play samples by index (soundPlay(sound:N), opcodes 0xd5 / 0x99 / 0x131 play, stop, is-playing); at most 128 samples per level, ids with bit 0x80 are the front-end sounds |
certain |
The samples are PlayStation-style VAG ADPCM, decoded by Vagcodec.adl |
likely (tag and codec name; the sample header was not decoded) |
AMPC holds ambient sound data (ambi / VABp blocks) |
likely, not decoded |
FESOUND.WAD is the front-end sound bank (not a chunk file) |
likely |
Samples can be moved between levels: the editor's cross-world import and the arena copy the
samples an imported object needs into the target level and renumber the sound:N operands
(notes/editor-cross-import.md). Changing which sample an
object plays is a constant edit in its script (Strats). Exporting or
replacing a sample's audio is not possible yet.
Speech and dialogue
- LGPC holds the dialogue texts of a level in all languages plus a speech slot per line.
- A speech slot
#<hex>is an index into SRPC, whose entries are offset/size pairs into the global speech filemusic/<language>.cvsin the game folder (the German version shipsenglish.cvs). - Strats show texts with opcodes 0xf0 / 0xfa (
topSay text:N). Imported objects bring their texts and speech references along.
The CVS file format itself was not analysed.