How this section is organised

The pages are grouped the way the disc is layered. Disc + container is the outermost shell: raw sectors, the single big archive (PROT.DAT) almost everything lives in, and the developer-left name map for its entries. Compression + dispatch covers how the game unpacks and routes what it loads. Per-asset formats are the individual asset types themselves. Battle / stat tables are the data tables baked into the game's executable. Streaming + scene containers are the bundles a scene loads as a unit, and runtime overlay carriers are the archive entries that hold code rather than data. If you're new, start with disc geometry and PROT.DAT - every other page assumes those two.

Each format carries a badge for how solid its decode is. The badge is a claim about evidence, not about how complete the page looks - trust it accordingly.

  • Confirmed - verified end-to-end against real on-disc data, with passing tests.
  • Inferred - deduced empirically from byte patterns; structurally consistent but not yet exhaustively validated.

A format can mix the two, and the better pages rate it per-field rather than per-page - the encounter record's shape and reader are Confirmed while the encoding within scripts stays Inferred. Where a page has its own confidence section, that section is authoritative over the badge here.

Disc + container layer

What the disc image looks like before any in-game format gets involved: the sector layout, the one archive file that holds nearly everything, and the text file that names its contents.

Compression + dispatch

How the game turns archive bytes into usable assets: the compression scheme, the type-byte dispatcher that routes each blob to its handler, and the several near-identical "many assets in one file" pack layouts.

Legaia LZS Confirmed
The dictionary compression wrapped around most bulk assets - a custom LZSS variant reverse-engineered from FUN_8001A55C. 4096-byte ring buffer, zero-init - which means "decompresses without error" is not a validity signal; always magic-check the decoded output.
Asset type dispatcher Confirmed
How the game knows what a loaded blob is: FUN_8001F05C dispatches on an 8-bit type byte (0=TIM, 2=TMD, 4=MES, 6=ANM, 7=VDF, 8=SIN, 9=TMD2, B=MOVE2), deciding LZS-vs-raw per asset. The type names come from the devs' own error strings left in the executable.
Asset descriptor format Confirmed
The (type_byte << 24) | size calling convention used by FUN_8001F05C, and the descriptor-pair walker that no code in the executable calls - it's reached only from a runtime overlay.
Pack format Confirmed
The simplest multi-asset bundle: header u32 count + u32 word_offsets[count], then assets back-to-back. Used inside DATA_FIELD streaming chunks.
Standalone TIM-pack Confirmed
A near-identical multi-texture bundle used by some standalone PROT entries, with different header math: (magic_lo, magic_hi, count<16, marker=0x01) + offsets; byte_offset = word_index*4 + 4. Includes the hidden boot-UI bundle at the head of the archive.
Field-pack format Confirmed
A magic-prefixed (0x01059B84) scene bundle whose 97-slot indexed block turns out to be a byte-identical shared template across all 4 carrier entries - and whose magic nothing in the game ever checks. Consumer is FUN_801D6704 (overlay 0897); slots are read at hard-coded offsets.
Player battle files Confirmed
The per-character battle-model files data\battle\PLAYER1..4 (retail battle_data, extraction 0863..0866): header + LZS palette chain + 12-byte descriptor table + per-slot LZS streams that decompress to [32-byte header + Legaia TMD + texture pool]. The old “16 MB container at 0865” was an over-read window into the monster archive (0867).
Row-479 NPC CLUTs Confirmed
NPC colour palettes (CLUTs - palettes stored as rows of framebuffer pixels): plain PSX TIMs in scene PROT entries with CLUT block at (fb_x=0, fb_y=479, w=256, h=1). The engine uploads them with merge-zeros semantics so multiple scene TIMs targeting the same row coexist (full slots 0..14 + partial slots 0..7).

Per-asset formats

The individual asset types - what a single texture, model, sound bank, or dialog file looks like once unpacked.

PSX TIM Confirmed
The PlayStation's standard texture format. 4 / 8 / 15 bpp; palettes (CLUTs) scatter across PROT entries. crates/tim exports to PNG.
Legaia TMD Confirmed
The 3D mesh format - a custom variant of the standard PSX TMD, magic 0x80000002. Object pointers are byte offsets relative to header end; primitives use a custom 8-byte group header + per-mode descriptor table at DAT_8007326C.
VAB sound bank Confirmed
PSX-standard instrument bank (program/tone/SPU-ADPCM sample). crates/vab extracts and decodes to WAV. Banks live across the sound blocks; the retail vab_01 block (extraction 1070..1192) is wall-to-wall VAB - the old “vab_01 is misleading” was the +2 filename shift.
PsyQ SEQ Confirmed
The music sequence format - PsyQ's MIDI-derived pQES container. 13-byte header (PPQN, tempo, time-sig) + delta-time / MIDI events with running status. Drives SsSeqOpen / SsSeqPlay. crates/seq parses + walks.
XA-ADPCM Confirmed
CD-XA Mode 2 Form 2 streaming audio (voice shouts, ambience). crates/xa demuxes per (file_no, ch_no) channel and emits one WAV per stream.
MES dialog Confirmed
The dialog-text container. Two variants: Compact (0x404 magic) and Records (0x44 0x78). Bytecode tokens (Glyph / Op65 / Op4c / Op26 / End). Renderer is overlay-resident.
Dialog font Confirmed
The proportional Latin font the dialog renderer draws with (FUN_80036888). 256-byte width table at 0x80073F1C; 38-entry escape table at 0x80074050; glyph bitmaps in VRAM at (896, 0), 4bpp, 16x16 cells (drawn 14x15).
ANM animation Confirmed
Skeletal animation container (asset-type 6). (count + byte_offsets + records); marker_1 = 0x080C across all observed records. Keyframe pose decoder ported in legaia_anm::AnimPlayer.
Player-character meshes Confirmed
Where Vahn, Noa, and Gala's models actually live. Field form = PROT 0874 §0 (low-poly pack, parser legaia_asset::character_pack); battle form = assembled per character from the player battle files' equipment-id sections (battle_char_assembly), with PROT 1204 other5 as the Baka Fighter / default-equipment sibling pack. Object-local vertices; rest poses come from the ANM / record[0] idle streams.
Monster animation Confirmed
Enemy battle animation inside the monster archive (extraction entry 0867). Per-action transform-keyframe stream at entry +0x8c: [u8 parts][u8 frames] + nine-byte TRS records (one part per TMD object). Action 0 is the idle loop; decoder FUN_8004998c.
MDT - move tables Confirmed
Tactical Arts move records (the fighting-combo system's data). Both layouts parse cleanly; the consumer is FUN_800204F8. The runtime MOVE base is sourced per-scene from a CDNAME slot, not from a single boot-time PROT entry.
Move-power table Confirmed
Battle-action per-move power + behaviour records (26-byte stride, VA 0x801F4F5C, PROT 0898). Damage roll, homing, hit reaction, sound cue and spawned-effect lists; resolved via the id→index map at 0x801F4E63 (the same id space as the spell table).
Art data - Tactical Arts records Inferred
Per-character art records (Vahn / Noa / Gala; PROT entry 0x05C4). 40-field schema: command sequence, action constant, power bytes, hit timing, special / hit effect cues, status effects, repeat-frame replay.
Per-character save record Confirmed
The in-RAM record that holds one party member's whole state: 0x414 bytes at 0x80084708 + slot * 0x414. Cheat-database-pinned offset table for stats, level, magic rank, spells, summons, equipment.

Battle / stat tables

The game's numbers - item names, spell stats, equipment bonuses, steal chances - live as static data tables inside SCUS_942.54 (the game's main executable), not in the asset archive. Each table below is byte-pinned against the executable; DAT_80xxxxxx names are the tables' RAM addresses as labeled in Ghidra.

Spell table Confirmed
Static spell stats (DAT_800754C8) + name pointers (DAT_800754D0), 12-byte stride. Player Seru-magic block 0x81..=0x8B; named monster attacks at 0x25... Parser legaia_asset::spell_names.
Item-name table Confirmed
Static item-name table PTR_DAT_8007436C[id*3] (256 ids, 12-byte stride). The id space monster drops, steals, and equipment all index. Parser legaia_asset::item_names.
Item-effect table Confirmed
What each usable item does: 130 4-byte effect descriptors at DAT_800752C0 - effect class, tier, all-party / field / battle usability flags. Parser legaia_asset::item_effect.
Equipment stat-bonus table Confirmed
8-byte records at DAT_80074F68 per equippable item: attack / defense / agility / speed bonuses, equip-character mask, slot type, Ra-Seru flag. Parser legaia_asset::equip_stats.
Accessory passive table Confirmed
64-slot passive-index space mapping accessories ("Goods") to per-character ability bits (char+0xF4, aggregator FUN_80042558), with stat-% magnitudes inline. Parser legaia_asset::accessory_passive.
Steal table Confirmed
Per-monster [steal_chance_pct, steal_item_id] pairs at DAT_80077828 (chance FIRST - the reverse of the drop field order). What the Evil God Icon steals. Parser legaia_asset::steal_table.
New-game starting party Confirmed
4-record template at 0x80078C4C (Vahn / Noa / Gala / Terra; 26-byte stride) that seeds the live 0x80084708 character records; opening scene town01. Parser legaia_asset::new_game.
summon.dat / readef.DAT Confirmed
Battle side-band streaming slots (extraction 893/894 = raw TOC 0x37F/0x380), 0x10800 bytes each: per-special-attack CLUTs, texture pages, summon-creature actor records, and the player art-anim "ME" archives. Parser legaia_asset::summon_readef.

Streaming + scene containers

The bundle formats a scene loads as a unit - room geometry, textures, scripts, and audio wrapped together - plus the records that drive encounters and scene transitions.

DATA_FIELD streaming Confirmed
The typed-chunk multi-asset container parsed by crates/asset::parse_streaming. Sister detector data_field_truncated catches the shape where the final chunk's declared size walks past EOF.
Scene bundles Confirmed
The family of per-scene container shapes - five sister detectors covering ~50% of PROT entries: scene_tmd_stream, scene_vab_stream, scene_asset_table, scene_scripted_asset_table, scene_event_scripts, plus tmd_size_prefix.
scene_v12_table Confirmed
Per-scene container: runtime-fixup header + inline record table + move-VM stager prescript at sector offset 0x800. 97 PROT entries (one per scene); strict header algebra N = 4*param + 22; the field VM installs prescript records via FUN_800252EC, the move VM (FUN_80023070) runs them.
World-map slot-4 records Inferred
Slot 4 of each kingdom bundle (PROT 0086 / 0245 / 0392, type byte 0x05): a per-kingdom runtime library of small object-local 3D meshes. Each 8-byte record is a GTE vertex (i16 x, y, z, attr); the renderer reads the pool in place. Container byte-verified vs live RAM. Not the bulk continent terrain source.
Effect bundles Confirmed
Battle/field visual effects. Magic 0x02018B0C (efect.dat). 2-pack wrapper: 14 sprite-anim entries + 33 effect scripts indexed by effect ID.
Per-scene primitive scratch buffer Inferred
A negative finding: the 1700-byte RAM cluster at 0x80108EA4..0x80109550 that earlier readings called a "navmesh" is actually a per-scene scratch buffer the renderer fills with assembled GPU primitive data on scene entry. No RAM cell anywhere holds a pointer into the window.
Encounter record Confirmed
Which monsters you can meet where: the on-disc record installed at actor[+0x94] by the script-VM and read by FUN_801DA51C. Layout: [3 reserved][count: u8][monster_ids: u8[count]]. Reader copies the ids into the global formation cell at 0x8007BD0C.
MAN relocation Confirmed
How to safely resize records inside a scene's script file (MAN). Scene-transition (0x3F door) destinations are partition-2 records reached via the partition-2 record-offset table (runtime-pinned); resizing a destination name fixes the partition tables, section-0 offset, intra-record jump deltas, and the external descriptor size. Powers the door randomizer.
STR FMV table Confirmed
How the game finds its movies: libcd's CdlFILE directory cache at 0x801CAE08 and the 23-slot FMV dispatch table at 0x801D0A6C (32-byte stride) the play loop reads - nine retail slots covering every movie on the disc; per-scene fmv_id triggers are disc-pinned as literal operands in the scene MAN scripts.

Runtime overlay carriers

Archive entries that hold code, not assets: overlays - chunks of MIPS machine code the game loads into RAM on demand, where most of the game's logic actually lives.

Auxiliary