8 Commits

Author SHA1 Message Date
Sylpheed RE agent
c75c982fa0 re: the working entity captures came from a SAVE SLOT, not mission select
Before deriving a new vtable I checked where gworld.py's constants came from.
They cite structures/unit-struct-runtime.md, which states its provenance:
"Captured 2026-07-29 ... all six tutorials and Stage 02 'Declaration of War'
loaded from save slot 01."

Loaded from a save slot -- not through MISSION SELECT, which is the route every
run this session has taken, and which needs the cleared-stage mask poke to offer
a stage at all.  So the constants may not be stale; they may just need the state
that route produces.  That is a cheaper question than writing a new vtable
finder, and it should be answered first.

First attempt inconclusive: driving the main menu's first item blind, five
presses deep, advanced the progress counter every time (3 -> 5 -> 6 -> 8 -> 10 ->
12, so the game responds) but left DEF_VTABLE / INST_VTABLE at 0/0 throughout.
Without a screen identity this is dead reckoning, and the first item may not be
the load-game entry -- newgame_path.sh documents it as NEW GAME with SELECT DATA
two screens further in.

Next: reach the save-slot screen deliberately rather than by counting presses,
and load slot 01.
2026-08-26 20:13:33 +00:00
Sylpheed RE agent
f2a18e555c re: "follow the name pointer" is structurally dead for pak strings
Locating DeltaSaber at mission time works: 53 occurrences, all in the heap
(0xBC66..-0xBC6C..), none in the XEX image -- DeltaSaber_T.xpr, _Special,
_NoseGun, _Missile, _TwinGun.

But searching all of guest memory for a big-endian pointer to those addresses
returns ZERO references for every one tried.  That is the format, not a search
bug: those strings live in the mission pak's IDXD string pool, and this corpus
decoded that container long ago -- records reference names by OFFSET into the
pool, never by absolute pointer.  So there are no pointers to find, and "find the
name, follow what points at it" cannot work on pak data by construction.

This also narrows what the string counts proved.  The title-vs-mission control
stands (DeltaSaber 0 -> 81), so mission-specific DATA is loaded, which is more
than "the tables load at boot".  But these are asset-table strings, not live
entity objects, so they do not show entities have been spawned.  Honest split:
the mission's pak data is loaded; whether entity objects exist is still
unmeasured, because both probes tried -- gworld's vtable constants and
name-pointer following -- are respectively stale and structurally inapplicable.

Remaining routes, untried: derive the entity vtable from CODE via sylpheed.db's
vptr_writes table, which exists for exactly this; or find the entity list from
the mission update function rather than from data.
2026-08-26 20:06:10 +00:00
Sylpheed RE agent
3e267ad4c4 re: the mission DOES load -- DEF_VTABLE=0 was a stale constant, not an empty game
Three iterations concluded "no units are loaded" from scan_vtable(DEF_VTABLE)
returning 0.  Withdrawn: the scan was measuring the wrong thing.

Counting unit-name strings in guest memory with the TITLE as a control (same boot
recipe, no mission):

    string        title    after take-off
    DeltaSaber        0        81
    rou_          1,981     7,680
    UN_              19       167
    e010             67       134
    ADAN          1,450     1,921

DeltaSaber is the player's craft: absent at the title, present 81 times after
take-off.  Every other count rises several-fold.  The stage content is
unambiguously in memory.

The control is what makes this a result.  Raw counts prove nothing on their own --
rou_ and ADAN are numerous at the title too, because the unit tables load at boot.
Only the title-vs-mission difference, and DeltaSaber's 0 -> 81 in particular,
separates "tables loaded" from "mission loaded".  My first reading skipped the
control and over-claimed; the control was run before publishing.

Withdrawn as a consequence: "no units are loaded"; and the inference that the
take-off lands in a never-ending cutscene (the movie accesses are real, but the
conclusion rested on DEF_VTABLE=0).  gworld.py's DEF_VTABLE 0x820AF844 and
INST_VTABLE 0x820AF030 do not locate entities in this build/state despite being
genuine vtables in sylpheed.db.

Next: derive the correct entity vtable.  The UN_ strings reachable by search are
UN_NOSE/UN_MOUNT attachment names in the XEX image, not runtime records -- so use
a name that only exists at mission time.  DeltaSaber is exactly that: find its
heap occurrences, find what points at them, read the referencing object's vtable.
2026-08-26 19:56:52 +00:00
Sylpheed RE agent
4ee7971340 re: the post-take-off state is measurably neither a menu nor flight
wait_flight.sh carries the corpus's best discriminator, and it is a whole-image
statistic rather than a named pixel: the flight HUD paints green over the frame
at 1.3-1.5% green fraction, against <0.1% on every menu.

Measured on the post-take-off state: green=0.0022, mean (1.6, 45.6, 50.1).  That
is 0.22% -- an order of magnitude above a menu, an order of magnitude below
flight, on a dark blue-green frame.  screen_id.py files it under "menu" because
that is the closest bucket it has; the state is neither.

wait_flight.sh then tapped A for 280 seconds and never saw the HUD.

With the 12 \dat\movie accesses, the reading is consistent: this is the cutscene,
it does not end on A, and it does not reach the flight HUD within five minutes.

Open, cheapest first: how the movie path signals completion (the corpus already
decoded the movie handler for the intro video and found a software-decode
deadline); whether a mission can be started by a route that skips the launch
cinematic; or whether the cutscene simply needs far longer under lavapipe.

Oracle status overall: boot, menus and take-off are reliable and reproducible;
only the cutscene->mission step is unsolved -- a much smaller and better-defined
gap than the freeze it replaced.
2026-08-26 19:43:40 +00:00
Sylpheed RE agent
9031c2510a re: the take-off sequence lands in the launch CUTSCENE, not a hang
Logging file and kernel activity through the whole navigation and counting names:

    12  \dat\movie      <- heavy, repeated movie access
     3  \dat\sound
     2  Stage_S01       <- the stage resource is referenced
     1  XamShowDeviceSelectorUI

So after take-off the game plays the launch cutscene.  Under software rendering a
720p decode is very slow -- this corpus already raised INSTRUCTIONS_PER_MS 100x
because the movie handler has a 2000 ms software-decode deadline -- which is why
the state persists for minutes.

It is unambiguously live, by the widest margin yet measured:

                     frozen   menus   this state
    screen liveness  0.00%    0.22%   11.00%
    guest churn      0.000%   0.190%  0.671%

and the progress counter advances on input (17 -> 101 across the skip attempts),
so the pad reaches the game.

But it does not skip: four rounds of START / A / B advanced the counter every
time and left DEF_VTABLE / INST_VTABLE at 0/0.  The input registers, it just does
not end the sequence.

The remaining gap is now narrow and named: the take-off cutscene runs and is not
skippable by the obvious buttons.  Either it must play out, or the right skip
input is unknown, or it waits on something the movie path never delivers.
2026-08-26 19:30:21 +00:00
Sylpheed RE agent
926cee6ba0 re: the sign-in fix holds end-to-end, but no units are loaded yet
With the emulator launched correctly and the boot verified by the progress
counter first (counter > 0 = title reached; a flaky boot never leaves 0),
nav_to_flight.sh ran the whole sequence -- main menu at 20 s, mask poke, stage
select, briefing skip, ready room, take-off -- where every previous attempt
stalled.

The game is alive at the end of it: screen liveness 2.13% against 0.00% when
frozen, guest churn 0.288-2.932% against 0.000%.  An animating screen and a busy
guest at the point that used to be stone dead.

But no units.  DEF_VTABLE (0x820AF844) has no hits on a direct byte search, with
a working control in the same run: searching for the poked cleared-stage mask
0x0001FFFE finds it at 0x828F40C0, exactly where nav_to_flight wrote it.  So the
search is sound and the vtable is genuinely absent.  Both vtable constants were
also checked against sylpheed.db's vtables table and are real vtables, so they
are not stale.  Three minutes of waiting left DEF/INST at 0/0 with the counter
static at 17.

So the run reaches a live, animating state that is not a mission with spawned
units -- most likely the launch cinematic or a post-take-off screen.  The freeze
is gone; what still separates this from unit spawn is the remaining work.
2026-08-26 19:20:24 +00:00
Sylpheed RE agent
0274b29368 re: the sign-in fix must be applied at launch, not by the navigator
nav_to_flight.sh contains no run-canary invocation -- it drives an
already-running emulator -- so whether a profile is signed in depends entirely on
how the caller launched it.  Every nav_to_flight run in this session was launched
with a bare run-canary, which is why they froze.  Worth stating plainly because
the script prints "signing in profile B13EBABEBABEBABE", which comes from the
emulator's startup rather than from the script arranging it.

Refuted: "each screen loads its own GP_*.pak", a plausible route to a real screen
identity.  With full file logging the only names that appear are at boot
(sound.p0x, tables.p00, hidden) and nothing new opens as the UI moves between
screens -- the paks are opened once and read by offset, so file I/O carries no
per-screen signal.

Also recorded: one launch this iteration never reached the title -- progress
counter stuck at 0, black screen, guest churn 0.001%.  That is a DIFFERENT
failure from the sign-in freeze, which stalls after the main menu with the
counters already advanced, and it matches the boot flakiness
canary-scripted-input-traps.md already documents.  The counters distinguish
them: sign-in freeze stalls past the title, a bad boot never leaves 0.
2026-08-26 19:07:25 +00:00
Sylpheed RE agent
93bc7bf061 re: SOLVED -- the mission freeze is a modal sign-in dialog
Every Xam UI dialog goes through xeXamDispatchDialog, and the calling guest
thread blocks on fence.Wait() until it is dismissed.  With kernel logging on the
last call before the freeze is XamShowSigninUI(00000001, 00000001): the game
asks for a signed-in profile, Xenia opens a modal dialog, and nothing in a
scripted run ever dismisses an ImGui dialog.

That accounts for every symptom at once -- Main XThread futex-blocked at 0 ms CPU
rather than spinning, emulator alive, no guest progress, no faults, and
independence from both the GPU backend and the allocation outcome.

Fix: run-canary --logged_profile_slot_0_xuid=B13EBABEBABEBABE.  Same route, one
variable changed:

                        no profile      with profile
    screen id           4, forever      4 -> 5 -> 6 -> 8 -> 9 -> 10
    XamShowSigninUI     called          not called
    alloc failures      1               0
    guest throws        1               0
    guest churn         0.000%          1.006%

XamShowDeviceSelectorUI is then requested but storage_selection_dialog defaults
to false, so it is not shown and does not block.

Why it took so long: --log_mask=13, used by every script in this corpus,
DISABLES kernel logging -- the one category that names the dialog.  Without it
the freeze presents as a bare futex block, which is why it was attributed in
turn to a heap leak, rounding, MmQueryStatistics, a build regression, the route,
the savegame, shader compilation, an infinite guest loop and the software
rasterizer, each refuted in its own section.

Nearest miss worth recording: challenge-mission-gate.md reported a "Disc Read
Error" dialog on this failure.  That is XamShowDirtyDiscErrorUI, which calls
exit(1) -- "This is death, and should never return" -- so it cannot be our
freeze, whose process stays alive.  Checking that distinction is what led to the
dialog mechanism.

Open: no mission reached yet (DEF_VTABLE/INST_VTABLE still 0 at screen 10), so
the remaining screens are menus.  Ordinary navigation, not a blocker.
2026-08-26 18:41:09 +00:00