Implement mounted append AUTORUN boot

This commit is contained in:
gamer147
2026-07-24 13:03:43 -04:00
parent 93486afade
commit 8f0c40f43f
16 changed files with 355 additions and 86 deletions

View File

@@ -83,7 +83,7 @@ noop_headless = false
source = "investigation"
confidence = "high"
depends_on = []
evidence = "native-RE (Ghidra): handler FUN_0041bc90 -> loader FUN_0040e980 -> resolver FUN_0044f390 indexes an 80-byte record table (base [ctx+0x414], count [ctx+0x40c]) at base+id*0x50 = the SYS4INI record layout {name[64],arc_id@0x40,file_number@0x44,offset@0x48,size@0x4c}. Confirmed statically: all 297 distinct corpus call-script ids resolve to a .BIN script with a semantically-exact name (0x1ab->ADDITEM, 0x2ae7->MES, 0x143->BUNKI, 0x329d->CALCREVISE), 0 out-of-range, 0 pack-branch. See docs/engine-re.md + name-resolution.md #1."
evidence = "native-RE (Ghidra): handler FUN_0041bc90 -> loader script_frame_load_resource@0x40e980 -> resolver asset_open_indexed_entry@0x44f390 indexes an 80-byte record table (FileDB+0x414 base, FileDB+0x40c count) at base+id*0x50 = the SYS4INI record layout {name[64],arc_id@0x40,file_number@0x44,offset@0x48,size@0x4c}. The FileDB is embedded at EngineCtx+0x9c24c, making those EngineCtx+0x9c660/+0x9c658. Confirmed statically: all 297 distinct base-corpus call-script ids resolve to a .BIN script with a semantically-exact name (0x1ab->ADDITEM, 0x2ae7->MES, 0x143->BUNKI, 0x329d->CALCREVISE), 0 out-of-range. See docs/engine-re.md + name-resolution.md #1."
confirm_by = ""
details = """
op 0x03 (call-script, argc 1): `call-script <id>`. RESOLVED — the id is a direct RAW index into
@@ -95,11 +95,13 @@ Native mechanism (dispatch table `handler(op)=ctx[0x26c93+op]`, op 0x03 -> FUN_0
2. FUN_0040e980 (loader): opens the resource by id, reads the 0x20-byte SYS4 header, checks magic,
allocates per-frame code/local buffers from the header var-counts, reads the bytecode body,
pushes a script frame (stride 0x1e = 30 dwords, indexed by ctx[0x14f45]).
3. FUN_0044f390 (resolver): record = [ctx+0x414] + id*0x50. Tries a LOOSE OVERRIDE first
(CreateFileA on record.name -> mod/patch hook point), else opens archive [record.arc_id*0x100 +
ctx+0x410], SetFilePointer to record.offset, size = record.size.
(High-byte-tagged ids `id & 0xff000000` select an alternate pack via [ctx+0x3028]; UNUSED by the
corpus -- 0/297 ids have a high byte.)
3. asset_open_indexed_entry@0x44f390 (resolver): its `this` is the embedded FileDB, not EngineCtx.
Base record = [FileDB+0x414] + id*0x50. It tries a LOOSE OVERRIDE first (CreateFileA on
record.name -> mod/patch hook point), else opens archive [record.arc_id*0x100 + FileDB+0x410],
SetFilePointer to record.offset, size = record.size.
High-byte-tagged ids select [FileDB+0x3028 + signed_selector*4] and index the chosen AAI by the
low 24 bits. The base corpus has 0/297 explicit high-byte call-script operands; INIT2 op 0x143
supplies mounted record-zero ids dynamically.
Companion op 0x8f `call` is INTRA-script (a local JSR), not cross-script -- see its entry.
This also names the whole call graph statically (build/callscript-names.json).
"""
@@ -2975,14 +2977,29 @@ argc = 0
abi_source = "kelebek+decode-validated"
[opcode.semantics]
name = "u00415FB0"
category = "unknown"
summary = ""
name = "run-mounted-append-autoruns"
category = "control"
summary = "() - enqueue record zero from every mounted nonzero AAI selector in ascending selector order, then execute those packed scripts serially before resuming the caller."
noop_headless = false
source = "kelebek"
confidence = "low"
source = "investigation"
confidence = "high"
depends_on = []
evidence = ""
evidence = "Ghidra /v2: op_0x143_run_mounted_append_autoruns@0x4172f0 scans mounted_aai_catalogs[1..255] at EngineCtx+0x9f278, enqueues selector<<24 through script_launch_queue_enqueue@0x40f820 while dispatch is suppressed, advances the caller PC, then tail-dispatches through script_launch_queue_dispatch_next@0x40f6e0. Positive queue entries load in reserved frame 37 with return sentinel -10; op_0x2_exit_or_return_frame@0x417940 dispatches the next queued entry or restores the suspended caller. Corpus: the sole site is INIT2@0x17f, after its 23 base INIT children and global/array setup and immediately before TUNE.BIN."
details = """
The opcode does not look up an AUTORUN filename. For each non-null mounted catalog pointer in selector
slots 1 through 255, it constructs the packed id `selector << 24`, whose low 24-bit record index is zero.
At Himegari cold boot the native catalog loader has already mounted APPEND01 in selector 1 before SYSTEM4
starts. SYSTEM4 calls INIT2; INIT2 runs EBINIT through SCINIT plus BTANINIT2, completes its base registry
setup, executes this opcode, and resumes at its following TUNE call only after every queued record-zero
script returns. Installed selector 1 record zero is `$1$AUTORUN.BIN`, which applies the append INIT deltas
and registrations. This is a serial base-then-append patch boundary, not a filename overlay.
PORT = IMPLEMENTED. `IScriptProvider.MountedAppendSelectors` exposes mounted selector identity without
coupling the VM to the SYS4 catalog type. The opcode snapshots, deduplicates, and sorts selectors, constructs
each packed record-zero id, and runs the resolved script through the ordinary nested-frame machinery before
resuming INIT2. Focused tests protect ordering, packed-id construction, caller suspension, and unresolved
record-zero failure. Natural SYSTEM4 boot proves BTANINIT2 -> `$1$AUTORUN.BIN` -> `$1$EBINIT.BIN` -> TUNE.
"""
[[opcode]]
op = 0x144