gworld.py's DEF_VTABLE 0x820AF844 and INST_VTABLE 0x820AF030 resolve exactly as
written: 13 unit definitions and 42 live instances, every one name-resolved, with
52 moving triples. The roster is coherent and stage-specific -- UN_S01_Asteroid_*
in the S01 training area, 2 e106 destroyers against 20 e007 turrets, 6 DeltaSaber_T
and exactly one _Player -- which is far stronger evidence than a hit count.
The constants were never stale. structures/unit-struct-runtime.md records its own
provenance ("all six tutorials and Stage 02 loaded from save slot 01") and
launch_mission.sh already encoded that route: title -> LOAD GAME -> slot 01 -> YES
-> READY ROOM -> TAKE OFF. LOAD GAME is the menu's SECOND item; the previous
iteration pressed the first (NEW GAME) and read the resulting 0/0 as evidence
about the constants. One `step down` separated a dozen iterations from this.
Control still owed and stated in the doc: the title-screen arm was measured in
earlier processes, not this one.
4.1 KiB
✅ Entity objects ARE spawned — the vtables were never stale, the ROUTE was wrong
Confidence: ✅ CONFIRMED. Measured 2026-08-26 in the sylph-re container, Canary on the retail disc, save slot 01, Stage 01 "Glasner Training Area".
The result
gworld.py's two constants resolve exactly as written:
| vtable | address | hits |
|---|---|---|
DEF_VTABLE (parsed .tbl definition, one per unit type) |
0x820AF844 |
13 |
INST_VTABLE (spawned entity instance, one per thing in the scene) |
0x820AF030 |
42 |
name_of() resolves every one of them:
# 13 definitions # 42 live instances
UN_f001_TCAF_DeltaSaber_T_Player 20 UN_e007_ADAN_Turret
UN_f001_TCAF_DeltaSaber_T 6 UN_f001_TCAF_DeltaSaber_T
UN_e007_ADAN_Turret 5 UN_e010_ADAN_Attacker_S
UN_e106_ADAN_Destroyer 2 UN_e106_ADAN_Destroyer
UN_e010_ADAN_Attacker_S 8 UN_S01_Asteroid_cmesh_0{1..4}{a,b}
UN_S01_Asteroid_cmesh_0{1..4}{a,b} 1 UN_f001_TCAF_DeltaSaber_T_Player
entities2.py reports 52 moving triples, so these are live objects with
changing positions, not inert table images.
Why this is not a false positive
A bit pattern can occur by chance; a coherent roster cannot. The evidence is the content, not the count:
- The asteroid definitions are
UN_S01_…and the stage actually loaded was S01 — the scan recovered the right stage's props without being told which stage was running. - The composition is internally sensible: 2
e106destroyers and 20e007turrets, i.e. ~10 turrets per destroyer, which matches the e106 part breakdown in ship placement (8 hull parts + 2 turrets per side). SixDeltaSaber_T= the player plus a wing. - Exactly one object is the
_Playervariant, and exactly one definition is.
❌ Control still owed, stated rather than glossed: the title-screen arm of this comparison was measured in earlier processes (0 hits at every menu state), not in this one. The stage-specific roster is strong evidence, but a same-process title control has not been run.
What was actually wrong — the route, not the constants
Every run in the preceding dozen iterations navigated through MISSION SELECT (which needs the cleared-stage-mask poke to offer a stage at all). Both scans returned 0/0 there, and the constants were marked 🔴 stale.
They were not stale. structures/unit-struct-runtime.md
records its own provenance — captures came from "all six tutorials and Stage 02
loaded from save slot 01" — and launch_mission.sh already encoded that
route: title → LOAD GAME → slot 01 → YES → READY ROOM → TAKE OFF.
LOAD GAME is the menu's second item. The previous iteration pressed the
first (NEW GAME) and read the 0/0 that followed as evidence about the
constants. One step down separated a dozen iterations of "stale vtable" from
this roster.
🔑 Method note. Two iterations in a row were spent re-deriving something the
corpus already recorded — first the provenance line, then the working script.
Read tools/re-capture/ and the doc's own provenance before deriving.
Reproduction
launch_mission.sh fly does the whole thing. On a slow lavapipe boot the
attract movie can outlast SKIP_INTRO_TIMEOUT; the emulator is nohuped and
survives, so re-run the post-boot half against the live process.
⚠️ wait_screen.sh readyroom reports failure on a successful run: the cyan
mission-briefing map classifies as menu (see
screen-id-briefing-misclass), so the route
looks stuck on the main menu while it is in fact three screens further on.
Still open
- The world-unit measurement (collisionset) — positions in world units against the HUD's own distance readout. This run reached the mission but the flight HUD was not yet up (green 0.03 %, vs 1.3–1.5 % in flight), so no distance readout was available to compare against.
- A same-process title-screen control for the scan above.