Sound banks (RESSON/*.MEG)
One bank per track (ambient loops: wind, machines, sea), one shared bank FIX.MEG (engine, tyres, crashes, the countdown, menu sounds), and one small bank per car that holds no sounds. Music is not here: it plays from CD audio (CDAREF.TXT, lists.md).
Reader: decoders/meg.py (decode, encode), crates/pod-formats/src/bank.rs (the whole bank), sound.rs (the sounds to play). State: decoded and round-trip for all 28 banks (measured, 2026-10-23: every byte is read in the order the game's loader reads it, and writing the decoded bank gives the original file); 82 sounds play in the viewer.
The banks were written by Ubi Soft's sound tool: they hold its project name (POD), a description ("1° essai d'intégration": first integration test), event types and French descriptions of each sound.
The loader
FUN_004c1e48 (observed) takes a bank name, adds .MEG, opens it in folder 14 (Data\Binary\resson\), reads the 40-byte header into a 0x90-byte bank slot at 0x698E8C (64 slots), then:
| Section | Read by | Content |
|---|---|---|
| 0 | FUN_004c12c4 | The sounds (a USSB block) |
| 1 | FUN_004c19c0 | SMMH groups |
| 2 | FUN_004c1be0 | The events (a second USSB block) |
| 3 | FUN_004c6518, when the bank is played | The bank's play list |
| 4 | streamed by FUN_004c6518 | The samples; the loader keeps only the offset |
It returns the slot number. FUN_0045ede0 calls it with each circuit's file stem and stores the slot at +0x88 of the circuit's row (lists.md).
Layout
Plain files, not in the block container. Each section starts where the one before ends, and section 4 ends at the end of the file (measured on all 28).
| Offset | Size | Content |
|---|---|---|
| 0 | 40 | Five (offset, length) pairs, u32 each; the first offset is 0x28 |
USSB header (sections 0 and 2)
| Offset | Size | Content |
|---|---|---|
0x000 | 4 | USSB |
0x004 | 12 | Unknown (differs between banks; a date or version, inferred) |
0x010 | 0xFF | Description, zero-terminated |
0x10F | 0x51 | Project name: POD, or PROJET (the tool's default) in some blocks |
0x160 | 4 | 1 in every bank |
0x164 | 2 | Record count |
0x166 | 2 | Highest record number (count - 1) |
0x168 | 1 | k: sample formats (section 0, 1 in every bank) or parameter definitions (section 2, 13) |
0x169 | 1 | 0 in section 0; 100 or 0 in section 2 |
The game reads the 0x164 bytes and the six count bytes with two ReadFile calls, then uses only the counts (observed in FUN_004c12c4, FUN_004c1be0).
Section 0: the sounds
After the header: k sample formats of 4 bytes (i16 bits, u16 rate: 16, 22050 in every bank; FUN_004c12c4 matches them against the sound card's format), then one record per sound of 0x11C + k × 0x30 bytes (0x14C here):
| Offset | Size | Content |
|---|---|---|
0x000 | 0x100 | Description, zero-terminated ("crissement pneu": tyre screech); the bytes after the zero are left over from the tool |
0x100 | 2 | Record number |
0x102 | 2 | Kind: 1 a sample, 4 a music script (FIX.MEG's "sequence CD" names Script1.txt and has no samples) |
0x104 | 0x18 | Six u32, 1 in every record |
0x11C | 0x30 × k | One variant per sample format, below |
| Variant offset | Type | Meaning |
|---|---|---|
0x00 | char[0x15] | Resource name (Criss2.RRR), with leftovers after the zero |
0x15 | u8 | Volume, 0 to 0x7F |
0x18 | u32 | 1 when the sound loops |
0x1C | u32 | Offset of the samples in section 4 |
0x20 | u32 | Length in bytes |
0x24 | u32 | Sample rate in Hz: 22050, 11025, 15000 |
0x28 | u32 | Loop start, bytes |
0x2C | u32 | Loop length, bytes; the whole sound when it does not loop |
The variants tile section 4 end to end in record order, and every loop ends at the sound's last byte (measured). 83 records: 82 samples and the script record.
Section 1: SMMH
May be empty: four of POD's track banks (BABELWEB, FACTORY, SKYRACE, SPIN) have a section 1 of length 0, so the events' USSB follows the sounds directly. The loader seeks to each section's offset from the header (POD FUN_004bb440) and the group reader returns "none" when it does not find SMMH (POD FUN_004bad08), so an empty section means no groups (observed; measured: all 50 of POD's banks read and write back byte for byte).
SMMH, u16 group count, u16 (2 in FIX.MEG, 0 elsewhere), then per group: u32 index, i32 entry count (-1: none), 0x14 bytes holding a name (Monza), and 0x20 bytes per entry (observed in FUN_004c19c0, which skips the name). Only FIX.MEG has groups: Monza with three entries and two empty ones. The entries' meaning is open; their first words (0x13, 0x14, 0x15) are record numbers of the Monza… engine sounds (inferred).
Section 2: the events
The second USSB header, then k (13) parameter definitions of 0x50 bytes, which the game skips (SetFilePointer by k × 0x50): the tool's names for event types and parameters ("evt son simple", "EVENT TYPE", "PARAMETRE 1"). Then one 0x88-byte event per record, passed to FUN_004c0d8c: a description at +0x02 ("lance pneu"), a name at +0x52, and event-type, parameter and flag fields after +0x74 (observed; field by field open).
Section 3: the play list
u16 count, then one u16 per entry: with bit 15 set, a record number in this bank; else a global sound number (observed in FUN_004c6518). The track banks list their own sounds (0x8000, 0x8001, …); FIX.MEG lists 22 global numbers.
Section 4: the samples
Signed 16-bit little-endian mono PCM. Measured: all 82 sounds are clearly above silence, and next-sample correlation is high for most; the three exceptions (NEON1, CHRYSAL2) are noise-like sounds (a neon buzz, a crystal shimmer).
Open questions
- The 12 bytes at
USSB+0x004, the six words at record+0x104, theSMMHentries and the event fields one by one. - Two sounds in one bank can share a name: which one does the game play?