# The title menu — how it moves, and where each button goes **Status:** ✅ `CONFIRMED` (**measured**, by driving the running game) for the movement rules and for all **five** main-menu destinations, `NEW GAME` included (→ `DIFFICULTY` → `SELECT DATA`, not a hang — corrected 2026-09-12, see the Q4 table). 🟡 the GamePart *id* behind each destination is a **name match onto the decoded id table**, not a measurement. Answers [MISSION Q5](../port/MISSION.md) and most of Q4. Nothing here is on the disc in any form found so far — the port is **authoring** these rules from this page, not transcribing a field. ## Q5 — movement Two boots via `tools/re-capture/boot_menu.sh`, cursor read off the focus ring with [`tools/re-capture/menu_focus.py`](../../tools/re-capture/menu_focus.py). | | behaviour | evidence | |---|---|---| | **initial focus, main menu** | **`TUTORIAL`** — the *middle* item, not the top | 2/2 boots, the first frame after the menu appears | | **initial focus, `EXTRAS`** | `MISSION SELECT` — the top item | [`extras-wrap.png`](captures/menu-nav/extras-wrap.png) | | **⬆⬇ — one item per press** | one item per press | ✅ *indirect but sound*: the wrap montage's **4 presses from `EXTRAS` landing on `OPTIONS`** only counts out if each press moves exactly one | | **⬆⬇ — no auto-repeat** | 🔴 **UNSETTLED, corrected 2026-09-12 — do not read this row as "none."** See [`f1-no-repeat-was-the-harness.md`](f1-no-repeat-was-the-harness.md): the driver this measurement drove input through (`--hid=file`'s `GetKeystroke`) is *deliberately* built to deliver exactly one event per press, by design, for other scripts' benefit — so it could not have shown repeat regardless of what the game does. A held direction moving the cursor exactly once was real and reproducible; what it proves is narrower than "no auto-repeat" and may be nothing at all. Kept below for the record | ~~measured 2026-08-30~~, [`data/nav-autorepeat-and-settled-b.txt`](data/nav-autorepeat-and-settled-b.txt). The counter passed its own control (a single 0.12 s tap gives exactly **1** spike, the hold gives **1**, against a 0.0003–0.0038 noise floor) — the counter was never the problem | | **wrap at the top** | ⬆ from the first item goes to the **last** | [`wrap-montage.png`](captures/menu-nav/wrap-montage.png), panels 1→2 | | **wrap at the bottom** | ⬇ from the last item goes to the **first** | same, panels 3→4, and 4 presses from `EXTRAS` landing on `OPTIONS` — i.e. wrapping — is what makes the count come out | | **left / right** | **nothing**, on the main menu | cursor unmoved across one ⬅ and one ➡ | | **Ⓑ on a submenu** | returns to the parent **with focus restored to the item you entered from** — `LOAD GAME`→`LOAD GAME`, `TUTORIAL`→`TUTORIAL`, `OPTIONS`→`OPTIONS`, `EXTRAS`→`EXTRAS` | 4/4 | | **Ⓑ on the main menu** | ✅ goes to the **title** — measured 2026-08-30, delivery-confirmed, **≤ 0.4 s**, and with **no loading screen** in between. ✅ **and the plate IS re-drawn**: Ⓑ on the menu at 351.2 s, plate pulse detected at 358.5 s — ~7 s later (2026-08-30) | **1 run** — [`../re/data/b-on-main-menu.txt`](data/b-on-main-menu.txt) · [mid-build-in](captures/title-builds/live-b-on-menu-title-buildin.png) · [settled](captures/title-builds/live-b-on-menu-title-settled.png). The footer point below still stands | | **Ⓑ on the title** | ✅ **nothing** — 20 s after a delivery-confirmed Ⓑ the screen is still the title, `PRESS Ⓐ BUTTON` up | measured 2026-08-30, [capture](captures/title-builds/live-b-on-settled-title-no-effect.png) · [series](data/nav-autorepeat-and-settled-b.txt). ✅ **This run waited for the plate pulse — the title's own settled signature — before pressing**, which is what the earlier attempt failed to do; its press landed during the build-in and was confounded. The 4.3 % of pixels that move are the plate's pulse and the sweeps (glyph 730, inside the 714–1520 pulse band) | Wrap holds on both screens tested — the 5-item main menu and the 3-item `EXTRAS` submenu — so it is a menu rule, not a per-screen table. ## ✅ 2026-08-31 — SETTLED: a submenu resets to the item it **opens on**, not to its top item **measured** — [`data/difficulty-resets-to-named-item.txt`](data/difficulty-resets-to-named-item.txt), [capture](captures/menu-nav/live-difficulty-opens-normal.png). `DIFFICULTY` is the screen that separates the two readings, because it opens on **`NORMAL`** — the second of `EASY` / `NORMAL` / `HARD` / `BACK`. Reproduced on a fresh boot today rather than inherited from the 2026-08-29 capture. | | | |---|---| | opened on | `NORMAL` | | after 1 delivery-confirmed DOWN | `HARD` | | after Ⓑ → main menu → Ⓐ → `DIFFICULTY` | **`NORMAL`** — in-cursor **1.0** from opened vs **93.9** from where left | ✅ **So reset goes to the opening item, and the opening item is a per-screen default that need not be the first.** `DIFFICULTY` returns to `NORMAL`, not `EASY`. 📌 The other four could not settle it because on `EXTRAS`, `TUTORIAL`, `OPTIONS` and `LOAD GAME` the opening item **is** the first item, so both readings predict the same observation. Five screens, and only the fifth carries the distinction — which is why `sylpheed-port` was right to refuse to promote 4/4 to a rule. ⚠️ **Safety, and it is why the run was possible**: `DIFFICULTY`'s *forward* path crashes the guest (Ⓐ → `SELECT DATA` → `PC 0x82307128`). The probe presses Ⓐ to enter, one DOWN, then Ⓑ to leave, and **never presses Ⓐ inside a submenu**. ⚠️ Reach: one boot, one round trip. Untested: whether the reset target moves once a difficulty has actually been **confirmed** — this run never confirms one. ## 🔴 2026-08-31 — a submenu's opening item is NOT always its first: `DIFFICULTY` opens on `NORMAL` **Already in this file, and I missed it.** `sylpheed-port` has been asking for a submenu whose opening item is not the first one, because that is what separates *"resets to the named item"* from *"resets to the top item"*. I told them none of the screens I measured was one — while **line 248 of this page** records `DIFFICULTY` as *"`EASY` / `NORMAL` / `HARD` / `BACK` … opening focused on `NORMAL`"*. ✅ **The provenance is clean and it is genuinely an opening state**: the run drove `NEW GAME` with **no d-pad**, the screen *"sat unchanged for 90 s"*, and [`s00a-drive-blocked-by-focus.md`](s00a-drive-blocked-by-focus.md) confirms the step matched the committed capture at **r = +0.999**. **So `NORMAL` — the second of four — is a default, not a top item.** That refutes *"a screen opens on its first item"* as a general description, and it means the distinction the port is asking about is **real in this game**, not academic: on `EXTRAS`, `TUTORIAL` and `OPTIONS` the two readings coincide only by accident. ❔ **It does not yet settle their question**, which is about **reset** rather than opening: to decide it, move the cursor in `DIFFICULTY`, leave, re-enter, and see whether it returns to `NORMAL` (named) or `EASY` (top). One experiment, and `DIFFICULTY` is the screen that can carry it. ⚠️ Its exit path crashes the guest (`SELECT DATA`, `PC 0x82307128`), so the run must go **back** rather than forward. 📌 The failure worth naming is mine: **I searched for a case among the screens I was measuring, and never grepped the page I was editing.** An answer already in the corpus is only as good as the reader's ability to connect it — the same amplifier problem as the stale index row, arriving from the other direction. ## ✅ 2026-08-31 — ALL FOUR measured submenus reset. The main menu is the exception. **measured** — [`data/submenu-focus-all-reset.txt`](data/submenu-focus-all-reset.txt), `tools/re-capture/submenu_focus_sweep.py`, one boot, fourth attempt. | screen | verdict | in-cursor: from opened / from where left | |---|---|---| | `LOAD GAME` | **RESETS** | 21.6 / 86.3 | | `TUTORIAL` | **RESETS** | 2.3 / 113.2 | | `OPTIONS` | **RESETS** | 1.9 / 102.6 | | `EXTRAS` (2026-08-30) | **RESETS** | 0.8 / 82.8 | | **main menu** | **PERSISTS** | — | ✅ **So the rule is simple after all, and it is the opposite of what one screen suggested**: submenus reset; the **main menu alone** remembers. Four of four. ✅ **Screens confirmed by eye**, because an earlier run was fooled about which screen it was on: [`TUTORIAL`](captures/menu-nav/live-tutorial-submenu.png) — seven items under `Level 1`/`Level 2` headers plus `BACK` — and [`LOAD GAME`](captures/menu-nav/live-load-game-slots.png), a **scrolling** slot list with the selection held at the vertical centre. 📌 `LOAD GAME`'s 21.6 is the only figure not near zero, and the capture explains it: that list **scrolls** instead of moving a ring, so re-entry restores a scroll position rather than a cursor sprite. Same verdict, different mechanism. ❔ **Still not separated: "resets to the named item" vs "resets to the top item".** `sylpheed-port` asked for a submenu whose opening item is not its first. None of these is one — `TUTORIAL` opens on `BASIC CONTROLS`, `OPTIONS` on `GAME SETTINGS`, and `LOAD GAME` on slot **01**, which *looks* non-first only because slots 19 and 20 are drawn above it by a wrapping list around a centred selection. ⚠️ Reach: one boot, one round trip per screen, one direction, one entry each. ❔ `NEW GAME` stays deliberately untested. ## ✅ 2026-08-30 — EXTRAS **resets**; the main menu **persists**. They differ. **measured** — [`data/extras-focus-resets.txt`](data/extras-focus-resets.txt), `tools/re-capture/extras_focus_persistence.py`. | | ring y | item | |---|---|---| | EXTRAS opened on | 347.5 | `MISSION SELECT` | | after 1 delivery-confirmed DOWN | 427.5 (+80.0) | `MOVIE THEATER` | | after Ⓑ → main menu → Ⓐ → EXTRAS | **347.5** | **`MISSION SELECT`** | Re-entry is **0.0 %** different from the first entry. So: * ✅ **EXTRAS resets.** `sylpheed-port` asserted this in their contract-check when nothing had measured it, and I flagged the assertion as an absence of evidence encoded as a positive claim. **They were right, and it is now measured.** * ✅ **`MISSION SELECT` is a genuine INITIAL focus**, precisely because this screen resets — unlike the main menu, where a reading not taken on a fresh boot's first entry measures history. * 🔴 **The two screens behave differently, so there is no menu-wide rule.** The main menu persists; EXTRAS does not. A generalisation in *either* direction would be wrong, which is why wrap (measured on two screens) generalises and this does not. * ✅ The screen was confirmed **by eye** — `E1.png` is EXTRAS, MISSION SELECT / MOVIE THEATER / BACK — because the previous run was fooled about which screen it was on. And the 80.0 px step independently matches the main menu's separately calibrated 79.25. ⚠️ Reach: one run, one round trip, one submenu. `OPTIONS`, `LOAD GAME` and `TUTORIAL` are untested, as is whether the reset is to `MISSION SELECT` or simply to the top item — those coincide here. ## 🔴 2026-08-30 (later) — the item NAMES below were wrong, and initial focus is NEW GAME **The reader was broken and my control could not see it.** `menu_focus.py`'s row centres are **design-space** rows read off `screenshot` output; my probes fed it whole-display `x11grab` frames, which carry Xenia's title bar and menu bar and show the game surface scaled by **1.060**. Caught by ground truth, not by a control: the probe announced *"on EXTRAS"*, pressed Ⓐ, and opened **OPTIONS**. Ring rows measured directly (`tools/re-capture/ring_row.py`), no assumed geometry: | frame | ring y | true item | |---|---|---| | first menu entry, fresh boot | **225.5** | **`NEW GAME`** | | after 2 delivery-confirmed DOWNs | 384.0 | `TUTORIAL` | | after Ⓑ → title → Ⓐ → menu | **385.5** | `TUTORIAL` | * ✅ **Initial focus on a fresh boot is `NEW GAME`** — 2/2 fresh boots, both the *first* menu entry. That agrees with `boot_menu.sh`'s own closing line and with [`menu-state-in-memory.md`](menu-state-in-memory.md)'s four-downs-to-`EXTRAS`, which only counts from `NEW GAME`. ~~"initial focus, main menu — TUTORIAL"~~ in the Q5 table below is **withdrawn**: it is the outlier, and this reading is the direct one. * ✅ **Persistence stands, and is now geometry-free**: 384.0 vs 385.5, 1.5 px apart. An equality test is immune to a constant offset, which is why that conclusion survived a broken reader when the labels did not. * 🔴 **The names I published for it were two positions out** — reported `TUTORIAL → EXTRAS → EXTRAS`, truth `NEW GAME → TUTORIAL → TUTORIAL`. * ⚠️ **The control was structurally blind to this.** "Two DOWNs must move the cursor exactly two items" tests *relative* motion, and a constant offset preserves relative motion exactly. **A control that only checks differences cannot see an error in the origin.** [data](data/menu-focus-reader-offset.txt) ## ✅ 2026-08-30 — the menu REMEMBERS its cursor across menu → title → menu **measured** — [`data/focus-persists-across-title.txt`](data/focus-persists-across-title.txt), `tools/re-capture/focus_persistence.py`. One run, control passed: | step | focus | ring vector | |---|---|---| | F1, on the menu | `TUTORIAL` | 130 76 **254** 69 64 | | F2, after 2× DOWN (**both delivery-confirmed**) | `EXTRAS` | 130 76 66 69 **254** | | F3, after Ⓑ → title → Ⓐ → menu | **`EXTRAS`** | 130 76 66 69 **254** | **F3 == F2, so focus persists** — the menu is re-entered on the item you left, not on a fixed one. 📌 **And this reframes the disagreement below rather than settling it.** If focus persists, then *any* "initial focus" reading not taken on a fresh boot's **first** menu entry is measuring history. The records need not disagree about the game at all — they may differ in what the cursor had already been moved to. **Nothing here says what the menu opens on**; this run's F1 was itself carried over from a prior probe's press. ⚠️ Reach: one boot, one round trip, one direction. Persistence across a **reboot** is untested, and is the reading that would matter for authoring a default. ⚠️ **2026-08-30 — and the sources DISAGREE, which nothing here had noticed.** `boot_menu.sh`'s own closing line says *"AT MAIN MENU (cursor on NEW GAME)"*, and [`menu-state-in-memory.md`](menu-state-in-memory.md)'s run reaches `EXTRAS` in **four** downs, which only counts from `NEW GAME`. Two sources say `NEW GAME`; this table says `TUTORIAL` 2/2. `skip_intro.sh` presses Ⓐ once and no d-pad, so the harness is not moving the cursor and that does not explain it. 🔴 **I tried to settle it and could not: the boot never reached the menu**, twice — the title gate cannot fire on this title ([harness-title-gate-assumes-a-static-title](harness-title-gate-assumes-a-static-title.md)). So the disagreement stands, and the round trip that would answer the persistence question — menu → Ⓑ → title → Ⓐ → menu, is focus where you left it or reset? — has still never been run. `tools/re-capture/focus_persistence.sh` is written and ready for a harness that can reach the menu. **🟡 Initial focus is reproducible but not established as invariant.** Both of my boots opened on `TUTORIAL`, and both used `boot_menu.sh`. The run recorded in [`menu-state-in-memory.md`](menu-state-in-memory.md) reached `EXTRAS` with *four* downs from the main menu, which only works from `NEW GAME`. Either the harness path matters or something persists. **Do not hardcode `TUTORIAL` without re-testing it**; what is solid is that the menu does *not* open on the top item in this harness. ## Q4 — where each button goes Measured by driving: focus the item, press Ⓐ, read the screen's own title. | button | screen it opens | evidence | GamePart id | |---|---|---|---| | `NEW GAME` | 🔴 **stale row, corrected 2026-09-12** — measured 2026-08-28: `DIFFICULTY` (`EASY`/`NORMAL`/`HARD`/`BACK`) → `SELECT DATA` → guest crash (unrelated cache-manager bug, not a menu fault). The "`NEW GAME` — measured" section further down this same page had the answer already and this table was never updated to match it | [captures](captures/newgame-path/) | `DIFFICULTY`: **no id-table name match** — already tried and refuted (`boot-config-and-gamepart-registry.md`: neither `DIFFICULTY` nor `EXTRA_MENU` survive as call-site strings). `SELECT DATA`: 🟡 `2 GP_SELECT_STORAGE`, a fresh name-guess, same low confidence as every other row here | | `LOAD GAME` | the save-slot list, `LOAD GAME` / `Current Storage` | [`q4-destinations.png`](captures/menu-nav/q4-destinations.png) left | 🟡 `3 GP_LOAD` | | `TUTORIAL` | the lesson list, `TUTORIAL`, Level 1 / Level 2 | same, middle | 🟡 `25 GP_TUTORIAL` | | `OPTIONS` | `OPTIONS` — GAME / CONTROL / SOUND / SCREEN SETTINGS / BACK | same, right | 🟡 `8 GP_OPTIONS` | | `EXTRAS` | **`GP_TITLE.pak` build 6** — MISSION SELECT / MOVIE THEATER / BACK | [`ui-title-build-map.md`](ui-title-build-map.md) | 🟡 `5 GP_EXTRAS` | | `EXTRAS ▸ MISSION SELECT` | the stage list + Wide Area Space Map — **8 rows visible of 16**, and rows below the first are **locked** on a fresh save ([below](#-mission-select-the-cursor-was-stuck-because-the-stages-were-locked)) | [`mission-select-stage01-only.png`](captures/mission-select-stage01-only.png) | 🟡 `7 GP_MISSION_SELECT` | | `EXTRAS ▸ MOVIE THEATER` | ❔ not tested | | 🟡 `6 GP_MOVIE_THEATER` | **Say which, as the gate asks.** The *screen* each button opens is **measured** — I pressed the button and read the title off the framebuffer. The **GamePart id is not measured**: it is the entry of the decoded 29-id table at `.rdata 0x820A1630` ([`challenge-mission-gate.md`](challenge-mission-gate.md) §3) whose *name* matches the screen I saw. The table is decoded; the *binding* of a button to an entry in it is a name match I made by eye. The port should treat these ids as authored. Worth noting that the ids and the paks are not one-to-one: `GP_EXTRAS` is id 5 with **no pak of its own** — its artwork is a build inside `GP_TITLE.pak`. ~~**❔ `NEW GAME` was deliberately not pressed.**~~ **Withdrawn — stale, fixed 2026-09-12.** This line said Ⓐ on it hangs the emulator ([`ui-paint-order-third-permutation.md`](ui-paint-order-third-permutation.md)), which the very next section of this same page already refuted on 2026-08-28: it does not hang, it opens `DIFFICULTY` then `SELECT DATA` before an unrelated crash. Kept struck rather than deleted — this is the exact failure this corpus keeps naming, a correction that landed lower in the same document than the claim it corrected and never caught up to the table above. ### 🔴 The "cheap way to finish this" was a dead route — WITHDRAWN 2026-08-29 This section used to say: *`0x828A690C` holds a live screen id (1 title, 3 main menu, 4 extras) and `0x828F38AC` the cursor; read them while pressing Ⓐ and the transition becomes a measurement, under `--gpu=null` with no screenshots.* **Do not do that. Those words are monotonic counters, not state.** [`menu-state-in-memory.md`](menu-state-in-memory.md) withdrew that identity **on the same day it was published** — driving deep and then pressing Ⓑ three times sends the "cursor" `36 → 38 → 40 → 41`, and a cursor returns when you go back. The values match across runs because the same key sequence produces the same count, not because `3` *means* main menu. With the sign-in fix the sequence runs `3 → 5`, skipping `4` entirely, so "4 = extras" was never a screen at all. This page kept recommending the route for three days after the page it cited had killed it. ⚠️ **A cross-reference is not a citation unless you re-read the target** — the two documents disagreed in the corpus and either would have been believed on its own. ✅ **What those words are still good for**: all three advance if and only if the game responds to input, and are stable when it does not. Read them as *"did the game react?"*, never as *"which screen is this?"*. Screen identity still has to come off the framebuffer. ❔ **So a measured button→GamePart-id binding remains unfinished**, and for the reason it always was: no screen/state enum has been located in guest memory. The ids in the table below stay a name match. ## ✅ `NEW GAME` — measured 2026-08-28, and it is not a hang The one destination this page could not test has been driven. **Ⓐ on `NEW GAME` does not hang.** It opens two more menus first: ``` NEW GAME -> DIFFICULTY -> SELECT DATA -> guest crash ``` * **`DIFFICULTY`** — `EASY` / `NORMAL` / `HARD` / `BACK`, footer `Ⓐ : OK Ⓑ : Back`, opening focused on **`NORMAL`** ([capture](captures/newgame-path/newgame-difficulty.png)). It sat unchanged for 90 s with the emulator healthy — a menu waiting for input, which is exactly what "a standing hang" looks like to a screenshot loop that never presses anything. * Ⓐ on `NORMAL` → **`SELECT DATA`**, a save-slot picker headed `Current Storage: Dummy HDD`, prompting to pick a file for the auto-save. * Then the guest throws, and Xenia pauses with `PC: 0x82307128` ([capture](captures/newgame-path/newgame-selectdata-crash.png)). **That crash is already in the corpus and is not new**: `0x82307128` is inside `sub_823070B0`, the cache-manager STL erase documented in [`title-crash-stl-tree.md`](title-crash-stl-tree.md), whose trigger is an incomplete on-disc shader/code cache — not the menu path. The corpus also already holds `captures/select-data-crash.png`. So Q4's last row closes as **measured**: | button | screen it opens | |---|---| | `NEW GAME` | **`DIFFICULTY`** (then `SELECT DATA`) | 🟡 The GamePart ids for these two are unmeasured, like the rest — `24 GP_DIALOG` and `3 GP_LOAD` / `2 GP_SELECT_STORAGE` are name-match candidates and nothing more. ### Initial focus — six data points now, and it still varies This boot opened the main menu on **`NEW GAME`**. Running tally across four boots of the same harness: `TUTORIAL`, `TUTORIAL`, `NEW GAME`, `NEW GAME`. Unchanged conclusion: **do not hardcode it.** ✅ **Two more, 2026-08-29, and the split is now even.** A drive that pressed Ⓐ with no d-pad movement ended in a **tutorial mission** (+0.960 against `tutorial-mission-reached-then-crash.png`), so that boot opened on `TUTORIAL`. A later boot read **`NEW GAME`** from a focus detector on the first menu frame. **Tally: `TUTORIAL` ×3, `NEW GAME` ×3.** Six boots, same harness, no other item ever seen. ⚠️ It is *not* uniform across the five buttons — only these two occur — which is a constraint on whatever selects it, and something a future explanation has to account for. Still **do not hardcode it**, and note that `newgame_path.sh`'s "NEW GAME is the first item so no d-pad is needed" is wrong half the time — see [`s00a-drive-blocked-by-focus.md`](s00a-drive-blocked-by-focus.md). ### The `NEW GAME` path completes — the `SELECT DATA` crash is state, not path A second run of the same path, 2026-08-28, **did not crash**: ``` NEW GAME → DIFFICULTY → (Ⓐ on NORMAL) → SELECT DATA → (Ⓐ on a slot) → a movie plays ``` The previous run's throw at `PC 0x82307128` is therefore **not inherent to this menu path** — the same six presses got through it. That is consistent with the trigger `title-crash-stl-tree.md` already names (an incomplete on-disc cache) and with nothing about `NEW GAME`. 🟡 n = 1 either way; do not read it as "fixed". Worth recording because the first observation could easily have hardened into "the new-game path crashes", which is what "A on NEW GAME hangs" had already become once. --- ## 🟡 Refutation attempt 2026-08-29 — the main menu's own footer does **not** advertise Ⓑ **Attempted claim:** this page's row *"Ⓑ on the main menu goes to the title, which re-draws `PRESS Ⓐ BUTTON` after a beat"*. **Why this row and not another.** It is one of only **two** rows in the Q5 table with an **empty evidence cell** (the other is "Ⓑ on the title → nothing"); every row that cites a capture cites one. And it is a rule the port will build on directly — it is the only way out of the main menu. **The measurement** — whole-frame colour test for the pad-glyph discs, run by [`tools/re-capture/footer_and_locked_rows.py`](../../tools/re-capture/footer_and_locked_rows.py) against the committed captures: | capture | Ⓐ glyph px | Ⓑ glyph px | |---|---|---| | `live-main-menu.png` | 438 | **0** | | `live-main-menu-options-focused.png` | 438 | **0** | | `live-extras.png` | 440 | 514 | | `difficulty-screen.png` | 438 | 518 | **The control passes twice over.** The same detector, unchanged, finds the red Ⓑ on the two screens that visibly have one; and the **Ⓐ** count is 438/438/440/438 across all four, i.e. the same glyph asset at the same size on every screen — so a Ⓑ of that family would have been ~450–520 px and cannot have fallen under a threshold. The negative is over the **whole frame**, not a guessed footer band: `live-main-menu.png` contains **zero** red-glyph pixels anywhere. So the main menu's legend reads `⊙ : Select Ⓐ : OK` where every submenu reads `⊙ : Select Ⓐ : OK Ⓑ : Back`. **Verdict: the claim SURVIVES, at reduced confidence, and the row is downgraded to 🟡.** A legend is not behaviour — a game may accept an unadvertised Ⓑ — so an absent glyph cannot refute a press that was actually observed. But: * the observation has **no capture behind it**, and it is now the only Q5 row contradicted by the game's own on-screen text; * there is a **named confound**: the title-side screens auto-return on idle, and "I pressed Ⓑ and ended up at the title, which drew `PRESS Ⓐ BUTTON` after a beat" is also exactly what an idle timeout looks like to an observer who does not hold the two apart. The corpus documents that timeout at ~8–10 s ([`boot-config-and-gamepart-registry.md`](boot-config-and-gamepart-registry.md)). **What would settle it:** press Ⓑ on the main menu and read `0x828A690C`, the live screen id (`1` title, `3` main menu, `4` extras) — a transition inside a second is a Ⓑ, one at ~8–10 s regardless of the press is the timeout. Cheap, and it needs no screenshots. 🔴 **Not runnable here.** This container has no disc and no ISO, so there is no oracle at all — see [`capture-harness-status.md`](capture-harness-status.md#-2026-08-29--the-disc-is-not-in-the-decoder-container-at-all). **For the port:** Ⓑ from the main menu to the title is **measured, single observation, uncited, and unadvertised by the game**. Implement it — it is the only exit — but treat it as authored rather than transcribed, and do not also build the idle-return on the assumption that the two are distinct until someone has separated them. --- ## ✅ MISSION SELECT: the cursor was stuck because the stages were **locked** **Measured 2026-08-29 from committed captures**, no disc needed. Settles the ⚠️ open in [`../game/navigation.md`](../game/navigation.md): *"sixteen d-pad presses never left Stage 01 — whether that is because only one stage was unlocked, or because the list is driven some other way, is unknown"*. The stage list has **three** label brightnesses, not two, and that is what discriminates. Sampling the label strip (x 190…320) of each of the 8 visible rows, 95th percentile of luminance: | capture | row 1 | rows 2–8 | |---|---|---| | `mission-select-stage01-only.png` | **254** | **104** | | `mission-select-all-story-unlocked.png` | **254** | **183** | | `mission-select-ends-at-stage16.png` | 183 | 183 ×6, then **254** on row 8 | * **254** = focused (the row carrying the spinning focus ring) * **183** = unlocked, not focused * **104** = **locked** The all-unlocked capture is the control: it holds row 1 focused at the identical 254 while rows 2–8 move 104 → 183 as one uniform step. So the dim rows in the Stage01-only capture are **not** "unfocused"; unfocused is 183, and they are 79 levels below it. **And the cursor does move when they are unlocked.** In `mission-select-ends-at-stage16.png` the list has scrolled to show Stage09…16, the scrollbar thumb is at the bottom, and the focus ring is on **Stage16** — the last row. Locked list: 16 presses, no movement. Unlocked list: the cursor reaches the end. | | | |---|---| | **rows visible at once** | **8** | | **list length** | **16** (`Stage01`…`Stage16`; the scrollbar bottoms out at 16) | | **why 16 presses did nothing** | every row below the first was locked | ⚠️ **Reach.** This is a still image, so it says the cursor *reached* Stage16, not how it got there and not whether the list wraps — the scroll thumb bottoming out at row 16 is consistent with either. Whether a *locked* row is skipped or simply unreachable is likewise not separated: with only row 1 unlocked the two are the same observation.