Implement root reload and title debug launcher
This commit is contained in:
@@ -101,7 +101,8 @@ S:\Game Hacking\Eushully\Himegari\ ← workspace root (three siblings)
|
||||
│ └── Age.Engine/Sys4/ runtime catalog parser, loose-first bounded ALF asset store,
|
||||
│ script provider, AGF/LZSS and Windows CUR decoders, and resource facade
|
||||
├── tools/frida/ runtime-capture + engine-dump scripts (see tools/frida/README.md)
|
||||
└── godot/ DELIVERABLE — the Godot/C# ADV front-end (references Age.Engine)
|
||||
└── godot/ DELIVERABLE — the Godot/C# ADV front-end (references Age.Engine),
|
||||
including the TITLE-only F4 debug scene launcher
|
||||
```
|
||||
|
||||
The disposable `build/page-map-<SCENE>.jsonl` files are produced by normal Godot runs and map runtime ADV
|
||||
|
||||
@@ -253,10 +253,55 @@ in one VM; Godot `--boot` remains only for an explicit direct-scene diagnostic s
|
||||
deterministic first-process-run behavior, not a profile/save decision. `SYSTEM4@0x29a` calls op `0x130` and
|
||||
executes `LOGO.BIN@0x2a4` then `OP.BIN@0x2a7` when its result is nonzero. Native
|
||||
`op_0x130_get_initial_root_run@0x4295b0` returns `EngineCtx+0x54ff0`; context construction initializes that
|
||||
field to one, while `op_0x9_handler` is its only later writer and clears it before resetting engine state and
|
||||
reloading root script id zero. The port now owns the same flag in the persistent VM: it begins at one,
|
||||
`0x130` writes it, and the existing op-`0x9` lifecycle boundary clears it. It is not a boot seed or profile
|
||||
value. Full native whole-stack root reload remains part of the broader scene-coordinator work.
|
||||
field to one, while `op_0x9_reset_scene_and_reload_root` is its only later writer and clears it before
|
||||
resetting engine state and reloading root script id zero. The port now owns the same flag in the persistent
|
||||
VM: it begins at one,
|
||||
`0x130` writes it, and op `0x9` clears it as part of the whole-stack root reload described below. It is not
|
||||
a boot seed or profile value.
|
||||
|
||||
**Whole-stack root reload (`0x9`, 2026-07-20).** Native
|
||||
`op_0x9_reset_scene_and_reload_root@0x418f50` is not an ordinary child-script return. It clears the
|
||||
initial-root flag, calls `script_frame_dispose@0x40e610` across all 40 interpreter slots, cancels timed and
|
||||
input-callback state, invokes `scene_context_init_reset@0x40b3b0`, resets hotspot/input services, and finally
|
||||
loads raw script resource zero with `script_frame_load_resource(..., 0)`. Raw SYS4INI index zero is
|
||||
`SYSTEM4.BIN` in Himegari.
|
||||
|
||||
The scene reset owns interpreter run state, ADV input/skip/auto state, retained gfx objects and command
|
||||
queues, text/render buffers, and—on the normal fresh-session path—the 1000 ordinary surface/movie slots.
|
||||
It does not clear the global VM bank or engine configuration. The port now mirrors that boundary: an `0x9`
|
||||
request propagates through every nested `call-script` frame without executing any caller continuation,
|
||||
clears scene-owned VM/Godot presentation and input state, cancels deferred SFX starts without unloading or
|
||||
stopping active channels/BGM, preserves global/external-global banks and process-owned configuration/caches,
|
||||
then begins raw script zero at offset zero in the same VM session.
|
||||
The retained ADV history backlog remains intact for now because its lifetime across this reset has not yet
|
||||
been proven; only recording suppression is reset. Focused tests cover a three-frame unwind and raw-zero
|
||||
resolution to `SYSTEM4.BIN`.
|
||||
|
||||
**Frontend exit request is not a root reload (`0x1`, 2026-07-20).** Native
|
||||
`op_0x1_throw_exit_request@0x4162e0` constructs reason value one and raises the engine's non-returning C++
|
||||
control exception (`DAT_005a9710`). Its only two corpus sites establish the intent: TITLE executes it after
|
||||
the fifth main-menu action's sound and delay, while SYSTEM4 executes it after reporting an invalid execution
|
||||
mode. The Windows/frontend catch policy—full exit versus returning to title—is outside this opcode handler
|
||||
and is not implemented in the Godot frontend yet.
|
||||
|
||||
TITLE happens to contain a developer menu immediately after its `0x1`, including a `call-script` to
|
||||
`DEBUG.BIN`; that code is unreachable in the native flow because the handler never returns. The port still
|
||||
treats unknown `0x1` as a fall-through stub, so selecting the fifth TITLE action would expose that menu by
|
||||
accident. This is a known discrepancy, not a legitimate route for validating `0x9`. End-to-end visual
|
||||
validation of the native `SYSTEM4 -> TITLE -> child -> 0x9 -> SYSTEM4 -> TITLE` history therefore remains
|
||||
deferred until the frontend exit/return-to-title boundary or a natural game-over/completion route exists.
|
||||
|
||||
The unreachable developer menu nevertheless records the game's intended debug-scene handoff. Its two ADV
|
||||
viewer choices write `G[0]=1`, `G[0xaba5c]=-1`, `G[0x62ccf]=0`, and a raw script id into `G[0x699]`, then
|
||||
return TITLE with local result one. TITLE's outer loop performs its normal ADV input/skip exit pair and
|
||||
returns to SYSTEM4. SYSTEM4 resumes at `0x2b0`; the nonzero `G[0xaba5c]` suppresses SCJUMP remapping, so the
|
||||
coordinator keeps the requested `G[0x699]`, performs its normal scene-entry setup, and calls that script at
|
||||
`0x477`. Other developer choices directly call utility scripts such as `DEBUG.BIN` from TITLE instead.
|
||||
|
||||
This also confirms three distinct cleanup owners around a debug launch: the selected script's own terminal
|
||||
subroutines, SYSTEM4's ordinary post-child cleanup (including all ten SFX channels and retained scene
|
||||
objects), and op `0x9`'s whole-stack scene reset when that opcode is actually executed. An arbitrary VM
|
||||
script replacement would bypass the first two and is not equivalent to native scene dispatch.
|
||||
|
||||
Both child scripts create/draw 800x600 surface 42 and call op `0x20f`; their resource ids are universal raw
|
||||
SYS4INI indexes `0x335f`/`LOGO.AGF` and `0x3364`/`OP.AGF`. `ED.BIN` is the only other corpus user, with
|
||||
|
||||
@@ -198,6 +198,11 @@ Operand 2 names the base cell itself: a global-bank operand produces a global re
|
||||
|
||||
## control
|
||||
|
||||
### 0x1 `throw-exit-request` (throw-exit-request, argc 0)
|
||||
- **summary:** () - raise the engine's non-returning exit/fatal-abort control exception with reason value 1. TITLE uses it for the fifth main-menu action; SYSTEM4 uses it after reporting an invalid execution mode.
|
||||
- **grounding:** source=investigation, confidence=high
|
||||
- **evidence:** Ghidra /v2: op_0x1_throw_exit_request@0x4162e0 constructs local value 1 and calls __CxxThrowException_8 with type descriptor DAT_005a9710; the handler is non-returning. Corpus has exactly two sites: TITLE@0x393 after the fifth menu action's sound/sleep, and SYSTEM4@0x5b9 after printing 'invalid execution mode'. TITLE bytecode following 0x1 builds a developer debug menu and can only be reached when a port incorrectly treats 0x1 as a fall-through stub. The frontend catch/prompt policy remains a separate unimplemented boundary.
|
||||
|
||||
### 0x3 `call-script` (call-script, argc 1)
|
||||
- **summary:** load & call another SYS4 script by id; id = RAW index into the SYS4INI file table (asset-index). Pushes a script frame; returns to caller when the callee ends.
|
||||
- **grounding:** source=investigation, confidence=high
|
||||
@@ -222,11 +227,11 @@ This also names the whole call graph statically (build/callscript-names.json).
|
||||
|
||||
|
||||
### 0x9 `exit-script` (exit-script, argc 0)
|
||||
- **summary:** () - terminate the active script lifecycle and return to root script id 0. Before the native engine resets/reloads the root, it clears the initial-root-run flag queried by op 0x130 so LOGO/OP are not replayed.
|
||||
- **summary:** () - discard the complete active script stack, reset scene-owned engine services, and load raw script resource 0 as the new root. The global VM banks and process-owned configuration survive; the initial-root-run flag queried by op 0x130 is cleared so LOGO/OP are not replayed.
|
||||
- **grounding:** source=investigation, confidence=high
|
||||
- **evidence:** Ghidra /v2: op_0x9_handler@0x418f50 stores zero to EngineCtx+0x54ff0, calls scene_context_init_reset, and loads root script resource id 0. Corpus sites are terminal scene/control exits rather than ordinary local returns.
|
||||
- **evidence:** Ghidra /v2: op_0x9_reset_scene_and_reload_root@0x418f50 clears EngineCtx+0x54ff0, disposes all 40 interpreter-frame slots with script_frame_dispose@0x40e610, aborts timed/input callback state, calls scene_context_init_reset@0x40b3b0, resets hotspot/input services, optionally releases AutoFreeTex surfaces, then calls script_frame_load_resource(...,0). The scene reset clears interpreter/ADV/input/retained-gfx state and normally releases the 1000 surface/movie slots; it does not clear the VM global bank or engine configuration. Corpus sites are terminal scene/control exits rather than ordinary local returns.
|
||||
|
||||
The port retains its earlier frame/session-boundary representation of root return, but now performs the proven process-lifecycle side effect by clearing its VM-owned initial-root-run flag. A faithful whole-stack root reload remains part of the broader persistent scene-coordinator work, not the startup-movie slice.
|
||||
Implemented as a whole-stack root-reload boundary in the persistent VM. A request propagates through every nested call-script frame without resuming caller instructions, clears VM/host scene presentation and input state, cancels deferred SFX starts while preserving active/process-owned audio, preserves globals/external globals and process-owned host configuration/caches, then resolves raw resource 0 through the script provider and starts it at offset zero. The retained history backlog is deliberately preserved pending a separate proof of its native lifetime; recording suppression is reset.
|
||||
|
||||
### 0x7b `coroutine-save-yield-handlers` (u0041ADB0, argc 2)
|
||||
- **summary:** (handler1_pc)(handler2_pc) — scene-coroutine: save the two per-frame yield/resume handler PCs. Native writes op1→ctx[0x6da88+idx*4], op2→ctx[0x6db28+idx*4] (idx=ctx[0x53d14] script-context index); its generic handler prologue records the 5-dword instruction length. SC0000 0x79: `0x7b label_3c9 label_41e` registers the ADV per-frame render→poll→yield handlers. Part of the scene-coroutine framework (see engine-re.md §Scene-coroutine framework); pairs with 0x7c (resume) + 0x140 (loop iterator).
|
||||
@@ -293,7 +298,7 @@ Native handler sleep_op_0xc8 @0x420ec0 is NON-BLOCKING: it arms a timer (sleep_t
|
||||
### 0x130 `get-initial-root-run` (get-initial-root-run, argc 1)
|
||||
- **summary:** (out) - write the engine's initial-root-run flag. It is initialized to 1 when the AGE context is constructed and cleared by op 0x9 before that opcode resets state and reloads root script id 0. SYSTEM4 uses the value to call LOGO.BIN and OP.BIN only on the process's initial root run.
|
||||
- **grounding:** source=investigation, confidence=high
|
||||
- **evidence:** Ghidra /v2: op_0x130_get_initial_root_run@0x4295b0 copies EngineCtx+0x54ff0 to operand 1. FUN_00413860 initializes +0x54ff0 to 1 at 0x413cc7/0x413d15; op_0x9_handler@0x418f50 is its only later writer and clears it before scene_context_init_reset plus script_frame_load_resource(...,0). Corpus: sole site SYSTEM4@0x29a branches to LOGO.BIN then OP.BIN only when the returned value is nonzero.
|
||||
- **evidence:** Ghidra /v2: op_0x130_get_initial_root_run@0x4295b0 copies EngineCtx+0x54ff0 to operand 1. FUN_00413860 initializes +0x54ff0 to 1 at 0x413cc7/0x413d15; op_0x9_reset_scene_and_reload_root@0x418f50 is its only later writer and clears it before scene_context_init_reset plus script_frame_load_resource(...,0). Corpus: sole site SYSTEM4@0x29a branches to LOGO.BIN then OP.BIN only when the returned value is nonzero.
|
||||
|
||||
Implemented as process-lifecycle state owned by the persistent VM: it begins at one and op 0x9 clears it. It is not a script global, save/profile value, command-line seed, or script-name special case.
|
||||
|
||||
@@ -796,10 +801,6 @@ op 0x90 (u0041BEB0, argc 7): `0x90 x y w h tgt_a tgt_b tgt_c`. Kelebek left it "
|
||||
|
||||
## unknown
|
||||
|
||||
### 0x1 `u004149C0` (u004149C0, argc 0)
|
||||
- **summary:** —
|
||||
- **grounding:** source=kelebek, confidence=low
|
||||
|
||||
### 0x2 `exit` (exit, argc 0)
|
||||
- **summary:** —
|
||||
- **grounding:** source=kelebek, confidence=med
|
||||
|
||||
@@ -112,8 +112,8 @@ that is one at context construction and cleared only when op `0x9` resets/reload
|
||||
SYSTEM4 calls `LOGO.BIN` and `OP.BIN` only while that flag is nonzero. The former stubbed-zero output
|
||||
explained the direct jump to TITLE. LOGO and OP then use the modal movie op
|
||||
`0x20f` with raw catalog movies `0x335f`/`LOGO.AGF` and `0x3364`/`OP.AGF`; existing `0x236` is the distinct
|
||||
non-modal, scene-local movie-to-surface path. The VM now models the initial-root flag and clears it at its
|
||||
existing op-`0x9` lifecycle boundary. Godot resolves a typed raw MPEG asset, reuses the asynchronous decoder
|
||||
non-modal, scene-local movie-to-surface path. The VM now models the initial-root flag and clears it at the
|
||||
op-`0x9` whole-stack root-reload boundary. Godot resolves a typed raw MPEG asset, reuses the asynchronous decoder
|
||||
and retained compositor, and parks the VM until EOF or mouse/Accept/Cancel input. Focused natural-boot tests
|
||||
prove `LOGO -> OP -> INIT -> TITLE` ordering and exact movie operands. MPEG audio remains explicitly deferred
|
||||
until the decoder abstraction has an engine-owned synchronized audio/volume contract.
|
||||
@@ -124,6 +124,15 @@ Replace the single-SC0000-root assumption with an application-owned session that
|
||||
SYSTEM4's computed `call-script` is the authoritative scene coordinator: child scenes return to that frame,
|
||||
while globals, the host, and intentional retained state remain owned by the same live VM session.
|
||||
|
||||
**Root-reload boundary implemented (2026-07-20).** Ordinary op `0x2` child exits still return to their
|
||||
calling SYSTEM4 frame. Op `0x9` is the distinct native reset path: it discards the complete active script
|
||||
stack, clears scene-owned graphics/input/ADV state, cancels deferred SFX starts while preserving active
|
||||
audio, preserves global banks and process-owned host state, and starts raw script resource zero
|
||||
(`SYSTEM4.BIN`) at offset zero. The implementation propagates the boundary
|
||||
through nested calls without running any caller continuation and records the new root frame with
|
||||
`FrameCause.RootReload`. Native RE and the one intentional history-lifetime exception are documented in
|
||||
`docs/engine-re.md`; the history backlog remains preserved until its ownership is proven rather than guessed.
|
||||
|
||||
Required responsibilities:
|
||||
|
||||
- Own global integer/string banks and any proven external/profile state across scenes.
|
||||
@@ -134,9 +143,97 @@ Required responsibilities:
|
||||
- Expose deterministic transition evidence: outgoing scene, reason/decision, incoming scene, and state
|
||||
summary suitable for tests.
|
||||
|
||||
Completion evidence: SYSTEM4 reaches a computed child script in one VM, the child returns to SYSTEM4,
|
||||
selected globals and system-owned state survive, and script-owned boundary cleanup releases scene-local
|
||||
presentation state.
|
||||
Completion evidence now present: SYSTEM4 reaches computed child scripts in one VM; ordinary children return
|
||||
to SYSTEM4; op `0x9` performs a tested whole-stack reload of SYSTEM4; selected globals and process-owned state
|
||||
survive; and scene-owned presentation/input state is released. Manual validation of a natural gameplay
|
||||
route through the first `0x9` remains deferred: Himegari's readily accessible return-to-title choice belongs
|
||||
to the still-unimplemented frontend exit-request policy, while the other known natural paths require later
|
||||
gameplay, game over, or completion. Do not use TITLE's currently exposed post-`0x1` developer-menu
|
||||
fallthrough as evidence; native `0x1` is non-returning. See `docs/engine-re.md`.
|
||||
|
||||
**Godot debug scene launcher (2026-07-20; implemented and manually validated).** The first version
|
||||
is deliberately narrower than arbitrary hot swapping:
|
||||
|
||||
- Expose an F4-style Godot overlay only while `TITLE.BIN` is the persistent VM's active SYSTEM4 child.
|
||||
- Resolve the chosen `.BIN` through the existing SYS4 catalog, then ask the VM to return the current TITLE
|
||||
child frame with the game-authored coordinator writes (`G[0]=1`, `G[0xaba5c]=-1`, `G[0x62ccf]=0`, and
|
||||
selected packed id in `G[0x699]`) applied on the VM thread.
|
||||
- Let SYSTEM4 resume at `0x2b0` and execute its real entry wrapper and computed `call-script`; do not replace
|
||||
the VM root or call the selected scene directly from Godot.
|
||||
- Disable switching while another scene is active. That scene must reach its own terminal cleanup and then
|
||||
either return through SYSTEM4's post-child cleanup or execute its genuine op `0x9`. A separate clean
|
||||
relaunch remains the escape hatch for a stuck/incomplete scene.
|
||||
|
||||
The runtime now has a generic debug-only "return this exact active child frame with queued global writes"
|
||||
request, thread-safe frame-generation/stack reporting, and the distinct `DebugReturned` trace outcome. TITLE
|
||||
does not park in ADV op `0x72`: its visible menu continuously polls input and executes a 1 ms op-`0xc8` sleep
|
||||
at `TITLE@0xe5`. The request therefore targets the observed active frame generation and is consumed by the
|
||||
VM thread at its next completed opcode boundary, before another TITLE opcode can execute. `SignalInput` is
|
||||
used only if the target happens to be in a real ADV wait, avoiding a stale signal that could advance the
|
||||
selected child. Synthetic coordinator tests cover both an ADV wait and TITLE's sleep/poll shape, selected-
|
||||
child dispatch, ordinary SYSTEM4 continuation, stale/ineligible request rejection, and selected-child
|
||||
op-`0x9` whole-stack propagation.
|
||||
|
||||
This launcher would provide the real visible TITLE→selected scene sequence and preserve the coordinator
|
||||
boundary, but it cannot manufacture valid late-game state. The current direct harness and opcode coverage
|
||||
suggest early ADV scenes and `DEBUG.BIN` are plausible targets; later scenarios, GAMECLEAR, battle/map, and
|
||||
profile-dependent scripts may still require progression data or missing opcodes. A startup-only/direct-scene
|
||||
selector is cheaper, but it is merely a UI for `--scene ... --boot` and provides no transition-lifecycle
|
||||
evidence. An unrestricted in-process switch would additionally require VM cancellation, task joining,
|
||||
movie/audio disposal, locator/trace regeneration, and an explicit global-state policy, so it is not a quick
|
||||
or trustworthy first version.
|
||||
|
||||
**Menu population and selection contract.** The runtime SYS4 catalog—not `build/` inventory—is the
|
||||
source of truth. Himegari currently has 481 unique base-catalog `.BIN` records: 136 `SC####`, 164 `SP*`, 8
|
||||
`DEBUG*`, 29 initializer-named scripts, and 144 other named scripts. Each menu row keeps the packed resource
|
||||
id as its identity and carries display name, pack selector, raw index, archive, size, and category; names are
|
||||
labels rather than keys so future append-pack collisions remain representable. Population should enumerate
|
||||
base `Catalog.Files` plus every mounted append catalog, exclude placeholders/non-BIN records, and compute
|
||||
`packed_id = (pack_id << 24) | raw_index` without parsing all scripts up front. The selected script is decoded
|
||||
and validated only when Launch is pressed; an unsupported decode reports an error and leaves TITLE running.
|
||||
The currently mounted append pack contributes 39 additional `.BIN` records, so the shipped launcher smoke
|
||||
test sees 520 distinct packed script ids.
|
||||
|
||||
The initial UI groups entries rather than implying every BIN is a standalone scene:
|
||||
|
||||
- **Scenario:** `SC####.BIN`, naturally sorted by number.
|
||||
- **Secondary/event:** `SP*.BIN`, naturally sorted by name and suffix.
|
||||
- **Debug:** `DEBUG*.BIN`.
|
||||
- **Other/expert:** every remaining script; the separate **All** filter includes every category. Initializers,
|
||||
callbacks, data routines, and modal UI scripts may require caller-owned state and may immediately return
|
||||
or corrupt the live session.
|
||||
|
||||
`SYSTEM4.BIN` and `TITLE.BIN` are not launchable in the first version; recursively dispatching either through
|
||||
SYSTEM4's child slot is not a scene test. Search is case-insensitive over name and hexadecimal/decimal packed
|
||||
id. The detail pane shows name, category, packed/raw id, archive, size, and the fixed warning that launch uses
|
||||
the current live global/profile state. Compatibility or opcode-gap badges are deferred until coverage logic
|
||||
has an engine-owned runtime API; the menu must not parse generated Markdown or call Python tooling.
|
||||
|
||||
The implementation should leave one explicit extension point for future test sequences:
|
||||
`DebugLaunchPreset(label, packed_script_id, extra_global_writes, note)`. Catalog rows use only the four
|
||||
coordinator writes above; profile-authored presets may later add proven story/progression globals without
|
||||
turning the menu into a free-form state editor or save backend. Arbitrary PC/offset jumps are out of scope.
|
||||
|
||||
**Implementation order.** (1) Add catalog script-entry enumeration with packed ids and unit coverage for
|
||||
base/append mounts, placeholders, duplicate names across packs, and category/sort/filter behavior. (2) Add a
|
||||
generic VM debug request targeted at an exact active frame generation; it applies an immutable set of global
|
||||
writes on the VM thread and returns that child at the next opcode boundary. Test SYSTEM4→TITLE→selected child,
|
||||
ordinary child return/cleanup continuation, op-`0x9` propagation, TITLE's sleep/poll loop, and stale/ineligible
|
||||
request rejection. (3) Add the Godot F4 overlay (`PopupPanel`, search/category controls, `ItemList`, detail
|
||||
pane, Launch/Cancel), consume all overlay input, and enable Launch only for the active `SYSTEM4 > TITLE`
|
||||
stack. (4) Add a Godot smoke test for catalog population and request wiring, then
|
||||
manually validate `TITLE -> DEBUG -> 0x9 -> SYSTEM4 -> TITLE` before expanding the selectable categories or
|
||||
adding presets.
|
||||
|
||||
Steps 1–4 are complete. F4 opens the Godot `PopupPanel` only for the exact active
|
||||
`SYSTEM4.BIN > TITLE.BIN` stack; search, category filters, packed-id metadata, guarded Launch, and Cancel are
|
||||
live. `SYSTEM4.BIN` and `TITLE.BIN` remain visible but unlaunchable. While the panel is open, AGE gameplay
|
||||
input is not forwarded. Launch reparses the selected packed id before queuing any writes. The threaded Godot
|
||||
selftest constructs the catalog and panel and currently reports 520 unique packed scripts. Manual validation
|
||||
confirmed `TITLE -> F4 -> DEBUG.BIN`: its four scripted ADV pages at `0xc7`, `0x110`, `0x17b`, and `0x1ed`
|
||||
were presented, its terminal op `0x9` at `0x1fb` ran, and SYSTEM4 reconstructed the visible TITLE menu. No
|
||||
launcher/session-lifecycle discrepancy was observed. DEBUG-specific content oddities are not acceptance
|
||||
failures for this developer route and remain out of scope unless they reproduce in a normal game script.
|
||||
|
||||
## Stage B2 — Faithful full boot
|
||||
|
||||
|
||||
@@ -162,6 +162,16 @@ render texture ops (no GPU context) — run windowed for real scenes. User args
|
||||
`--scene SC0000 --boot --shot-sequence ... --gfx-log ...` to distinguish control-flow stalls from retained-object/compositor
|
||||
failures at an exact bytecode boundary. Relative output paths are project-relative (`godot/`).
|
||||
|
||||
**Godot debug scene launcher:** press **F4** while the natural boot is showing TITLE. TITLE's visible menu is
|
||||
a live 1 ms sleep/input-poll loop rather than an ADV `wait-for-input`; the launcher identifies that exact
|
||||
active child frame and returns it cooperatively at the next completed opcode boundary. The overlay enumerates
|
||||
all base and mounted-append `.BIN` records by packed id, with All/SC/SP/Debug/Other filters, name or exact
|
||||
hexadecimal/decimal id search, and archive/raw-id details. `SYSTEM4.BIN` and `TITLE.BIN` are intentionally
|
||||
unlaunchable. Launch is accepted only for the exact `SYSTEM4.BIN > TITLE.BIN` wait stack; it returns TITLE
|
||||
with the coordinator globals queued on the VM thread, then lets SYSTEM4 perform its normal computed child
|
||||
call. F4 outside TITLE prints an unavailable reason and changes no state. Cancel or Escape closes the panel.
|
||||
The launcher does not seed story/profile state, jump to byte offsets, or force-switch an active child scene.
|
||||
|
||||
**Godot page locator:** every normal run recreates `build/page-map-<SCENE>.jsonl`, adding one record per
|
||||
`wait-for-input` with the run-relative page, page-start location, canonical wait script/offset, last
|
||||
show-text instruction and string offsets, text, and nested call stack. Use `--page-map <jsonl>` to override
|
||||
|
||||
Reference in New Issue
Block a user