# The WAD LZ77 container Target: `SCUS_972.68` v1.01. Insomniac's LZ77 stream. A 16-byte header followed by a sequence of packets. Each packet begins with a **flag byte** selecting one of four classes. This format is **not** the `G/*.WAD` container described in [`global-wad.md`](global-wad.md), despite the shared name and extension. WAD streams are compressed and appear inside level cores and MPEG data; the `G/` containers are uncompressed tables. Confusing the two produces garbage. ## Header ```text offset size field 0x00 3 magic, "WAD" 0x03 4 total stream length in bytes, including this header 0x07 9 unused ``` `compressed_size` at `0x03` is the authoritative length. A stream whose declared size exceeds the buffer is rejected rather than truncated. ## Packets | Flag | Class | Displacement bits | Length | |---|---|---|---| | `0x00..0x0f` | literal run | — | flag + 3 (flag 0 escapes to a byte + 18) | | `0x10..0x1f` | back-reference | 15 | 3 bits in flag, else a byte + 7 | | `0x20..0x3f` | back-reference | 14 | 5 bits in flag, else a byte + 0x1f | | `0x40..0xff` | back-reference | 11 | 3 bits in flag | Every packet ends with 0–3 extra literal bytes carried in unused low bits of the packet, so literal and back-reference packets interleave without alignment. This is why the format does not read as a bit stream, and why a first attempt that modelled it as one will appear to produce plausible output for a few kilobytes before failing. ### Literal run Flag `< 0x10`. The count is `flag + 3`, except flag `0x00` which escapes to a following byte giving `byte + 18`. The bytes follow immediately. Two literal packets in a row are invalid: the encoder merges them. The decoder rejects the stream rather than accept a misparse. ### Back-reference A back-reference copies `len` bytes from `displacement` positions back in the already-produced output. **Overlapping copies expand as run-length.** The source index advances with the destination, so `displacement = 1` repeats a single byte. This is used intentionally by the encoder. A displacement of zero, or one that reaches before the start of the output, is invalid. ### Pad and dummy packets In the `0x10..0x1f` class, a packet whose displacement field is entirely zero is special: - length field not 1 → a **pad packet**: the reader skips forward to the next `0x1000` boundary. These exist so compressed blocks align with something on the disc. - length field 1 → a **dummy packet**: it carries only its trailing literal bytes. ## Worked example The first stream in this game's `MISC.WAD` begins: ```text 05 80 00 00 00 10 | 00 0d ... ``` - Flag `0x05` is `< 0x10`, so it is a literal run of `5 + 3 = 8` bytes: `80 00 00 00 10 00 0d 00`. - The next flag byte starts the following packet. ## Implementation `crates/gc-formats/src/wad.rs`. Parses through the same bounds-checked reader as everything else in the crate, so a truncated stream produces a typed error rather than a panic. A `BadMagic`, an out-of-bounds read, and a displacement before the output are three distinct error kinds. ## Provenance The packet structure was recovered from behavioural analysis of the retail data, guided by the format description in the Wrench project (, GPLv3). **No Wrench code is copied into this repository** — see `PROVENANCE.md`. The decoder here is written from the specification and verified against this disc's own streams.