diff --git a/docs/re/BACKLOG.md b/docs/re/BACKLOG.md index 140a8cea..1432e180 100644 --- a/docs/re/BACKLOG.md +++ b/docs/re/BACKLOG.md @@ -176,9 +176,14 @@ main menu has been reached (screenshot in successes without `--log_ui_draws`, 0 of 7 with it. An interleaved series **refuted the boot-time confound** (the latest title of all, 268 s, accepted Ⓐ; a 232 s title refused), and no mechanism exists for the flag — it is read only -when F10 arms a capture, and F10 was never pressed. The variable has been removed -rather than believed: F10 now arms the capture unconditionally, so navigation -runs need no flag. Until that +when F10 arms a capture, and F10 was never pressed. The variable was removed rather than +believed — F10 now arms the capture unconditionally — and with it gone a fresh +run **still** failed, so the flag is not the cause either. Net: Ⓐ succeeds about +half the time and nothing measurable predicts which; five explanations are +eliminated. The input path is now mapped statically (`entry_point` → +`sub_8216EA68` main loop → `sub_822F1AA8` per-frame input → `sub_82457038` pad +poll → `XamInputGetKeystrokeEx`), and the poll itself is not state-gated, so the +gate is in a consumer further up. Until that is separated, capturing a screen *and* navigating to it in the same run is not dependable. The earlier claim, kept: the title that ends the boot sequence accepts a single Ⓐ (2 of 2 at the time); the title the attract loop returns to diff --git a/docs/re/canary-scripted-input-traps.md b/docs/re/canary-scripted-input-traps.md index a69d6f22..1b773e52 100644 --- a/docs/re/canary-scripted-input-traps.md +++ b/docs/re/canary-scripted-input-traps.md @@ -252,3 +252,50 @@ content call on the press, and the age of the title — and the fifth (the captu flag) has a strong correlation and no possible mechanism. The next honest step is not another guess from outside: it is the guest's own state machine, and that means reading the title code in `sylpheed.db`. + +### 2026-08-19 (later) — the flag hypothesis loses its own test + +With the capture cvar **removed from the launch line entirely** (F10 arms +unconditionally now), a fresh navigation run reached the boot title and Ⓐ **did +nothing**. So the flag is not necessary for the failure, and the correlation — +0 of 7 with it, 4 of 6 without it — does not survive as an explanation. + +What is left is the plain reading, and it is worth stating as the conclusion +rather than as a stepping stone: **Ⓐ at the title succeeds about half the time, +and nothing measurable from outside predicts which.** Eliminated so far: Xenia UI +swallowing the keystroke (diagnostic never fires), the driver filter (flags 3 vs +`Controller = 1`), a sign-in or content call on the press (none is made), the age +of the title (the latest title of all accepted; an earlier one refused), and now +the capture cvar. + +## The input path, mapped statically + +Since the outside is exhausted, the guest side was traced in `sylpheed.db`: + +``` +entry_point 824AB748 + └ sub_8216EA68 (968 B) main loop + └ sub_822F1AA8 (996 B) per-frame input update + └ sub_82457038 (628 B) THE PAD POLL + └ sub_824AA870 → XamInputGetKeystrokeEx (flags = 3) +``` + +`XamInputGetKeystrokeEx` has exactly **one** caller in the whole title +(`sub_824AA870`, a wrapper that maps user index `0xFF` to 0 and ORs in +`0x4000_0000` = ANY_USER), and that has exactly one caller, the poller. The +poller's shape is readable and matches the runtime trace: + +* `+0` flags word — bit 31 "disabled", bit 30 "copy current→previous", bit 3 + "also poll device state"; +* a **keystroke queue** at `+68` with a count at `+72`: it drains + `GetKeystrokeEx` with `flags = 3` into 8-byte slots (the same `flags = 3` the + phase-A trace recorded, so this is the code the trace was watching); +* the current pad state at `+36`, the previous at `+52`, compared field by field + at the end (buttons `+40/+56`, triggers `+42/+43`, sticks `+44…+50`) to return + "changed" (3) or "unchanged" (0), and 2 if the device vanished. + +**Nothing in that path is state-gated** — it polls unconditionally and reports +changes. Whatever ignores Ⓐ at an attract title is a *consumer* further up, and +finding it means identifying the object the poller fills (passed in as `r3` from +the per-frame update) and then its readers. That is a real RE job, not a +one-iteration probe, and it is where this thread now stands.