At a glance

In the game
The choreography of pause-menu, shop and save-UI windows opening, closing and sliding
Magic / marker
None - a zero opcode byte terminates a program
Lives in
Menu overlay, PROT extraction entry 0899 (slot-A base 0x801CE818): programs cluster at file 0x16260..0x16740, VA 0x801E4A78..0x801E4F58
Stride
4 bytes per instruction; programs are 2 to 7 instructions long on disc
Retail reader
FUN_801D6628(&program), 13-entry jump table at 0x801CED70
Parser
legaia_asset::widget_script (parser + jal-site scanner); interpreter port legaia_engine_vm::run; host wiring legaia_engine_core::menu_widget
Confidence
Confirmed - interpreter and caller disassembly, program bytes verified on the disc image
Used by
Shop flow, Level-up notice, Field menu

Instruction encoding

Each instruction is exactly 4 bytes. After every instruction the interpreter reads the opcode byte of the next slot and stops when it is zero.

+0 +1 +2 +4 opcode u8 0x01..0x0D window id u8 0..51 operand u16 LE: packed x/y or style next slot 00 = end 1 byte 1 byte 2 bytes
One instruction. A program is a run of these ending where the next opcode byte is 0x00.
OffsetSizeFieldMeaning
+01opcode0x01..=0x0D selects one of 13 handlers; 0x00 terminates the program
+11window idIndex into the 52-record window descriptor table (16 bytes per record); the record's x / y are the instruction's default coordinates
+22 (LE)operandPacked position for opcodes 0x02 / 0x09: x = (w >> 7) & 0x1FE, y = w & 0xFF. Style byte for 0x03. Zero elsewhere on disc

Opcode semantics (create / snap / slide / close / global tick) belong to the interpreter and are documented with its port in crates/engine-vm/src/lib.rs and on the actor VM page.

OpcodeSeen on disc as
0x01Open a window at its home position
0x02Open at a packed position (operand)
0x04Close
0x05Global tick
0x06Motion-flag clear
0x0AClose / re-open / slide-back composite

Where the programs live

Each caller builds a pointer to a program and calls the interpreter with it. Because the table is overlay data at fixed addresses, the lookup is per boot, not per scene: the same programs are resident whenever the menu overlay is - pause menu, shop, save UI, every scene.

  • legaia_asset::widget_script::scan recovers the programs structurally: find every call into the interpreter, resolve the argument each site materialises, keep the targets that parse as terminated programs with in-range opcodes and window ids.
  • Call sites that forward the pointer through a saved register (the shop pair among them) are not resolvable by that pass; those programs are pinned by reading the caller's disassembly.
  • The from-scratch engine resolves the same programs out of the user's disc at boot and runs them through the ported interpreter on the same shop transitions (legaia_engine_core::menu_widget).

Pinned programs

Byte-verified on the disc image. The shop pair is additionally pinned by the randomizer's Seru-trading vendor, which reuses exactly these scripts (legaia_patcher::seru_overlay::consts, shop flow).

VAFile offsetProgramCaller
0x801E4E380x16620[05][01 21][01 2A][01 20][01 28][01 22][00] - tick, then open vendor plate, picker, gold box and two panelsshop picker open, FUN_801DAFD4
0x801E4E540x1663C[04 28][04 2A][04 22][00] - close the picker windows, keep gold + vendor plateshop Sell transition, FUN_801DAFD4
0x801E4A780x16260[05][00] - global tick onlymenu-open staging (multiple callers)
0x801E4D50 / 0x801E4D780x16538 / 0x16560[01 07][00] - open window 7spell level-up notice, FUN_801D9280 / FUN_801D9594
0x801E4EA8 / 0x801E4EDC0x16690 / 0x166C4[01 1F][00] - open window 31Point Card toast, FUN_801DB7F4 / FUN_801DB380

How we know

Function / siteAddressWhat it provesEvidence
Interpreter entryFUN_801D6628Takes a program pointer; 4-byte strideDisassembly of PROT 0899 at slot-A base 0x801CE818
Opcode range check0x801D6680sltiu v0, opcode-1, 0xd - 13 handlers, 0x00 falls outDisassembly
Jump table0x801CED70The 13 handler addressesDisassembly
Terminator re-read0x801D6854lbu v0,0x0(s4) after each dispatch - a zero byte ends the programDisassembly
Window-table index0x801E4738 + id*0x10Byte 1 is a window id, not an actor or animation idDisassembly of the base materialisation
Program bytesfile 0x16260..0x16740The pinned programs above exist on the disc as listedcrates/asset/tests/widget_script_real.rs (disc-gated)

Source of record: docs/formats/window-script.md.

History: the "sprite-walk interpreter" reading

The interpreter was once read as the title screen's sprite-walk interpreter with an ANM-trigger opcode, which led to a hunt for a per-scene program carrier. Its base materialisation indexes the window descriptor table, byte 1 is a window id, and no arm of the 13-way dispatch hands off an animation id - so it is the menu overlay's window-widget interpreter and the programs are overlay-resident data. Recorded in do-not-re-walk.

See also