Overlay pointer-table code Inferred
When a Ra-Seru summon like Nighto's Hell's Music fills the screen, the code choreographing that attack was not in memory a second earlier - it was streamed off the disc into a small "slot" of RAM just for the cast, and thrown away afterwards. These are the blobs that hold such code. Sister format to MIPS overlay code: the same family of on-disc code blobs (overlays - chunks of MIPS code the game loads into RAM on demand), but instead of starting with a function prologue, these start with a table of function pointers, then the code those pointers reference. A few of them open with an ASCII title that reads like a song name but is the battle special attack the overlay implements.
At a glance
- In the game
- Per-attack code for summons and special attacks (the slot-B "stagers"), plus other mode-specific modules that expose an entry-point or dispatch table.
- Magic / marker
- No header - the first u32 is a pointer into the overlay window
0x801C0000..=0x801FFFFF, followed by 3..63 more - Lives in
- PROT.DAT entries in the
0900..=0968range (extraction index), 42 entries, 14-160 KB; the attack stagers load at slot-B base0x801F69D8 - Parser
legaia_asset::overlay_ptr_table::detect(crates/asset/src/overlay_ptr_table.rs); load bases incrates/asset/data/static-overlays.toml- Confidence
- Inferred as a detector (a shape heuristic with zero overlap against named formats); the individual attack-stager identities are capture-pinned.
- Used by
- summon.dat / readef.DAT, Static overlay pipeline
Layout
The overlay window is the RAM region reserved for swappable code, so a run of valid pointers into it is a strong sign the blob expects to live there. The run is 4 to 64 pointers long; the first word that is not such a pointer starts the body.
| Offset | Size | Field | Meaning |
|---|---|---|---|
+0x00 | 4 | ptr_0 | Address in 0x801C0000..=0x801FFFFF (the overlay window) |
+0x04 | 4 | ptr_1 | Same range |
+N*4 | 4 | ptr_{N-1} | Last pointer (still in range); N is 4..64 |
+(N+1)*4 | rest | body | First non-pointer u32 - typically MIPS code, sometimes a jr ra; nop stub or a leading ASCII string |
Tables come in three shapes:
| Shape | Size | Tell |
|---|---|---|
| Function entry-point table | Small (5-14) | Monotonic; one slot per public function |
| Switch dispatch table | Larger | Repeating handler addresses; the C compiler's switch(x) over a dense range |
| Per-mode actor vtable | Small | Only 3 distinct values across N slots |
Detection
Two checks produce zero overlap with already-named formats:
- The first u32 is in
0x801C0000..=0x801FFFFF(the overlay window). - The run of consecutive overlay-pointer u32s is between 4 and 64 long.
Monotonicity is not required - switch dispatch tables legitimately repeat handler addresses.
use legaia_asset::overlay_ptr_table;
if let Some(t) = overlay_ptr_table::detect(buf) {
println!("Overlay pointer table: {} entries, first=0x{:08x}, last=0x{:08x}",
t.count, t.first_ptr, t.last_ptr);
}
Once the load address is known (the pointer values bound it from above: base <= min_ptr), the entry can be imported into Ghidra via scripts/ghidra-analysis/bulk-import-overlays.sh.
Where they sit
All 42 matches are in the 0900..=0968_xxx_dat range, 14 KB to 160 KB, in two pointer clusters:
| Entries | Pointer range | Shape |
|---|---|---|
| 30 | 0x801F6Axx - 0x801F71xx | Small function-entry tables, monotonic, 5-14 entries - the slot-B stagers |
| 12 | 0x801F84xx and up | Mixed: some monotonic, some switch dispatch with repeating handlers |
Entries that open with a title
A handful lead with an ASCII string before the pointer table. The string is the battle special-attack name the overlay stages. All of these load at slot-B base 0x801F69D8.
| Entry | Title | What it stages | Spell id | Pinned by |
|---|---|---|---|---|
0907_xxx_dat | Hell's Music | Nighto's summon | 0x85 | Capture on the summon loader's 903..=913 slot; the same name in the spell table and summon.dat |
0924_xxx_dat | Ultimate Rave | Lippian (rare-Seru flute summon) | 0x96 | Capture mid-cast off the loader-B current id |
0927_xxx_dat | Dark Eclipse | Juggernaut (Evil Seru Magic) | 0x99 | Capture mid-cast off the loader-B current id |
0957_xxx_dat | (string table) | The summon_effect_table overlay - a summon / effect / target label table, then an absolute-pointer table and code | - | Static overlay map |
0924 and 0927 have computed rather than constant loader call sites, which is why their identities come from captures instead of a static loader constant.
History: the "Disco King dance-song" reading
The titles look like song names, and an earlier reading filed 0907's title as a Disco King dance track. It is refuted: the dance overlay (0980) contains zero slot-B loader call sites - its music is sequenced BGM via the sound streaming loader - while 0907 is capture-pinned as Nighto's summon stager. Retired readings are collected on do not re-walk.
How we know
| Claim | Evidence | Where |
|---|---|---|
| Pointer-run shape is code | Zero overlap with any named format over the corpus; bodies disassemble as MIPS | crates/asset/src/overlay_ptr_table.rs |
Slot-B base 0x801F69D8 | Summon loader constant + the stager pointer clusters | crates/asset/data/static-overlays.toml |
0907 = Nighto (spell 0x85) | Capture of the summon loader's 903..=913 slot select | summon.dat / readef.DAT action-id map |
| 0924 = Lippian, 0927 = Juggernaut | Mid-cast capture of the loader-B current id | PCSX-Redux probes |
| 0980 is not a stager | No slot-B loader call site in the dance overlay | Address reference scan |
Source of record: docs/formats/overlay-ptr-table.md.