Window widget scripts Confirmed
When the shop opens, five UI windows slide onto the screen in one coordinated motion - the
vendor's name plate, the Buy/Sell picker, the gold box and two panels. That entrance is data: a tiny
bytecode program interpreted by the menu overlay's window-script VM, FUN_801D6628 (Ghidra's
name for the traced routine at that RAM address; an overlay is a chunk of code the game loads
into RAM on demand - the menu overlay, archive entry PROT 0899, hosts the pause menu, shop
and save UI). The programs themselves are resident in the same overlay image, a small program table in
its data segment - not in a scene file or an asset bundle. This page is the byte-level spec; the
interpreter is the actor / sprite VM.
Confidence
Confirmed. The instruction shape and dispatch come from the interpreter's disassembly
(fixed 4-byte stride, zero-opcode terminator, sltiu range check over the 13-entry jump table
at 0x801CED70); the program contents are byte-verified on the disc image, and the shop pair
is additionally pinned by the randomizer's seru-trading vendor, which reuses exactly these scripts.
Parser + scanner: legaia_asset::widget_script; disc pins in
crates/asset/tests/widget_script_real.rs.
Instruction encoding
Each instruction is exactly 4 bytes; a zero opcode byte ends the program:
+0x00 u8 opcode ; 0x01..=0x0D dispatch via the jump table at 0x801CED70;
; 0x00 terminates
+0x01 u8 window_id ; index into the 52-record window descriptor table at
; 0x801E4738 - the VM computes 0x801E4738 + id*0x10 and
; reads the record's x/y as the default coordinates
+0x02 u16 operand ; little-endian; packed position for opcodes 0x02/0x09
; (x = (w >> 7) & 0x1FE, y = w & 0xFF), style byte for
; 0x03, zero elsewhere on disc
Opcodes observed in disc programs: 0x01 (open at home), 0x02 (open at packed
position), 0x04 (close), 0x05 (global tick), 0x06 (motion-flag
clear), 0x0A (close / re-open / slide-back composite).
Where the programs live
The referenced programs cluster in one data region of the menu overlay image (file
0x16260..0x16740, VA 0x801E4A78..0x801E4F58). Each caller materialises a program
pointer with a lui/addiu instruction pair (or forwards one through a saved
register) and calls FUN_801D6628(&program). The parser's scanner recovers the programs
structurally: decode every jal FUN_801D6628 word in the image, resolve each call site's
argument materialisation, and keep the targets that parse as terminated programs with in-range opcodes
and window ids. Because the table is overlay data at fixed addresses, the programs are resident whenever
the menu overlay is - every scene, per boot, no per-scene lookup.
Pinned programs
| VA | Program | Caller |
|---|---|---|
0x801E4E38 | [05][01 21][01 2A][01 20][01 28][01 22][00] - open vendor plate, picker, gold box + two panels | shop picker open, FUN_801DAFD4 |
0x801E4E54 | [04 28][04 2A][04 22][00] - close the picker windows, keep gold + vendor plate | shop Sell transition, FUN_801DAFD4 |
0x801E4A78 | [05][00] - global tick only | menu-open staging |
0x801E4D50 / 0x801E4D78 | [01 07][00] - open window 7 | spell level-up notice |
0x801E4EA8 / 0x801E4EDC | [01 1F][00] - open window 31 | Point Card toast |
The clean-room 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).