Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

SFX Sound Effects File Format

Single-file container for all game sound effects, stored as MAIN.SFX in the SOUND directory. Does not include voice clips (those are in ENGLISH.RTX).

Overall Structure

[FXHD — effect-bank header]
[FXDT — sequential effect records and PCM data]
[END — four-byte terminator]

Effects are stored sequentially with no offset table. The game references effects by their 0-based index in the file.

FXHD (Header Section)

44 bytes total. Section size word is big-endian; remaining fields are little-endian.

OffsetSizeTypeEndianNameDescription
0x004[u8; 4]—tagAlways FXHD
0x044u32BEsection_sizePayload size excluding this field and the tag
0x0832[u8; 32]—descriptionASCII string, set by internal tool “SoupFX”
0x284u32LEeffect_countNumber of sound effects (118 in MAIN.SFX)

FXDT (Data Section)

Begins with a 4-byte ASCII tag FXDT, followed by a big-endian u32 section size (excluding itself and the tag), followed immediately by sequential effect records.

Effect Record

27-byte header followed by raw PCM audio data.

All fields little-endian unless noted.

OffsetSizeTypeNameDescription
0x004u32type_idAudio type: 0 = 8-bit mono, 1 = 16-bit mono, 2 = 8-bit stereo (unused), 3 = 16-bit stereo
0x044u32bit_depth0 = 8-bit, 1 = 16-bit
0x084u32sample_rateAlways 11025 or 22050 Hz
0x0C1u8base_volumeAlways 64 (all 118 effects). Base volume (Miles 0..127 scale) of every start: the caller’s volume is added and the sum clamped to 0..127. Positional callers pass the distance volume relative to this base; FlatSound(e, 0, 0) plays at 64. See positional sound.
0x0D1u8loop_flag0 = play once. Non-zero enables looping; 0xFF loops forever, any other value is passed as the Miles loop count (see Loop Behavior).
0x0E4u32loop_offsetByte offset into PCM data for loop restart point (always 0)
0x124u32loop_endSample count before looping (always 0xFFFFFFFF)
0x164u32data_lengthByte count of raw PCM data following this header
0x1A1u8reserved_1aPadding between header and PCM data. Always 0.
0x1Bvar[u8]pcm_dataRaw PCM audio: u8 samples for 8-bit, i16 LE samples for 16-bit

Loop Behavior

The engine interprets loop_flag as follows:

  • loop_flag = 0: play once (non-looping effects)
  • loop_flag = 0xFF: Miles loop count 0, i.e. loop until stopped (ambient loops like fire, water, wind)
  • any other non-zero value: passed unchanged as the Miles loop count. The only shipped case is effect 117 (the snake charmer tune), flag 0xE1, which plays 225 times rather than indefinitely.

When looping is enabled the engine also passes loop_offset and loop_end as the Miles loop block.

All shipped effects use loop_offset = 0 and loop_end = 0xFFFFFFFF.

Runtime Effect Structure

The engine allocates a 34-byte (0x22) runtime structure per effect, reading 26 bytes (0x00–0x19) from the file. The remaining 8 bytes are computed at runtime:

Struct OffsetSizeSourceContents
0x00–0x1926FileHeader fields (type_id through data_length)
0x1A–0x1D4RuntimePointer to allocated PCM data buffer
0x1E–0x214RuntimeComputed duration value: (data_length << 8) / (sample_rate × bytes_per_sample × channels)
  • RTX — dialogue audio container. Uses the same 27-byte audio header structure (offsets 0x00–0x1A) as SFX effect records. SFX stores sound effects; RTX stores voice clips.

External References