This repository has been archived on 2026-09-16. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Syplheed-Reborn/docs/re/menu-state-in-memory.md
Sylpheed RE agent 15e58d93b1 re: correct the "screen id" -- they are monotonic counters, not identities
The names in menu-state-in-memory.md are wrong for at least two of the three
words, and the test that shows it is going backwards.  Driving deep into the
menus, then three presses of B:

    0x828F38AC "cursor"   36  -> 38 -> 40 -> 41
    0x828F37B4 "misc"    971  -> 1067 -> 1068 -> 1068
    0x828A690C "screen"   56  -> 56, 56, 56

A cursor returns when you go back.  These only ever increase -- monotonic
counters, with 0x828F38AC advancing about 2 per input.  Driving forward produced
1,3,4,5,6,8,10,12,25,29,32,33,50,53,56 for the "screen id", which is an identity
sequence only if the game has 56+ screens and never revisits one -- exactly what
a counter also looks like.

Withdrawn: 0x828A690C as a screen IDENTITY (1 title, 3 main menu, 4 extras).  The
values are path-dependent; they matched across runs because the same key sequence
produces the same count, not because 3 means main menu.

Survives: all three advance if and only if the game responds, and are stable when
it does not.  That is a real input-progress signal, reproducible across runs and
both GPU backends, and it is what made blind navigation work.  Read it as "did
the game react?", never "which screen is this?".

It also retro-confirms the freeze diagnosis: with the sign-in fix the sequence
runs 3 -> 5, skipping 4 entirely, so "4 = extras" was never a screen -- it was the
count at which the game stopped responding.  The counter reading explains both
observations.

Open: no mission reached.  Counters at 56/41/1068, guest churn 0.190% (alive;
frozen is 0.000%), DEF_VTABLE and INST_VTABLE still 0.  Without a real screen
identity, navigation is dead reckoning; finding a genuine state enum is next, and
the snapshot-and-diff method can be repeated with these counters excluded.
2026-08-26 18:51:25 +00:00

4.8 KiB
Raw Blame History

The menu's screen id and cursor, in guest memory

Found and verified 2026-08-26. Menu navigation in this corpus has always been driven by screenshots. That is unusable under --gpu=null, which is the only configuration where the game does not hit the software-rasterizer freeze (mission-freeze-heap-exhaustion.md) — so without a memory signal, the one backend that runs is the one that cannot be steered.

The words

address meaning
0x828A690C screen id1 title, 3 main menu, 4 extras
0x828F38AC menu cursor (a second copy at 0x828F38BC)
0x828F37B4 tracks the screen, distinct value per menu

How they were found

Snapshot 0x82800000 + 3 MB at each menu of a rendered run, then keep the 4-byte words that (a) differ between screens and (b) hold small integer values. Of 786 432 words, exactly four qualified — and one of them, 0x828A690C, has the property that matters: it changes on a screen transition and stays put when only the highlight moves.

screen:  title -> main menu -> (4x down) -> extras
828a690c:   1  ->     3     ->     3     ->    4      <- screen id
828f38ac:   2  ->     4     ->    12     ->   14      <- cursor moves with the highlight
828f37b4:  12  ->    45     ->    45     ->   49

Verified against a second run on a different GPU backend

The values were then read on a fresh --gpu=null run — no display at all — while driving the same key sequence blind:

step rendered (lavapipe) blind (--gpu=null)
title 1 / 2 / 12 1 / 2 / 12
main menu 3 / 4 / 45 3 / 4 / 45
after 4× down 3 / 12 / 45 3 / 12 / 45
extras 4 / 14 / 49 4 / 14 / 49

4 / 4 exact, across two runs and two backends. That is the check that matters: the words are not run-dependent, unlike the OB counter address this corpus had to mark run-dependent earlier.

tools/re-capture/menu_state.py reads them (menu_state.py watch polls and prints on change).

Still open: the rest of the sequence into a mission. Blind driving reached extras (screen 4) and a further Ⓐ did not move it — 4 / 14 / 49 twice — so MISSION SELECT needs a cursor move first. The screen ids beyond 4 are unmapped; the same snapshot-and-diff method extends to them, but it must be done on a rendered run, and the rendered run freezes on entering that screen. The way through is to map the ids up to the freeze and step blind past it.


🔴 Correction: these are counters, not a screen id and a cursor

2026-08-26, same day. The names above are wrong for at least two of the three words, and the test that shows it is going backwards.

Driving deep into the menus and then pressing Ⓑ (back) three times:

before after 3×
0x828F38AC ("cursor") 36 38 → 40 → 41
0x828F37B4 ("misc") 971 1067 → 1068 → 1068
0x828A690C ("screen id") 56 56, 56, 56

A cursor returns when you go back. These only ever increase — they are monotonic counters, and 0x828F38AC advances by ~2 per input. Driving forward gave 1, 3, 4, 5, 6, 8, 10, 12, 25, 29, 32, 33, 50, 53, 56 for the "screen id": that is a plausible identity sequence only if the game has 56+ screens and you never revisit one, which is precisely what a counter also looks like.

🔴 Withdrawn: "0x828A690C = screen id (1 title, 3 main menu, 4 extras)" as an identity. The values are path-dependent — they match across runs because the same key sequence produces the same count, not because 3 means main menu. 0x828F38AC is not a cursor and 0x828F37B4 is not a per-menu value.

What survives, and is still useful: all three advance if and only if the game responds, and they are stable when it does not. That is a genuine input-progress signal, reproducible across runs and both GPU backends, and it is what made blind navigation work. Read it as "did the game react?", never as "which screen is this?".

And it retro-confirms the freeze diagnosis. With the sign-in fix the sequence runs 3 → 5, skipping 4 entirely — so the old "4 = extras" was never a screen at all: it was the count at which the game stopped responding, i.e. the blocked state. Two readings of the same number, and the counter reading explains both.

Still open: a mission is not reached. After a dozen presses the counters are at 56 / 41 / 1068, guest churn is 0.190 % (alive — frozen is 0.000 %), and DEF_VTABLE / INST_VTABLE scans are still 0 / 0. Without a real screen identity, navigation is dead reckoning; finding an actual screen/state enum is the next job, and the snapshot-and-diff method that found these counters can be repeated with the counters themselves excluded.