Jazz Jackrabbit Sound Format
Jazz Jackrabbit sounds are stored in the SOUNDS.00X files. SOUNDS.000 is used by the game as a 'base' file, when Jazz is playing levels the sounds in SOUNDS.00X are added to this. This is done by the header in SOUNDS.00X pointing to sounds in SOUNDS.000 (by using a special pointer) as well as having references to their own sounds. Thus SOUNDS.000 is the largest file, with other sound files often being little more than empty headers.
Sound files consist of a header ('sfx' + $1A) followed by raw sound data. The end of the file contains a list of the sound names and properties, with the final four bytes being the sound list location in the file. The game reads the file by checking the header, taking the last four bytes, finding the list and reading it.
Raw sound data: This is exactly like a wave file, being composed of 'samples' much like those used in ProTracker Studio Module (PSM) music files. The data consists of 1-byte signed entries and also sometimes contains a sample header for the samples to be extracted back to the original files, but this is treated as sound data by Jazz and is unimportant. The header though is as follows:
1 1 $01, start of header 2 13 Sample name 14 2 Word, $0005 16 2 Size of sample after header 18 10 Blank 28 4 Sample volume 32 4 Pitch 36 40 Blank 76 4 header end 'SCR' + $00
Sound list: The sound list consists of a varying number of entries, read until 4 bytes from the end of the file. It has a maximum length of 32 18-byte entries.
0 12 Sound name, this is the name of the sound, used by levels and such to play the sound, padded with nulls. 12 4 Sound location in sound file, data is read from here. If this value is larger than $7FFFFFFF then is the 'negative' of the value and refers to the location of a sound in SOUNDS.000 (Thus the first entry in most SOUNDS.00X is $FFFFFFFC, pointing to 4 in the .000 file.) 16 2 Sound length, in bytes.
Oddly, for SOUNDS.001 and onwards (2,3,...) any sound over 15 that refers to SOUNDS.000 refers to it 346 bytes further along than it should. This appears to relate to the header structure somehow, but I don't know exactly. Also sound 15, if it refers to SOUNDS.000 will have the reference value of SOUNDS.000 sound 15, no matter what value it has for the location.