Last iteration I blamed four failed runs on the probe sampling every ~41 s, slower than the title screen lasts, and withdrew three earlier conclusions on that basis. Building the fix tested the claim and killed it. The speedup is real and control-verified. One long-lived ffmpeg x11grab stream, raw RGB, glyph counted in numpy -- no per-sample process startup, no PNG encode, no convert -crop: wrapper `screenshot` 3.98 s per sample (emulator running) import -window root -> PPM 1.20 s long-lived x11grab stream 0.29 s 13.7x The counter is byte-identical to is_title.py: 753 on the committed title capture, 327 on the main menu. Pointed at a running game it says the opposite of what I expected: 332 frames in 85.3 s = 3.89 fps; max glyph 0 1674 frames in 420.0 s = 3.99 fps; max glyph 0 1674 consecutive samples over seven unbroken minutes, four per second, zero green-(A) pixels. Sampling rate was a real defect that happened not to be the cause. So "neither locale reaches the interactive title without a pad press" -- withdrawn last iteration for want of evidence -- is reinstated, now as a dense measurement, with its reach stated: a MID-RUN window only, silent about the boot title. Leading hypothesis, unconfirmed: the PRESS (A) plate appears only in the boot title window and the attract loop's title carries none, which is exactly what title_states_capture.sh was written to test. The experiment is to start the fast probe from t=0 rather than attach to a run already in progress. METHOD: fixing the instrument is how you test the explanation that blamed it -- a plausible mechanism is a hypothesis, and the fix is its experiment, not its proof.
5.3 KiB
🔴 Why the boot harness stopped reaching the title — screenshot costs 10.8 s
Status: ✅ diagnosed, with a control. Four consecutive runs on 2026-08-28/29 failed to reach the interactive title, across two locales, two launch paths and two display-gamma settings. The cause is none of those.
The measurement
| condition | one screenshot call |
|---|---|
| while Xenia Canary is running | 10.8 s |
| immediately after killing it | 0.117 s |
92×. The 1-minute load average at the slow measurement was 1.80, so this is contention with the emulator (both go through the same X server), not general system load.
Why that breaks the harness
skip_intro.sh takes two grabs 0.6 s apart per iteration, plus an
is_title.py numpy load. Its actual sample timestamps in the last run:
57, 95, 177, 218, 238, 298, 333, 380, 426, 471, 515 → intervals
38, 82, 41, 20, 30, 30, 35, 47, 46, 45, 44, 43, 21, 19 median 41 s
A 41-second sampling interval against a title screen that the corpus already
documents as lasting "a few seconds" before auto-returning to the attract loop
(wait_title.sh's own header). The harness is not seeing a stuck game; it is
blinking slower than the thing it is looking for.
That is also why runs at 16:43–18:05 the same day succeeded and later ones did not — nothing about the game changed.
🔴 What this retracts
Three earlier conclusions were built on these runs and are withdrawn as causes, though the observations stand:
- "the Japanese-locale run never reaches the interactive title" — it may well have appeared, unsampled.
- "neither locale reaches the interactive title without a pad press" — the English control shared the same defect, so it controlled for locale but not for the sampling rate.
- "the game sat in the attract loop for 604 s" — what was observed is that every one of ~15 samples landed on movie content, which at a 41 s interval is a much weaker statement than it reads as.
⚠️ A confound I introduced
Setting kernel_display_gamma_type = 0 makes the frame substantially brighter
(a mid-attract frame measured mean 122.8 against 52.5 and 82.8 on
comparable phases at type 2). skip_intro.sh classifies movie-vs-static on an
absolute rmse threshold of 1500 between two grabs, so a brighter output
inflates that difference and biases every frame toward "movie". The capture
harness's tuning is coupled to the display settings — changing gamma and
capture behaviour in one run confounds both.
🔴 The fix works — and it REFUTES the diagnosis above
Built and measured (tools/re-capture/fast_title_probe.py): one long-lived
ffmpeg x11grab stream, raw RGB frames, glyph counted in numpy. No per-sample
process startup, no PNG encode, no convert -crop.
| probe | seconds per sample, emulator running |
|---|---|
the wrapper screenshot |
3.98 |
import -window root → PPM |
1.20 |
| long-lived x11grab stream | 0.29 |
13.7× faster, and the counter is control-verified against the committed
frames — it returns 753 on live-title-press-a.png and 327 on
live-main-menu.png, byte-identical to is_title.py.
Then it was pointed at a running game:
332 frames in 85.3 s = 3.89 fps; max glyph 0
1674 frames in 420.0 s = 3.99 fps; max glyph 0
1 674 consecutive samples over seven unbroken minutes, four per second, and the interactive title never appeared. So the sampling rate was a real defect and not the cause. The hypothesis on this page — that the harness was blinking slower than the event — is mine, and refuted by my own fix.
What that restores
Last iteration I withdrew three conclusions on the strength of that hypothesis. The withdrawal was right at the time (15 samples at 41 s intervals cannot support them) and is now superseded by better evidence: dense sampling says the interactive title genuinely does not appear in a mid-run window. Reinstated as a measurement, with its reach:
- ✅ over 420 continuous seconds, English,
gamma_type = 2, ~13 minutes into a run with no pad input, zero frames carried the green Ⓐ glyph. - ⚠️ Reach: this covers a mid-run window only. It says nothing about the first minutes of boot.
🟡 The leading hypothesis, not confirmed
The corpus already suspects the answer. title_states_capture.sh exists to test
"whether the interactive one draws ptbtn00 (the PRESS Ⓐ plate) and the other
does not" — i.e. the title appears twice: once at the end of the boot
sequence, and again from the attract loop, and only the first may carry the
plate. If so, the plate's window is early and one-shot, and no amount of
mid-run sampling will ever find it.
That is consistent with everything measured, and it is not confirmed. The test is to start the fast probe before the boot title — from t=0 rather than attaching to a run already in progress.
The original fix note, kept
Make the probe cheap enough to sample faster than the title window: grab a small
region rather than the full surface, drop the ImageMagick convert round trip,
or keep the glyph test in one long-lived process instead of re-importing numpy
per sample. None of that is done — this page is the diagnosis, and it is what
every remaining emulator-side question is waiting on.