Land SYSTEM4-rooted Godot boot

This commit is contained in:
gamer147
2026-07-20 18:13:32 -04:00
parent 7250de7fea
commit 097473fe16
18 changed files with 385 additions and 111 deletions

View File

@@ -75,13 +75,13 @@ highest-risk area of the port. This doc is the steering state; it feeds the A2b
AGE game with the same container — **the "scope" was just which SYS4INI section the scene lives in.**
(The old `play-bgm 5→BGM006` validation point was a mis-attribution — the real game plays BGM005.)
**System/global-id exception (identified 2026-07-10; not yet implemented).** Some SYSTEM4 loads use
**System/global-id exception (identified 2026-07-10; implemented).** Some SYSTEM4 loads use
the SYS4INI record's universal `raw_index` directly, including the two `@` placeholder records, rather
than a scene-local manifest index. `SYSTEM4.BIN` writes `G[0x69b]=0x337e`, then
`set-texture(G[0x69b], slot=0x11)`. SYS4INI `raw_index 0x337e` is `DATA1/SO001.AGF`, the shared
800×300 RGBA system-chrome sheet. The filtered `files[]` list omits placeholders, so treating `0x337e`
as a `files[]` position currently mis-resolves it to `SETROUTE.BIN`. This path needs a distinct
`raw_index → entry` lookup; the scene-manifest rule above remains correct for SC texture/voice ids.
800×300 RGBA system-chrome sheet. `ResourceMap.ResolveTexture` therefore tries the active script's
scene manifest first and then the distinct universal raw-id lookup; the scene-manifest rule above
remains correct for ordinary SC texture/voice ids.
*How we got here (condensed):* first confirmed `resId == file_number` via Frida load-order correlation
for SC0000's opening, but `file_number` is not globally unique so a per-scene "scope" was needed. A long
@@ -104,16 +104,18 @@ highest-risk area of the port. This doc is the steering state; it feeds the A2b
model approximated the game's immediate-mode blit-onto-slot-0 canvas. See `docs/phase-a-slice-plan.md`
(A2b section) for the implementation history and current retained-object model.
**Current system-chrome shortcut/gap (confirmed 2026-07-10).** `Main --boot` executes only
`INITCONFIG/INIT2/INIT` through `CaptureHost` and copies their globals into the scene VM; it does not
replay SYSTEM4's graphics side effects through `GodotAdvHost`. `convert_agf.py --scene SC0000` also
converts only SC0000's manifest, so `build/textures/SO001.BMP` is absent. `CALLBACK_WINDOW.BIN` expects
slot `0x11` to already contain SO001, draws the 800×227 textbox from `(0,0)`, and crops the lower-right
buttons from the same sheet. In the port slot 17 is unpopulated, so retained handle `0xd2f0` resolves as
a colored surfaceless object and the compositor draws the observed opaque black fill. A temporary decode
verified SO001 is 800×300, 32-bpp, with substantial per-pixel alpha; the current rasterizer already
consumes source alpha. The missing prerequisites are system-asset resolution/conversion and retained
slot initialization, not new textbox drawing or button interaction.
**System chrome ownership (resolved 2026-07-20).** The normal Godot entry now runs SYSTEM4 as the live
root, so its SO000/SO001 loads, ADV-layout definitions, and retained slot initialization execute through
`GodotAdvHost` before TITLE and child scenes. Asset lookup decodes VFS-owned AGF bytes directly and does
not depend on a scene-limited converted BMP. `CALLBACK_WINDOW.BIN` consequently inherits slot `0x11`
with SO001 and can crop its textbox/buttons normally. The explicit `--scene SC0000 --boot` diagnostic
still injects the same known inherited layout and surface state because it intentionally bypasses
SYSTEM4; that shortcut is no longer the shipped/default route.
The active manifest is frame-local, not fixed to the root scene: every VM call frame brackets host work
with its script context. `set-texture` resolves the local id at load time and retains the normalized raw
catalog id in the graphics surface, so that surface remains stable after a nested helper returns or a
sibling script becomes active. Voice, SFX, and movie calls likewise resolve against the executing frame.
4. **Audio.** **✅ WIRED (2026-07-06), VFS bytes complete (2026-07-11).** `IHost.PlayBgm/PlayVoice` +
VM dispatch (`play-bgm` 0xbf / `play-voice` 0xc4, both argc 1); `ResourceMap.ReadAudio` opens the
resolved catalog entry through `IAssetStore`; `GodotAdvHost` passes the bytes to `Main`'s players

View File

@@ -245,9 +245,9 @@ optionally calls `LOGO.BIN` and `OP.BIN`, calls the one-op `INIT.BIN`, and enter
not a thin handle seed: it calls 23 data initializers in order (`EBINIT`, `CNINIT`, `ITINIT`, `SKINIT`,
`ILINIT`, `AFINIT`, `TRINIT`, `MAINIT`, `ALINIT`, `CDINIT2`, `MPINIT`, `LAINIT`, `OBINIT`, `STINIT2`,
`RTINIT`, `CGINIT`, `SPINIT`, `CTINIT`, `CVINIT`, `CIINIT`, `VIINIT`, `SCINIT`, `BTANINIT2`) and then
`TUNE.BIN`. The CLI `play --boot` nine-script list is therefore only a partial diagnostic approximation;
the Godot `--boot` path reaches the complete list indirectly because it executes `INIT2` with call-script
resolution enabled.
`TUNE.BIN`. The CLI `play --boot` nine-script list is therefore only a partial diagnostic approximation.
Godot now runs SYSTEM4 itself by default, so this complete sequence and its host-visible side effects execute
in one VM; Godot `--boot` remains only for an explicit direct-scene diagnostic such as `--scene SC0000`.
An existing native operand trace identifies every observed heap codebase by a 100% match against its static
instruction-offset set. The captured New Game route is:
@@ -262,6 +262,11 @@ SYS4INI id `0x22` (`SC0000.BIN`) when the mapping is zero, and executes computed
Thus normal scenes remain nested script frames under SYSTEM4 and return to it; the port should keep one
VM/host session rooted at SYSTEM4 rather than replace top-level VMs based on a host-invented scene result.
**Port landing (2026-07-20).** The no-argument Godot path is rooted at SYSTEM4 and renders TITLE without
manual inherited-layout or surface injection. A real-script integration test drives the same input callback
lifecycle through TITLE and GAMESTART and observes SYSTEM4 enter SC0000 with `G[0]=1`, `G[0x699]=0x22`,
and script-produced `G[0x6c1]=1`. Direct `--scene` launches retain the old bootstrap strictly as a diagnostic.
`tools/frida/capture_script_loads.py` hooks `script_frame_load_resource@0x40e980` and reads its third stack
argument (the raw packed resource id) for direct name resolution. It is attach-only: attempting to gate the
installed executable at process start with this loader hook produced Protection Error 45 and no records.
@@ -852,18 +857,26 @@ Ghidra functions renamed + plate-commented, saved).
(`EngineCtx+0x51b64`), not op `0x238`.
- **`0x203` (`gfx_op_0x203_worker_set_color` `0x47e9b0`)**: sets a **static** color/alpha `obj+0x60`, no anim
bit. Immediate per-object modulation.
- **Blit** (`gfx_object_blit_d3d9` `0x4774c0`): selects a **blend mode** (`local_2c`: 0 opaque, 1 alpha
`SRCALPHA/INVSRCALPHA`, 2/3 additive/special for glow/flash) and passes a modulation color/alpha to the
device draw. Slice A ports the **alpha** path (fades); additive (glow) is deferred (its `local_2c` source
field is `obj+0x30`, the value written by op `0x203`. Mode 1 uses packed ARGB alpha as opacity and RGB
as multiplicative D3D modulation. For a **textured mode-0** object, preserved `0xffffffff` is opaque
- **Blit** (`gfx_object_blit_d3d9` `0x4774c0`): selects a **blend mode** from `obj+0x30`, the value written
by op `0x203`, and passes a modulation color/alpha to the device draw. Correcting the D3D9 constants:
mode 1 writes `SRCBLEND=SRCALPHA` (5) and `DESTBLEND=ONE` (2), so it is additive glow—not ordinary
`SRCALPHA/INVSRCALPHA`. Mode 2 conditionally writes `ONE/ZERO` for a selected render target; mode 3 adds
the subtract blend operation to the mode-1 factors. The port implements mode-1 additive composition,
where packed alpha scales source contribution and packed RGB multiplicatively modulates it. For a
**textured mode-0** object, preserved `0xffffffff` is opaque
identity, not a request to replace the texture with white; the packed alpha byte is therefore not a
generic tint-strength control. Modes 2/3 remain separately scoped beyond the completed mode-1 path, and
generic tint-strength control. Mode 3 remains separately scoped beyond the completed mode-1 path, and
surfaceless mode-0 fills remain a distinct consumer case.
**TITLE SO022 additive proof (2026-07-20).** TITLE loads type-1 8-bpp `SO022.AGF` with no alpha plane and
no color key, binds two 140×140 spritesheet objects, and calls `0x203(handle,1,255,0xffffff)` for both.
Ordinary alpha composition therefore produces opaque black squares around the blue flames. Native mode-1
`SRCALPHA/ONE` makes black contribute zero; the implemented additive raster path removes the rectangles
while preserving the animated glow, verified across a windowed SYSTEM4/TITLE capture.
**SC0000 third-CG white-screen and missing-glow fix (2026-07-11).** The page containing
`大役を担ったのは…` reaches the intended EV052DA image and both animated AE001D layers. A synchronized
Godot capture proved AE001D is correctly alpha-bearing and drawn in mode 1 at only 6-8% object opacity;
Godot capture proved AE001D is correctly alpha-bearing and drawn in mode 1 at only a 6-8% additive source scale;
it was not the white wall. During the preceding `0x223` EV052CA→EV052DA crossfade, base handle `0xcb2a`
renders EV052DA in mode 2 with identity modulation. When the transition ends, `0x203@0x12478` restores that
same textured object to mode 0 with negative color operands, preserving `0xffffffff`. Native keeps EV052DA
@@ -908,8 +921,8 @@ alpha/RGB target operands independently preserve their bytes from current `+0x60
The port now carries current and target separately and samples them from the unified `FrameClock`; an op
`0x203` static write after `0x202` therefore becomes the ramp's current value rather than overwriting its
target. Mode 0 retains the established CG/tint/fill behavior; mode 1 now uses native alpha opacity plus RGB
modulation. `draw-string 0x204`/`0x7a` remains a separate dependency.
target. Mode 0 retains the established CG/tint/fill behavior; mode 1 uses native additive composition with
ARGB alpha as the source scale plus RGB modulation. `draw-string 0x204`/`0x7a` remains a separate dependency.
**ADV chrome correction (2026-07-11).** Mode 0 cannot be classified from the final packed color alone.
Static `0x203(mode=0, alpha=0, rgb=white)` remains the established opaque/no-tint CG initializer, but a
@@ -1004,13 +1017,13 @@ AE001H, exactly matching the reported white pulse. Follow-up native dataflow clo
fresh objects initialize static color `obj+0x60` to `0xffffffff`; the interpolator samples that temporary
color toward target `obj+0x240`, then `gfx_object_composite` passes the sample and the unchanged blend
selector `obj+0x30` to `gfx_object_blit_d3d9`. Mode 0 enables no alpha blending and uses RGB only as vertex
modulation, while mode 1 enables SRCALPHA/INVSRCALPHA. AE001H therefore cycles
modulation, while mode 1 enables SRCALPHA/ONE additive composition. AE001H therefore cycles
`0xffffffff ↔ 0xe0ffffff`: identity RGB throughout, with alpha intentionally inert in mode 0, so native has
no visible pulse. The faithful fix is now fully bounded: initialize/resolve static color correctly, sample
packed ARGB, and consume it through the existing mode-specific blend path instead of converting animated
alpha into tint strength. The port now initializes static color to native identity `0xffffffff`, resolves
negative operands in `SetColorAnimResolved`, samples packed ARGB before blend selection, and feeds it through
the existing mode-specific path. Exact AE001H, mode-0 RGB-modulation, and mode-1 alpha regressions cover the
the existing mode-specific path. Exact AE001H, mode-0 RGB-modulation, and mode-1 additive regressions cover the
contract; the white pulse is removed without suppressing the scripted channel.
**Resolved 2026-07-20:** `0x236` is the movie-to-retained-surface path described below. `0x242` is the

View File

@@ -387,9 +387,9 @@ The handler clears the map embedded at retained-gfx owner+0x408, resets its coun
- **evidence:** Ghidra handler 0x4228d0 packs operands 4/5 and calls worker 0x47ea00(handle,delay,duration,packed). Consumer 0x472f00: shared start +0x34; color delay/duration +0x38/+0x4c; current/target +0x60/+0x64; frame clock retained-gfx owner+0xb550 (EngineCtx+0x51b64); bytewise integer LERP; natural or owner+0xb55c (EngineCtx+0x51b70) forced completion. /v2 annotated and saved 2026-07-10.
### 0x203 `gfx-draw-color` (gfx-draw-color, argc 4)
- **summary:** 0x203 (handle)(mode)(alpha)(color) — worker stores the D3D blend selector at obj+0x30 and STATIC packed color at obj+0x60; the handler's ctx+0x53d88 write is the generic 9-dword instruction length. Negative alpha/RGB preserve current static bytes. Mode 0 is the opaque textured path: preserved 0xffffffff is identity (the alpha byte is not tint strength); mode 1 is SRCALPHA/INVSRCALPHA with ARGB alpha opacity and multiplicative RGB modulation; mode 2 is the 0x223 transition-source identity path. Surfaceless mode-0 fill consumption remains a distinct case.
- **summary:** 0x203 (handle)(mode)(alpha)(color) — worker stores the D3D blend selector at obj+0x30 and STATIC packed color at obj+0x60; the handler's ctx+0x53d88 write is the generic 9-dword instruction length. Negative alpha/RGB preserve current static bytes. Mode 0 is the default textured path: preserved 0xffffffff is identity (the alpha byte is not tint strength). Mode 1 is SRCALPHA/ONE additive glow with ARGB alpha scaling the source contribution and RGB providing multiplicative modulation. Mode 2 conditionally forces ONE/ZERO for the selected render target and is used by 0x223 transition sources; mode 3 selects a subtractive special path. Surfaceless mode-0 fill consumption remains distinct.
- **grounding:** source=investigation, confidence=high
- **evidence:** Ghidra handler 0x4229a0; negative operands read current obj+0x60, then worker 0x47e9b0 stores op2 at obj+0x30 and ARGB at +0x60. gfx_object_composite call-site 0x47f78f passes +0x30/+0x60 directly to gfx_object_blit_d3d9; mode 1 sets D3DRS SRCALPHA/INVSRCALPHA and the packed color is the device draw modulation. Mode 2 transition setup and synchronized pixels prove 0xffffffff is identity, not solid white. SC0000 page 14 adds the mode-0 endpoint proof: after the EV052CA->EV052DA 0x223 crossfade, 0x203@0x12478 restores the base CG to mode 0 with preserved 0xffffffff; native keeps EV052DA visible while the port's tint-strength interpretation turns every texel white.
- **evidence:** Ghidra handler 0x4229a0; negative operands read current obj+0x60, then worker 0x47e9b0 stores op2 at obj+0x30 and ARGB at +0x60. gfx_object_composite call-site 0x47f78f passes +0x30/+0x60 directly to gfx_object_blit_d3d9. Correct D3D9 constants at 0x4774c0 prove mode 1 writes SRCBLEND=5/SRCALPHA and DESTBLEND=2/ONE, not INVSRCALPHA. TITLE draws two opaque-black, no-colorkey SO022 flame sprites with mode 1; additive composition removes black and preserves the blue glow, verified in a windowed capture. Mode 2 transition setup and synchronized pixels prove 0xffffffff is identity, not solid white. SC0000 page 14 adds the mode-0 endpoint proof: after the EV052CA->EV052DA 0x223 crossfade, 0x203@0x12478 restores the base CG to mode 0 with preserved 0xffffffff; native keeps EV052DA visible while the port's tint-strength interpretation turns every texel white.
### 0x208 `get-texture-size` (get-texture-size, argc 3)
- **summary:** 0x208 (slot)(out_w)(out_h) — writes the loaded texture's width/height into two output globals; keystone for bytecode-computed sprite/bg geometry (SC0000 label_12649)
@@ -522,9 +522,9 @@ This is a target-pixel operation, not retained-object teardown. It invokes IDire
- **evidence:** Native /v2 decompile: worker stores period at obj+0x230, frame_count at +0x238, columns at +0x23c. Interpolator computes ((now-start)/period)%frame_count, then offsets both source-rect X bounds by rect_width*(frame%columns) and Y bounds by rect_height*(frame/columns). SC0000 uses (100,8,4) with AE001H's eight 200x200 cells in a 4x2 800x400 sheet.
### 0x232 `u00421EF0` (u00421EF0, argc 4)
- **summary:** 0x232 anim-color (handle)(period)(alpha)(color): ping-pong the temporary packed ARGB passed to the normal object blit. Handler resolves negative alpha/RGB from static color obj+0x60 and clamps alpha above 255. Blend selector obj+0x30 is unchanged: mode 0 keeps default opaque blending (animated alpha is inert; RGB is vertex modulation), while mode 1 consumes ARGB alpha as opacity. Fresh static color is 0xffffffff. The C# VM resolves sentinels and consumes sampled ARGB through the unchanged mode-specific path. See docs/engine-re.md §SC0000 anim cluster.
- **summary:** 0x232 anim-color (handle)(period)(alpha)(color): ping-pong the temporary packed ARGB passed to the normal object blit. Handler resolves negative alpha/RGB from static color obj+0x60 and clamps alpha above 255. Blend selector obj+0x30 is unchanged: mode 0 keeps default blending (animated alpha is inert; RGB is vertex modulation), while mode 1 uses sampled ARGB alpha as the SRCALPHA scale for additive composition. Fresh static color is 0xffffffff. The C# VM resolves sentinels and consumes sampled ARGB through the unchanged mode-specific path. See docs/engine-re.md §SC0000 anim cluster.
- **grounding:** source=investigation, confidence=high
- **evidence:** Ghidra /v2: gfx_op_0x232_anim_color@0x423c30 resolves sentinels then calls gfx_worker_anim_color@0x47ef50; gfx_object_anim_interpolate@0x473ed0 samples static obj+0x60 toward target obj+0x240 into a temporary packed color; gfx_object_composite@0x47f650 passes that color plus unchanged selector obj+0x30 to gfx_object_blit_d3d9@0x4774c0. Blit mode 0 enables no alpha blend and passes RGB as modulation; mode 1 enables SRCALPHA/INVSRCALPHA. gfx_object_init_default@0x472810 initializes obj+0x60=0xffffffff. SC0000 0x1a0e (handle,1200,224,-1) is therefore 0xffffffff<->0xe0ffffff with inert alpha and identity RGB: no visible pulse. C# regressions cover exact AE001H visual invariance, negative-RGB preservation, mode-0 RGB modulation, and mode-1 alpha opacity.
- **evidence:** Ghidra /v2: gfx_op_0x232_anim_color@0x423c30 resolves sentinels then calls gfx_worker_anim_color@0x47ef50; gfx_object_anim_interpolate@0x473ed0 samples static obj+0x60 toward target obj+0x240 into a temporary packed color; gfx_object_composite@0x47f650 passes that color plus unchanged selector obj+0x30 to gfx_object_blit_d3d9@0x4774c0. Blit mode 0 leaves the default path and passes RGB as modulation; mode 1 sets SRCALPHA/ONE additive composition. gfx_object_init_default@0x472810 initializes obj+0x60=0xffffffff. SC0000 0x1a0e (handle,1200,224,-1) is therefore 0xffffffff<->0xe0ffffff with inert alpha and identity RGB in mode 0: no visible pulse. C# regressions cover exact AE001H visual invariance, negative-RGB preservation, mode-0 RGB modulation, and mode-1 additive scaling.
### 0x234 `anim-start` (anim-start, argc 5)
- **summary:** (handle)(period_ms)(axis_x)(axis_y)(axis_z) — configure cyclic rotation. Worker stores period obj+0x228, start obj+0x214=0, and float axis obj+0x244; each frame uses integer degrees floor(((now-start)%period)*360/period). gfx_object_composite right-multiplies this separately anchored transform after the one-shot scale/rotation/translation product, so cyclic rotation also rotates the translation vector.

View File

@@ -90,6 +90,15 @@ coverage is 100% for all 23 data initializers, CALCARR, and TUNE; the remaining
SYSTEM4-rooted path visible and interactive in Godot, then investigate only the gaps actually reached on
that route instead of treating every static gap as a prerequisite.
**Godot root landing (2026-07-20).** The no-argument Godot/run-godot path now starts SYSTEM4 directly and
does not apply the direct-SC0000 layout/surface bootstrap or the diagnostic `--boot` prefix. A windowed run
reaches and renders TITLE using SYSTEM4-owned retained state. A real-script integration test drives TITLE's
Game Start input, GAMESTART's release-gated default selection, and proves the same VM enters SC0000 through
SYSTEM4's computed resource id `G[0x699]=0x22`; `G[0]=1` and the script-produced ADV-chrome flag
`G[0x6c1]=1` are present at that boundary. `--scene SC0000 --boot` remains available only as the explicit
single-scene diagnostic harness. This lands the boot/title/New Game entry half of B1B3; proving a completed
scene return plus boundary cleanup still belongs to B1 completion.
## Stage B1 — Persistent session and scene coordinator
Replace the single-SC0000-root assumption with an application-owned session that runs SYSTEM4 as its root.

View File

@@ -132,21 +132,24 @@ at 2.5M lines). All observe-only → parity preserved; all on `run`/`play`/`swee
- **Godot** accepts **`--trace-histogram <file>`** — profile the **real** run (headless flow diverges because
`wait-for-input` is a no-op there; the real run to page 1 is ~562 steps with **0** sleeps vs headless's 2M
steps / 493k sleeps). Dumped when the scene ends or the window closes. e.g.
`godot --path godot -- --boot --shot out/p1.png --trace-histogram out/hist.txt`.
`godot --path godot -- --scene SC0000 --boot --shot out/p1.png --trace-histogram out/hist.txt`.
**Godot frontend** (`S:/Godot/Godot_v4.7…`; project = `godot/`). Toolchain: `godot --headless --path godot
--import``dotnet build godot/Himegari.csproj``godot [--headless] --path godot [-- <userargs>]`.
Plays the real bytecode with call-script execution on (subroutines run live). `--headless` can't render
texture ops (no GPU context) — run windowed for real scenes. User args (after `--`):
- `--scene <NAME>` — which scene to play (default `SC0000`), e.g. `--scene SC0240` (executes 29 nested subroutines).
Plays the real bytecode with call-script execution on (subroutines run live). A no-argument launch, including
`run-godot.ps1`, starts the persistent `SYSTEM4.BIN` root and reaches TITLE naturally. `--headless` can't
render texture ops (no GPU context) — run windowed for real scenes. User args (after `--`):
- `--scene <NAME>` — override the default `SYSTEM4` root with a direct diagnostic scene, e.g. `--scene SC0240` (executes 29 nested subroutines).
- `--selftest` — headless; runs a **synthesized** scene through the thread/suspend/`CallDeferred` plumbing and asserts it matches a live headless run (full handling; no vm0/frozen golden). Exits.
- `--seed 0xADDR=VAL` (repeatable) — seed initial global state, e.g. `--seed 0xa57=1` unlocks Lily's form-A voiced dialogue.
- `--boot`run SYSTEM4's state prefix (`INITCONFIG/INIT2/INIT`) via `GameSession` before the scene, so scene-assumed boot state (chiefly INIT2's gfx handle array) is present. **Needed for the gfx CGs to render** (without it the opening event CGs collapse/drift). e.g. `godot --path godot -- --boot`.
- `--boot`direct-scene diagnostic only: with `--scene <non-SYSTEM4>`, run the old
`INITCONFIG/INIT2/INIT` state prefix before that isolated scene. The normal SYSTEM4-rooted launch neither
needs nor applies it. e.g. `godot --path godot -- --scene SC0000 --boot`.
- `--shot <png> [--shot-page N]` — capture page N to a PNG then quit (dev screenshot). At scene end it also prints the call-scripts executed as nested frames.
- `--shot-sequence <dir> [--frames N]` — dump one PNG per rendered frame (`frame_0000.png…`, default N=180 ≈ 3s @60fps) then quit, auto-advancing past input waits. Verifies time-based retained effects and publication boundaries as distinct frames, which a single `--shot` cannot. CPU/IO-heavy by design (a PNG every frame); a dev diagnostic, not a normal run. e.g. `godot --path godot -- --boot --shot-sequence out/seq --frames 300`.
- `--shot-sequence <dir> [--frames N]` — dump one PNG per rendered frame (`frame_0000.png…`, default N=180 ≈ 3s @60fps) then quit, auto-advancing past input waits. Verifies time-based retained effects and publication boundaries as distinct frames, which a single `--shot` cannot. CPU/IO-heavy by design (a PNG every frame); a dev diagnostic, not a normal run. e.g. `godot --path godot -- --scene SC0000 --boot --shot-sequence out/seq --frames 300`.
- `--sleep-scale <f>` — multiply every explicit `sleep` (op 0xc8) duration by `f` (default 1.0). This stretches only script-authored sleep holds; it does not slow ordinary opcode bursts or replace `0x20c`/`0x21c` presentation pacing. Debug-only; leave at 1.0 for real playback.
- `--speed <f>` — scale sleeps and retained presentation clocks without throttling ordinary opcode bursts or auto-advancing input waits. Values 0.058 are accepted; `--speed 0.25` is useful for transform inspection, while 1.0 is normal playback.
- `--gfx-log <file>`**compositor + op diagnostic** (the tool that root-caused the grey background). Logs, per rendered frame, only the objects whose draw outcome **CHANGED** (drawn↔skip↔gone, resId, resolved file, `slot`, `src`/`dst`, `op`acity, `tintStr`ength) — quiet until something actually changes, so the exact frame a layer drops out (and why) stands out. Also traces every `set-texture`/`create-texture` **slot assignment** (via `GodotAdvHost.TraceOps`). Works live or with `--shot-sequence`. Use it before theorising about layering/blend/geometry: it showed the grey BG = the slot-selecting globals resolving to 0 → every texture collapsing into slot 0 (see engine-re.md §"Grey-background root cause"). e.g. `godot --path godot -- --boot --gfx-log out/gfx.log` then click to the bad page.
- `--gfx-log <file>`**compositor + op diagnostic** (the tool that root-caused the grey background). Logs, per rendered frame, only the objects whose draw outcome **CHANGED** (drawn↔skip↔gone, resId, resolved file, `slot`, `src`/`dst`, `op`acity, `tintStr`ength) — quiet until something actually changes, so the exact frame a layer drops out (and why) stands out. Also traces every `set-texture`/`create-texture` **slot assignment** (via `GodotAdvHost.TraceOps`). Works live or with `--shot-sequence`. Use it before theorising about layering/blend/geometry: it showed the grey BG = the slot-selecting globals resolving to 0 → every texture collapsing into slot 0 (see engine-re.md §"Grey-background root cause"). e.g. `godot --path godot -- --scene SC0000 --boot --gfx-log out/gfx.log` then click to the bad page.
Matrix-channel outcomes also include `base`, `anchor`, projected `dst`, sampled `scale`/`trans`, and
one-shot-plus-cyclic `rot`ation angles. Active op-`0x202` outcomes include packed `color=current->target`
and `colorProgress`, synchronized with the same frame/clock in `--timeline-log`. Parent directories are
@@ -155,7 +158,7 @@ texture ops (no GPU context) — run windowed for real scenes. User args (after
- `--timeline-log <jsonl>` — diagnostic-only synchronized event stream for a real Godot run. Records every
executed script byte offset/opcode, virtual time/frame, VM state changes (`running`, `sleep`, `input-wait`,
`halted`), BGM events, and changed visible-object compositor outcomes in one ordered JSONL file. Combine with
`--boot --shot-sequence ... --gfx-log ...` to distinguish control-flow stalls from retained-object/compositor
`--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 page locator:** every normal run recreates `build/page-map-<SCENE>.jsonl`, adding one record per