At a glance

In the game
The specialised code behind cutscenes, the world map, menu screens and minigames - loaded when that mode starts, gone when it ends. Every loading pause between modes is an overlay swap.
Magic / marker
No header - the blob begins with a MIPS function prologue (addiu sp, sp, -X = 0x27BDFFxx)
Lives in
PROT.DAT entries in the 0901..=0969 range (extraction index), 14-37 KB each; loads into the overlay window 0x801C0000..0x80200000
Parser
legaia_asset::mips_overlay::detect (crates/asset/src/mips_overlay.rs); category mips_overlay in the categorize pipeline
Confidence
Inferred - a shape heuristic with zero false positives over the corpus, not a loader trace; each blob's load base comes from the asset chain that pulls it in.
Used by
Static overlay pipeline, Overlay capture

Layout

Nothing on the disc labels these entries as code - they look like any other binary blob. Every compiled MIPS function opens by moving the stack pointer down to make room for its locals, so a blob that begins with that instruction is a code image whose entry function starts at byte 0.

+0x00 +0x04 +0x08 stack adjust addiu sp, sp, -X prologue follow-up sw ra / addiu / lui / lw code (14-37 KB) position-dependent on load base 0x27BDFFxx 0xAFB?00xx or similar
The detector reads only the first two words; everything after them is the overlay body.
OffsetSizeFieldMeaning
+0x004first instruction0x27BDFFxx - addiu sp, sp, -X, the negative stack adjust that opens a compiled function
+0x044prologue follow-upsw ra/s* (0xAFB?_00XX), or another addiu / lui / lw / R-type - the second instruction of the entry function's prologue
+0x08restcodeThe overlay body, position-dependent on its load base

Detection

Three checks together produce zero false positives across the corpus:

  1. u32_le[0] & 0xFFFF_FF00 == 0x27BD_FF00 - addiu sp, sp, -X.
  2. (u32_le[0] & 0xFF) ∈ [0x80, 0xF8] - only accept reasonable stack adjustments (8 to 128 bytes).
  3. u32_le[1]'s 6-bit MIPS opcode field is one of the common function-prologue follow-ups (sw, addiu, lui, lw, R-type, ldc/sdc).
use legaia_asset::mips_overlay;

if let Some(m) = mips_overlay::detect(buf) {
    println!("MIPS overlay: stack frame = {} bytes; second op = {:#04x}",
             m.stack_frame_bytes, m.second_op);
}

Where they sit and what they do

  • Range. Every match is in the 0901..=0969 extraction range, 14 KB to 37 KB, with one 163 KB outlier at 0969_xxx_dat.BIN.
  • Load base. The overlay window is 0x801C0000..0x80200000; each blob loads at a fixed offset inside it, determined by the asset chain that pulls it in. Recovered bases are committed in crates/asset/data/static-overlays.toml.
  • Likely jobs. From size and the xxx_dat clustering: cutscenes, world map, menu screens, minigames, and per-scene special code that does not fit in the main town-field overlay.
  • Importing. Once a base is known, scripts/ghidra-analysis/bulk-import-overlays.sh loads the blob into Ghidra (the disassembler this project uses) at that base.

Trusting an address from an overlay dump

A dumped function's printed address is only as good as the base the dump was made at; a filename prefix is not evidence of the base. Before citing an overlay address, run the byte-match arbiter (scripts/ghidra-analysis/classify-worklist.py --explain <addr>) and trust its image= verdict. Only a REAL self-entry body at a recovered base attests a distinct function at its printed address.

Failure modeWhere it bitesWhat the arbiter reports
Mis-recovered baseThe bat_back_dat (PROT 0896) dump family, whose link base is unrecoveredField / battle bodies or interior fragments - never a standalone 0896 function at the printed VA
Relocation duplicateDebug-menu (0971), minigame (0977 / 0978) and menu (0899) overlays re-image a shared library at a different base per modeDUPLICATE of the canonical VA in 0970 / 0972 / 0899
Inherited CDNAME labelThe other_game block opens at extraction 0972 and its name carries forward to 0977Name by extraction index: 0977 is the Muscle Dome door/init slot, not a fishing overlay; 0978 opens monster_test
Details: the two 0896 imports and the re-image pairs
  • PROT 0896 is dumped twice, neither at a runtime base: an untagged batch at 0x801C0000, whose prints above 0896's own 0x9000 bytes read through into the field (0897) and battle-action (0898) overlays, and a batch tagged [overlay_0896 base=0x801C5818] - a phantom base recovered from a jal. No dump in this family can be cited by its printed address. Per-program re-key law: docs/reference/overlay-va-aliases.md.
  • The re-image pattern is the same one functions records for 09000901 and 09650967: bodies byte-identical modulo relocation to an already-dumped body.
  • A CDNAME label is a hint, not a verdict - see CDNAME numbering.

How we know

ClaimEvidenceWhere
Prologue shape identifies codeZero false positives over every PROT entry; every match disassembles as MIPS from byte 0crates/asset/src/mips_overlay.rs, categorize sweep
Overlay window 0x801C0000..0x80200000Load targets of the overlay loader; RAM mapMemory map, Boot sequence
Per-blob load basesStatically recovered from the loader constants and cross-checked against capturescrates/asset/data/static-overlays.toml, static overlay pipeline
Address attestation rulesByte-match of each dumped body against every imagescripts/ghidra-analysis/classify-worklist.py, docs/tooling/dump-corpus-integrity.md

See also