At a glance

In the game
Every field scene load - the town overlay's init walks one of these to install the scene's assets.
Magic / marker
None - a leading u32 count and a header word, then the pairs.
Lives in
In RAM, at the head of a decoded buffer; PROT 0874 (player.lzs, extraction-index space) is the three-descriptor instance the character mesh pack is read through.
Retail reader
The descriptor walker, reached from the town overlay's init (how we know).
Parser
legaia_asset::parse_player_lzs (crates/asset/src/lib.rs).
Confidence
Confirmed - walker disassembled, overlay caller traced; the second header word's purpose is Unknown.

Layout

Two header words, then a flat array of 8-byte pairs. data_offset is byte-relative to the buffer start; type_size packs the asset-type byte (the 8-bit tag saying TIM / TMD / MES / …) in its high byte with the payload size in the low 24 bits. Each payload is an LZS stream when the container is a player.lzs-style chain.

count header word type_size 0 data_offset 0 type_size 1 +0x00 +0x04 +0x08 +0x0C +0x10 one 8-byte pair per asset, count pairs total type_size = (type << 24) | size
The descriptor: four little-endian words of header + pairs, no magic.
OffsetSizeFieldMeaning
+0x004countNumber of descriptor pairs that follow.
+0x044header wordPurpose unknown. On PROT 0874 it is 0x2CBA0, the offset of a VDF data tail past the LZS payload that the battle loader registers verbatim - see character mesh § on-disc layout. Editors must keep it byte-exact.
+0x08 + 8i4type_size_i(type << 24) | size: asset-type byte in the high byte, size in the low 24 bits.
+0x0C + 8i4data_offset_iByte offset of asset i from the buffer start.

Where it appears

  • In RAM only. Strictly scanning all 1233 PROT entries (the numbered slots of PROT.DAT, the disc's main asset archive) against this shape as a top-level entry finds zero hits. The table only exists once an LZS chain such as player.lzs has been decoded; the DATA_FIELD streaming format carries descriptor-shaped chunks under its own header instead.
  • Reached only through an overlay. The executable's static call graph never touches the walker - it looks like dead code until the town overlay's init is followed (how we know). This "zero static callers but alive via overlay" pattern recurs across the whole codebase; treat a zero-xref result as "needs an overlay sweep", never as "dead".
  • Installs the party's field meshes. The same walk registers PROT 0874 §0's five TMDs into the model slots the field-form character meshes draw from.

The Rust parser is named parse_player_lzs after the container it was first read through; the format itself is not player-specific.

How we know

FunctionAddressWhat it proves
Descriptor walkerFUN_80020224Reads count, then walks the (type_size, data_offset) pairs and dispatches on the high type byte.
Town overlay MAIN_INITFUN_801D6704, call at 0x801D6B0CCalls the walker with a0 = 0 on every field scene load; result stored at 0x80087AF8. Zero static xrefs exist in SCUS_942.54.
Type-2 (TMD) handler chainFUN_8001F05C case 2 → FUN_80026B4CRegisters PROT 0874 §0's five TMDs into DAT_8007C018[0..=4] - the field character-mesh slots.

See also