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/canary-scripted-input-traps.md
Sylpheed RE agent de038c54c0 docs/re: why a scripted run cannot get past the title — three traps and a blocker
Each of these presents as "the pad is dead", and each has a different cause.

1. **F10 opens the emulator's menu bar.** It is the RE capture hotkey AND the
   toolkit's menu key. With that menu open — or any Xenia UI window, the
   Profiles Menu included — `IsUIActive()` is true, so XamInputGetKeystrokeEx
   returns SUCCESS with a ZEROED keystroke before the pad driver is asked. The
   guest polls, gets nothing, and does nothing, with no error anywhere. Escape
   does not close it; a click on the game surface does. This cost most of an
   iteration.

2. **The file-pad was never the problem.** It delivers (vk=5800 down/up per tap)
   and A skips movies in the same runs.

3. **(A) at the title needs a signed-in profile.** Without one the guest calls
   XamShowSigninUI and Xenia's dialog appears — which is also the proof the
   guest reads the button. That dialog cannot be completed here: the gamertag is
   an ImGui text field and synthetic X key events never reach it. Hence Canary's
   new --create_profile_if_none.

And the blocker, stated as measured rather than as a theory: with the profile
signed in, (A) still does not advance the title across four boots. The
reproducible failure is next door — with the default --mem_watch=true the guest
crashes in the boot content path (read of 0x10000000C at 0x82307128, thread 9,
after a guest C++ throw), and with --mem_watch=false it does not. That is a
second, far cheaper reproduction of the Ready-Room crash the canary handoff
blames on the mem_watch probe: 40 s from a cold boot instead of after a mission.

One observation kept because it did not reproduce: a single (A) once crashed the
guest at a DIFFERENT PC (0x824578A0, thread 6). Two attempts to reproduce it
gave neither a crash nor a transition.

Next step named: those two PCs in xenia-rs/sylpheed.db, and the content exports
around the press.
2026-08-18 20:16:27 +00:00

121 lines
6.9 KiB
Markdown

# Getting past the title screen in the container — three traps and one blocker
**Status:** ✅ `CONFIRMED` for the three traps (each reproduced, and two of them
fixed in the toolkit). 🔴 **blocked** on reaching the main menu: the guest reads
Ⓐ at the title, and the step *behind* Ⓐ either crashes it or stalls it.
Written down because each of these presents as "the pad is dead" or "the game
ignores input", and each has a completely different cause.
## 1. F10 opens the emulator's menu bar, and that swallows every guest keystroke
F10 is the RE hotkey (ship capture, and now `log_ui_draws`). It is *also* the
toolkit key that opens the application menu bar, and it does both. With that menu
open, `XamState::IsUIActive()` is true, so `XamInputGetKeystrokeEx` returns
`X_ERROR_SUCCESS` with a **zeroed** keystroke before the driver is ever asked
(`xam_input.cc`). The guest polls, gets an empty event, and does nothing —
forever, and with no error anywhere.
This cost most of an iteration. Symptom: a run presses F10 to arm a capture,
then every later Ⓐ does nothing; the title sits there while the pad log happily
prints `[file-pad] keystroke vk=5800 down`. Screenshot
[`captures/title-with-emulator-menu-open.png`](captures/title-with-emulator-menu-open.png)
shows the giveaway — `Open… / Open Recent / Install Content… / Exit` over the
title art. It is easy to miss because the menu is at the far left of the window
and the game is still animating behind it.
**Fix:** after any F10, click once on the game surface to dismiss the menu.
`Escape` does *not* close it. `ui_draw_capture.sh` now does this.
## 2. The pad is fine — the driver was never the problem
Worth stating because the file-pad's own history (`--hid=file`, `GetKeystroke`
implemented specifically so "PRESS Ⓐ BUTTON" would work) makes it the natural
suspect. It delivers: the log shows `vk=5800 down`/`up` per tap, and Ⓐ during a
movie skips the movie, every time. When the title ignores Ⓐ, the pad is not why.
## 3. Ⓐ at the title needs a signed-in profile — and this container cannot type one in
With no profile, Ⓐ **is** handled: the guest calls `XamShowSigninUI` and Xenia
pops its Sign In dialog ([`captures/title-signin-dialog.png`](captures/title-signin-dialog.png)),
`ProfileManager: Found 0 Profiles`. That dialog is the proof the guest reads the
button.
The dialog cannot be completed from here: "Create Profile" opens an **ImGui text
field** for a gamertag, and synthetic X key events do not reach it. Tried, all
with the window focused (`xdotool getwindowfocus` = the game window):
`xdotool type --window`, `xdotool type` via XTEST, single `xdotool key` presses,
clicking the field first. The field stays empty; `Create` with an empty gamertag
is refused. Mouse clicks *do* work (they opened the dialog and the sub-panel), so
it is text entry specifically.
Xenia's own **Profile ▸ Show Profile Menu** panel does have a working `Create
Profile` button, and mouse clicks reach it — but the gamertag it then asks for is
the same ImGui field, so the UI route dead-ends in the same place.
**Fix, landed in Canary** (`auto/re-ui-draw-order`): a `--create_profile_if_none=<gamertag>`
cvar that calls `ProfileManager::CreateProfile(tag, autologin, default_xuid)` at
startup when no profile exists. `default_xuid` is fixed at `B13EBABEBABEBABE`, so
a script can then pass `--logged_profile_slot_0_xuid=B13EBABEBABEBABE` and be
deterministic. Verified: `ProfileManager: RE bootstrap profile 'SylphRE' ->
created`, then on the next boot `Found 1 Profiles` / `Loaded SylphRE (GUID:
B13EBABEBABEBABE) to slot 0`, and the Profiles Menu panel shows the user
([`captures/xenia-profile-panel-signed-in.png`](captures/xenia-profile-panel-signed-in.png)).
The profile persists on disk, so later runs need only
`--logged_profile_slot_0_xuid=B13EBABEBABEBABE`.
## The blocker: what happens *after* Ⓐ
With the profile created and signed in — Xenia's own **Profile ▸ Show Profile
Menu** confirms it, `User: SylphRE / XUID: B13EBABEBABEBABE / Assigned to slot: 1`
(the panel counts from 1; the log says slot 0) — Ⓐ at the title **still does not
advance the screen**. Measured across four boots, including one that was allowed
to play the whole intro untouched, with holds of 10 s and bursts of five taps.
What is *not* the explanation, each checked:
* the emulator menu bar being open (trap 1) — the grabs are clean;
* the pad (trap 2) — Ⓐ skips movies in the same runs;
* the profile being absent (trap 3) — it is present, signed in, and the Sign In
dialog no longer appears;
* an ImGui window being open — but note this generalises trap 1: **any** Xenia UI
window makes `IsUIActive()` true, the Profiles Menu included, so a panel left
open silently disables the guest's input for as long as it is up.
**One observation that did not reproduce, recorded rather than dropped.** In the
run where the Profiles Menu had just been closed, a single Ⓐ **crashed the
guest** — PC `0x824578A0`, guest thread 6, distinct from the boot-path crash
below. Two later attempts to reproduce it (open the panel, close it, press Ⓐ)
produced neither a crash nor a transition. So it is one data point that Ⓐ *can*
reach code the title does not otherwise run, and nothing more.
**The reproducible crash is the boot-time content path.** With the default
`--mem_watch=true`, in two independent runs, the guest dies with an access
violation reading `0x00000001_0000000C` at PC `0x82307128` on guest thread 9,
right after `HostPathDevice::ResolvePath(\aab216c3\5\c10eae6)` and a
`RtlRaiseException(E06D7363)` (a C++ throw). Xenia pauses itself and stacks up
crash dialogs — 991 in one run. With `--mem_watch=false` that crash does not
happen at all.
That pairing — crash with the memory-probe thread on, none with it off, both in a
save/content path — matches the suspect ranked #1 in
`xenia-canary/HANDOFF-crash-oracle-2026-07-16.md`, whose crash was also a guest
C++ exception in a cache/save path. This is a second, far cheaper reproduction of
it: at the **title screen**, ~40 s from a cold boot, instead of in the Ready Room
after a mission.
**Next step, for whoever picks this up.** Two threads to pull, in this order:
1. `0x82307128` and `0x824578A0` in `xenia-rs/sylpheed.db` (the container has it)
— what function is the title's Ⓐ path in, and what is at `+0xC` of the
structure it dereferences;
2. the content exports this title imports — `XamContentCreateEnumerator`,
`XamContentGetDeviceState`, `XamUserReadProfileSettings` — logged around the
press, to see whether the guest is handed a bad enumerator or a device state
it does not accept. `\aab216c3\5\…` is the content directory in question.
**What this blocks:** every dynamic experiment past the title — a second UI
screen's paint order, the main menu, mission captures. Everything up to and
including the title screen is unaffected, which is why the paint-order result
above could still be measured.