Tried to close out issue #1 with an actual draw-log measurement this iteration: built f1_hold_capture.py to boot to the settled main menu via the proven glyph-gated route, arm the F10 UI-draw capture, hold a direction, and read cursor position per frame -- the instrument f1-menu-repeat-harness- built-not-answered.md already validated but never got to run against a reachable menu. Four bugs found across four boot attempts: 1. tap() shelled out to pad.py without this script's own env, so the press went to /tmp/xenia_pad.txt while Canary watched OUT/pad.txt -- an unobserved press indistinguishable from a dead pad. Fixed with an in-process tap() using the same pad() the hold uses; confirmed working the next run (title 154.5s, menu 163.0s). 2. ui_draw_capture_frames/max were persisted at 3/20000 from a prior session in xenia-canary.config.toml -- log_ui_draws is now a documented no-op (F10 arms unconditionally) and these two cvars didn't visibly respond to command-line overrides. Bumped to 600/400000 directly in the config. 3. The real blocker: this container has no signed-in profile (no content/ directory at all -- a fresh container after a restart, which every container is right after one). Without a profile the title's sign-in dialog sets IsUIActive() true, which reproduces structures/title-a-press-fault.md's already-diagnosed unbounded- keystroke-queue crash -- verified byte-for-byte against that page's own addresses (PC 0x868 past sub_82457038, 0x828F3xxx registers, identical host/guest address arithmetic), looping continuously from before F10 was ever pressed. Fixed by creating a profile (--create_profile_if_none) and signing in (--logged_profile_slot_0_xuid), matching boot_menu.sh, which already did this and so never hit it. Confirmed: zero crashes with the fix, dozens per run without it. 4. Found but not re-verified: no xsetroot blank before launch, so a stale X-root frame from a killed prior run gave a false "TITLE" read at 2.6s, before any real window existed -- skip_intro.sh already blanks the root for exactly this reason. Fixed in the script. Ran out of budget before a clean end-to-end run landed. Still no number for issue #1 -- the Port keeps -1.0. Flagged prominently (HANDOFF, REFUTED.md) because bug 3 will hit any bare run-canary invocation in any fresh container, not just this script.
108 lines
6.0 KiB
Markdown
108 lines
6.0 KiB
Markdown
# F1 dynamic attempt — harness debugged through four bugs, no measurement yet
|
|
|
|
**Status:** ❔ not answered. Built
|
|
[`tools/re-capture/f1_hold_capture.py`](../../tools/re-capture/f1_hold_capture.py)
|
|
to close out issue #1 with an actual draw-log measurement — boot to the
|
|
settled main menu (the proven glyph-gated route), arm the F10 UI-draw
|
|
capture, hold a direction, read the cursor's position per frame. Never
|
|
completed a clean end-to-end run this iteration; four real bugs found along
|
|
the way, three fixed and confirmed, one fixed but not re-verified. Same shape
|
|
as [`f1-menu-repeat-harness-built-not-answered.md`](f1-menu-repeat-harness-built-not-answered.md) —
|
|
the harness is closer, the number still isn't here.
|
|
|
|
⚠️ **Container reset warning, read this if you are a fresh session:** bug 3
|
|
below will hit *any* scripted `run-canary` invocation in a container that has
|
|
never signed in a profile — which is every container right after a restart,
|
|
per this project's own "your session is new each time" note. `boot_menu.sh`
|
|
already handles it; a bare `run-canary` call does not.
|
|
|
|
## Bug 1 — `tap()` shelled out to `pad.py` with the wrong environment
|
|
|
|
First attempt's "tap A" used `subprocess.run([sys.executable, PAD, ...])`
|
|
without passing this script's own `env` dict, so the subprocess inherited
|
|
`os.environ` instead — where `XENIA_PAD_FILE` was never set at the OS level,
|
|
only in the local dict. `pad.py` wrote its default `/tmp/xenia_pad.txt`;
|
|
Canary was watching `OUT/pad.txt`. The press never arrived: **an
|
|
unobserved press that looks identical to a dead pad**, and it cost one full
|
|
520 s boot before the mismatch was found (only one `[file-pad]` log line the
|
|
whole run — the initial clear).
|
|
|
|
**Fixed:** an in-process `tap()` using the same `pad()` function the hold
|
|
uses, no subprocess. **Confirmed working** the very next run: title reached
|
|
at 154.5 s, tap delivered, menu reached at 163.0 s.
|
|
|
|
## Bug 2 — the persisted `ui_draw_capture_frames` was 3, disc-wide default
|
|
|
|
`ui_draw_capture_frames = 3` / `ui_draw_capture_max = 20000` sat in
|
|
`~/.local/share/Xenia/xenia-canary.config.toml` from a previous session — an
|
|
old capture's window, kept because `--log_ui_draws=true` (the flag most
|
|
existing scripts pass) is **now a documented no-op** (`command_processor.cc`:
|
|
*"OBSOLETE — the UI draw-order capture is armed by F10 unconditionally now"*).
|
|
Passing `--ui_draw_capture_frames=3000` on the command line did not visibly
|
|
change the value logged at startup, and this container's saved config wins
|
|
for these two cvars regardless of the flag.
|
|
|
|
**Fixed:** edited the toml directly, `600` / `400000` — wide enough to cover
|
|
a multi-second hold at any plausible present rate. Confirmed applied (log
|
|
dump shows the new values) on the next run, though it wasn't the run that
|
|
also isolated bug 3, so it hasn't independently produced a capture yet.
|
|
|
|
## Bug 3 — no signed-in profile, and it reproduces the documented crash
|
|
|
|
The real blocker. This container had **no `content/` directory at all** —
|
|
a fresh container after a restart, exactly as the loop brief warns, and
|
|
`f1_hold_capture.py` (unlike `boot_menu.sh`) never checked. Without a
|
|
profile, the title shows a sign-in dialog, `IsUIActive()` goes true, and —
|
|
**this is the exact crash `structures/title-a-press-fault.md` already
|
|
diagnosed** — `XamInputGetKeystrokeEx` returns success with an empty
|
|
keystroke forever, the game's unbounded pump queues every empty result, and
|
|
it eventually crashes on a bad allocation.
|
|
|
|
Reproduced, not just matched by description: the crash dump's PC
|
|
(`0x824578A0`) sits **0x868 past `sub_82457038`** (that doc's "keystroke
|
|
pump"), registers hold values in the `0x828F3xxx` range (the input-manager
|
|
singleton at `0x828F3888`), and the access violation address relationship —
|
|
`0x1701D0000` (host) → `0x701D0000` (guest, `r9`) — matches that doc's own
|
|
worked arithmetic exactly. Without a profile the crash repeated in a tight
|
|
loop (one dump roughly every 200 log lines) for the entire run, starting
|
|
before F10 was ever pressed — this is not an F10 side effect, it is the
|
|
title's own boot path with no profile to sign into.
|
|
|
|
**Fixed:** `run-canary --create_profile_if_none=F1Probe`, wait ~5 s, kill it
|
|
— creates `content/<XUID>/`. Script now resolves that XUID and passes
|
|
`--logged_profile_slot_0_xuid=<XUID>`, matching `boot_menu.sh`. **Confirmed**:
|
|
zero crash dumps in the run that used it, against dozens per run before.
|
|
|
|
## Bug 4 — no root-window blank before launch; found, not re-verified
|
|
|
|
The run after fixing bug 3 detected "TITLE" at **2.6 s** — long before any
|
|
real window could exist — and never recovered. `skip_intro.sh`'s own header
|
|
explains why: *"The X root keeps the DEAD session's last frame, so a fresh
|
|
launch would be detected as already at the title."* The previous run's
|
|
killed window left stale pixels on the shared `:98` display; my script never
|
|
blanked it, unlike every proven boot script.
|
|
|
|
**Fixed in the script** (`xsetroot -solid black` before each launch) but
|
|
**not re-run this iteration** — four bugs and roughly nine minutes of boot
|
|
time across four attempts is where this stopped rather than chasing a fifth.
|
|
|
|
## What's left
|
|
|
|
The harness should now be correct: env-safe input, a wide enough capture
|
|
window, a signed-in profile, a blanked root. The next run is the actual
|
|
measurement — hold a direction on the settled menu, read `read_draws.py`'s
|
|
per-frame quad positions, group by `(page, width, height)` shape (the
|
|
approach `menu_repeat_probe.sh`'s own notes call "track one quad shape's
|
|
position over time," the one that correctly reports no motion when there is
|
|
none), and report which shape-group's position changes, at what frame
|
|
spacing, at the achieved present rate.
|
|
|
|
## Reach
|
|
|
|
Everything here is ⟨harness⟩ / ⟨environment⟩ — about this container and this
|
|
tool, not about the game. Bug 3's crash mechanism is not new (already fully
|
|
diagnosed in `structures/title-a-press-fault.md`); what's new is the trigger
|
|
(a freshly-reset container with no profile) and that it reproduces
|
|
byte-for-byte against that page's own addresses. No claim about F1's actual
|
|
repeat rate is made or changed here.
|