# WAD container A level is one file `wads/t1lm.wad`. It is a flat list of chunks: ``` u32 total length repeat: u32 tag (four ASCII letters stored reversed: "OFNI" in the file = INFO) u32 length length bytes of chunk data ``` There are no checksums. When a chunk changes size, only the chunk length and the total length must be rewritten ([`format/Wad.java`](../../src/main/java/com/eliasmueller/llamamod/format/Wad.java), [`tools/wadtool.py`](../../tools/wadtool.py) – `wadtool.py list|extract|replace`). ## Chunks In file order. "Loader" is the function in `groove.exe` that reads the chunk (dispatcher at 0x558960). | Chunk | Contents | Documented in | |---|---|---| | INFO, VERS | u32 1 each, ignored | – | | WFPC | u32 feature flags of the level; they switch optional blocks in MAP and STPC on and off – never change them | [Geometry](geometry.md#wfpc-flags) | | TEXT | texture pages, texture rectangles, texture animations | [Textures](textures.md) | | FONT | 256 × 4 u16 glyph rectangles | – | | SPRT | sprite list (u32, more with WFPC 0x100000) | – | | NAME | u32 + level name (not shown anywhere in the game) | – | | SMPC | sound samples of the level (`cvg ` blocks) | [Music and sound](audio.md) | | AMPC | ambient sound data (`ambi`/`VABp`) | [Music and sound](audio.md) | | SRPC | references into the speech file `music/.cvs` | [Music and sound](audio.md) | | **TRAK** | world geometry: the tile models (render triangles + collision polygons) | [Geometry](geometry.md) | | **STPC** | object models, skeletal animations and the **strat code** (object behaviour) | [Geometry](geometry.md#stpc-object-models-and-code), [Strats](../strats/README.md) | | **MAP** | the tile grid, vertex colours, visibility regions, objects, waypoints, environment zones | [Geometry](geometry.md), [Objects](objects.md) | | LGHT | lights (directional and point lights for object models) | [Objects](objects.md#lights) | | LNFO | u32 coins, u32 secrets: the totals shown on the tally screen | [TestLevel](testlevel.md#tally-totals) | | LGPC | dialogue texts in all languages + speech slots | – | | END | end marker | – | Not every level has every chunk. The three chunks that matter for level building are **TRAK**, **STPC** and **MAP**; a new level takes everything else (textures, sounds, sky, fog, music) from an original **base level**. ## The base-level idea An object type exists in a level only if its code is in that level's STPC. MAP refers to a type by its **byte offset into STPC** – there is no global type id. So every custom level starts as a copy of an original level (default: Village 1, `t1l1m001`) and replaces geometry and objects: * Python [`tools/levelbuild.py`](../../tools/levelbuild.py) and Java [`levelbuild/LevelBuilder.java`](../../src/main/java/com/eliasmueller/llamamod/levelbuild/LevelBuilder.java) generate TRAK and MAP from a script and keep STPC, TEXT and sound of the base. * The level editor stores only the difference to the base level and rebuilds the WAD from the user's own CD ([notes/editor-format.md](../../notes/editor-format.md)). * Object types of *other* levels can be merged into the base's STPC together with their models, animations, textures and sounds – the editor's *All worlds* import and the arena use this ([notes/editor-cross-import.md](../../notes/editor-cross-import.md)). ## Level memory The game loads STPC, TEXT (compressed pages + 20 bytes per texture entry), TRAK, MAP, LGPC and the strat pool into one **16 MB** block (`FUN_0041eea0`); original levels use up to about 7 MB. See [Engine facts and limits](engine-limits.md).