At a glance

Where
efect.dat = extraction PROT 0873, one of the four befect_data files 0870..0873 (etim / etmd / vdf / efect); the 0x02018B0C bundle only in 0000_init_data
Magic
2-pack: none - two absolute pack offsets behind an 8-byte header. Bundle: 0x02018B0C
Runtime copy
post-init buffer at _DAT_8007BD5C, byte-identical to the disc entry; live pool at _DAT_8007BD30 (5008 bytes)
Parser
engine_vm::effect_vm::EffectCatalog::from_efect_dat_bytes (2-pack); legaia_asset::effect_bundle (bundle); legaia_asset::befect_cluster (the four files)
Confidence
Confirmed - every record field read off its battle-overlay consumer; texel source pixel-verified against battle captures
Used by
Effect VM, Battle action SM, move-power effect lists
efect.dat pack0_off pack1_off sprite atlas, 8 B each pack0: anim batches pack1: effect scripts +0 +4 +8 count + u32[count] count + u32[count] a spawn script[effect_id] child: sprite_id anim batch frame: atlas index atlas entry u v w h clut tpage textured quad etim pages (320..448, 0)
One file, three tables: an effect script names sprites, a sprite's animation batch names atlas entries, and an atlas entry is a VRAM rectangle on the etim pages.

The runtime 2-pack (efect.dat)

When a hit lands, the battle overlay looks up an effect id, spawns a handful of child sprites around the impact point, and animates each from a short frame list. Both packs are offset tables of absolute file offsets - not the word*4 offsets of asset::pack. The retail file holds 144 atlas entries, 14 animation batches and 33 scripts.

OffsetSizeFieldMeaning
+0u32pack0_offsetabsolute offset of pack0; fixed up to a pointer on first init
+4u32pack1_offsetabsolute offset of pack1; same fixup
+8N × 8sprite atlasVRAM rectangles, up to pack0
pack0u32 count + u32[count]anim batchesframe-batched animation records
pack1u32 count + u32[count]effect scriptsone per effect id

The three record kinds

RecordOffsetFieldMeaning
atlas entry (8 B)+0..+3u, v, w, h (u8)texel rectangle (u, v)..(u+w-1, v+h-1) inside the texture page
+4clut (u16)CLUT id, copied into the primitive's CLUT field
+6tpage (u8)texture-page byte, copied into the primitive's tpage field; +7 reserved
anim batch (pack0)+0, +1frame_count, flags
+2frames, 6 B each+0 atlas index; +1..+5 timing / direction bits
effect script (pack1)+0, +1child_count, flagsflags bit 0 = random child distribution
+2spread (u16)half-range for random child position (8.8 fixed)
+4children, 14 B each+0 u16 sprite_id (pack0 index); +2 i16 X half-width; +4 u16 anim flags; +6 i16 Z half-width; +8 6 B curves / sound / timing

Field order matters. The u16 at atlas +4 is the CLUT, the byte at +6 the tpage. The often-cited 0x7680 is therefore a CLUT - it decodes to framebuffer (0, 474), an effect-CLUT row - not a texture page. The real page byte is e.g. 0x25 = page (320, 0), 4bpp.

The battle effect cluster (befect_data)

efect.dat is one of four dev-named files the battle scene loader pulls in sequence. The loader opens each by dev-path string, which is a trap stub on this build, so the load resolves through the raw TOC index (raw = extraction + 2; see CDNAME numbering).

Loader caseDev nameRaw / extractionContent (byte-checked)
0x8etim.dat0x368 / 08703-TIM pack: three 64×256 4bpp pages at VRAM (320,0) / (384,0) / (448,0), CLUTs at (0, 474..476). The first TIM's flags word is 0x00010008 - strict TIM parsers reject it.
0xbetmd.dat0x369 / 087130-TMD asset::pack - the effect 3D-model library, registered into the mesh pool at battle init.
0xbvdf.dat0x36A / 087232-entry offset pack (~96 B records), asset type 0x07.
0xcefect.dat0x36B / 0873The 2-pack above: pack0@0x488, pack1@0x900.
0x4(battle-type conditional)0x367 / 0869 or 0x36D / 0875Streaming [VAB chunk][type-3 chunk] files outside the block.

Extraction 0874 is not effect data: it is player.lzs, the field character mesh pack. The CLI asset befect-cluster PROT.DAT --cdname CDNAME.TXT classifies the window; it resolves the symbol in define-number space, so its window is 872..875.

History: raw indices read as extraction indices

Readings that applied raw TOC indices as extraction indices ("etim = entry 872", "PROT 870 = index 0x366") are superseded; extraction 0870 is the case-0x8 load. An earlier cluster analysis read 0874 as "etmd/vdf/etim LZS sections" (it is player.lzs), and a note guessed the billboard texel source was entry 875. See do-not-re-walk.

Where the pixels come from

The atlas carries only VRAM coordinates; the pixels are blitted at load time. Two texture pools serve battle effects:

  • etim.dat (0870) - battle-only. Uploaded on battle entry into columns the field also uses, so field captures hold unrelated texels there. Pixel-exact against every stable Rim Elm battle capture. Engine: scene::upload_flame_atlas_into_vram, into a throwaway VRAM copy discarded on battle exit.
  • player_data §2 (0874 §2) - field-resident, kept through battle: eight TIMs at fb_y = 256+ (three character atlases, two shared 256-colour pages, two extension tiles; full table on character-mesh). Engine: scene::upload_effect_textures_into_vram at scene entry.

A melee hit-spark capture confirms the 2D path: the impact draws as textured quads on the etim pages (320,0) / (448,0) with CLUT rows 473..480, present only in the impact frame - no primitive samples page (0,0) or "tpage 0x7680".

The battle summon model: geometric, library at 0871

A player Seru-magic cast pages in a per-summon code overlay (extraction PROT 903..913; Gimard Burning Attack 0x81 → 903) that supplies the spawn logic. The effect-model library is etmd.dat (0871): the 30-entry pack loads verbatim at 0x800CA25C and registers into DAT_8007C018[3..32]. Gimard's flame is slot 26 (pack entry 23); the engine seeds the same slots at scene entry (scene::seed_effect_model_library_from_etmd, GIMARD_TAIL_FIRE_MODEL_INDEX = 26). None of 0874 §0's field-character TMDs are resident mid-cast; its smallest TMD bakes a flame-like CLUT and survives only as a preview fallback.

Animation is geometric, not CLUT cycling. Two animation-distinct capture frames share a byte-identical CLUT band (rows 470..499) while their framebuffers differ ~21%. A live trace of the player cast shows the per-actor draw firing 35-64× per frame through the rigid-TRS keyframe decoder, while the move VM fires only 2-3× - the player summon is drawn as an ordinary battle actor (engine path engine-vm/anim_vm.rs). The summon overlays do carry real move-VM part records (legaia_asset::summon_overlay, link base 0x801F69D8), driven by the engine as a stand-in summon::SummonScene; the overlay's three conditional CLUT uploads target rows 481+, not the flame's row 478. Scope: the player Burning Attack; the enemy Fire Tail is untraced.

Runtime: pool, spawn, and the bit-7 multiplex

Three battle-overlay routines own the format: an init that zeroes the pool and converts both packs' offsets to pointers; a spawn API (effect_id, world_pos, angle) that takes the first free master slot and points its cursor at script + 4; and a two-pass per-frame walker - pass 1 advances the 32 master slots and spawns children from the next 14-byte instruction, pass 2 turns the 128 child slots into GPU sprite quads from the atlas.

OffsetSizeRegion of _DAT_8007BD30
+0x00016table head: (u16 id, u16 param, buf+8, pack0+4, pack1+4) written by init
+0x0104096128 × 32-byte child slots (per-sprite render state)
+0x101089632 × 28-byte master slots (per-effect instance)
+0x13901968unused

A battle move reaches this pool through its move-power effect lists (+0x12 / +0x16). Each list byte multiplexes two id spaces by bit 7: 0x01..=0x63 is the 3D move-FX path (prototype table 0x801F6324, not this pool; 0x64 = screen flash), while 0x80..=0xFE spawns pack1[id & 0x7F] here. Two ids are special-cased: 0x04 and 0x13 resolve to 18-byte move-VM trigger programs in the overlay tail (the two arms of the radial particle burst), not pack1 scripts. The engine models the split as EffectListEntry::{Spawn, AltEffect}.

Side-band streaming files

A separate loader case streams one of two runtime-only files by raw TOC index: summon.dat (0x37F = extraction 893) when bit 7 of _DAT_8007BD24[0x26B] is set, else readef.DAT (0x380 = 894). Both carry per-special-attack CLUT rows, 4bpp pages and summon-creature actor records - decoded on summon-readef.

On-disc effect bundle (magic 0x02018B0C)

A separate container carrying effect geometry, found only in 0000_init_data. Its consumer is unreached, so this section is structural. Parser legaia_asset::effect_bundle::detect.

OffsetSizeFieldMeaning
+0u32magic0x02018B0C
+4u32HEADER_A0x1D = 29 TMD slots (1 master + 28 sub)
+8u32HEADER_B0x1E = HEADER_A + 1 (sentinel)
+1228 × u32offset tablestrictly ascending (0x17F4 .. 0x404D); slot size = next − this
after tableasset regiona master Legaia TMD first (1 object, 382 verts, 760 primitives)

The 28 offsets do not byte-align with sub-TMD positions; they likely index an abstract runtime buffer. A related shape, the field-pack (magic 0x01059B84), has its own page.

How we know

FunctionAddressWhat it provesDump
Init / pack fixup0x801DE914 (via loader case 0xE)2-pack wrapper, offset-to-pointer fixup, table-head record, pool size 5008funcs/overlay_battle_801de914.txt
Spawn API0x801DFDF8Master-slot allocation, script cursor at +4, ids 0x04 / 0x130x801F5D90 / 0x801F5CF8funcs/overlay_battle_801dfdf8.txt
Per-frame walker0x801E0088; emit ~0x801E0840..0980Child descriptor fields, atlas byte order (CLUT at +4, tpage at +6), sin/cos LUTs _DAT_8007B7F8 / _DAT_8007B81Cfuncs/overlay_battle_801e0088.txt
Effect-list dispatchFUN_801E09F8FUN_801DFDF0The bit-7 multiplexfuncs/overlay_battle_801e09f8.txt
Battle scene loaderFUN_800520F0, sub-state at gp+0xA59; raw-index open FUN_8003E8A8Case → file → raw index mapfuncs/800520f0.txt
Image uploaderFUN_800198E0FUN_800583C8 (LoadImage); CLUT cache 0x8007BEC0How etim pages reach VRAMfuncs/800198e0.txt
Mesh registrarFUN_80026B4C; pool DAT_8007C018etmd registers 30 TMDs at slots 3..32funcs/80026b4c.txt
Side-band handler0x801F17F8FUN_800558FCRaw indices 0x37F / 0x380 = extraction 893 / 894funcs/overlay_battle_801f17f8.txt
CapturesRim Elm battle states; battle_gimard_tail_fire_a/_b; melee hit-sparkBuffer at _DAT_8007BD5C = disc sector 0x9086; etim pixel-exact; geometric summon animationscenario manifest
Open questions and history
  • Effect id → name. There is no string table; the only "name" available is an id → triggering-move join off the move-power table.
  • The low-band readef.DAT aux-slot consumer - see summon-readef.
  • The 0x02018B0C bundle's consumer is unreached.

History: the side-band files were once placed at extraction 895 / 896 by comparing raw indices against extraction numbering; and under the over-reading entry window, 0871's pack body appeared to span an "extended footprint". See prot.

Source of record: docs/formats/effect.md.

See also