64 lines
3.6 KiB
Markdown
64 lines
3.6 KiB
Markdown
# WAD container
|
||
|
||
A level is one file `wads/t1l<world>m<chapter>.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/<lang>.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).
|