Overview

Implementation: crates/asset/src/pack.rs.

Layout

u32 count
u32 word_offset[count]   // each is in 4-byte words from the start of THIS pack data
... sub-asset bytes, packed back-to-back ...

Sub-asset i lives at byte range [word_offset[i] * 4 .. word_offset[i+1] * 4), with the last sub-asset ending at the chunk's end. Note the offsets count 4-byte words, not bytes.

Example

A TIM_LIST chunk header followed by a 2-TIM pack (a TIM is the PlayStation's standard texture format):

chunk header:    6c 02 01 01    type=0x01 (TIM_LIST), size=0x01026C
pack count:      02 00 00 00    count = 2
offset[0]:       03 00 00 00    word offset 3 → byte 12 (= start of TIM 0)
offset[1]:       8b 20 00 00    word offset 0x208B → byte 0x822C (= start of TIM 1)
[then 2 PSX TIMs back-to-back]

Distinction from the standalone TIM-pack

The standalone TIM-pack form - used for whole archive entries rather than chunks inside a stream - is structurally similar but uses an 8-byte header (a byte[3] == 0x01 / byte[2] < 0x10 discriminator pair, then a u32 count at +4) and adds a constant +4 to each word offset. The pack-inside-streaming-chunks form here lacks the discriminator prefix and its word offsets are taken straight from the pack-data start - use the right format for the source. (The third sibling, field-pack, is a magic-prefixed scene bundle with its own page.)

See also