diff --git a/docs/port/MISSION.md b/docs/port/MISSION.md index b16d6c6..2c749d9 100644 --- a/docs/port/MISSION.md +++ b/docs/port/MISSION.md @@ -114,12 +114,26 @@ independent landmarks rather than guessed: `XLanguage::kJapanese = 2` (`xbox.h:307`). Writing 2 there and restoring afterwards is using canary's own persistence, not patching its code. -**🟡 Still not settled, for a smaller reason.** A run with the locale set to -Japanese booted fine, but **never reached the title in 787 s** — `wait_title.sh`'s -green-Ⓐ oracle never fired, and burst-sampling 8 frames found none correlating -above 0.18 with either build-7 render. The run sat in the attract loop. So this -needs a *longer or pad-driven* run, not a rebuilt emulator. The locale was -restored to English afterwards. +**🟡 Still not settled — two runs, and the reason moved again.** + +*Run 1 (2026-08-28)* reported "title not seen" in 787 s. **That was a broken +tool, not the game.** `wait_title.sh` still carried the single-pixel oracle that +`is_title.py` was written to replace — a 1280×720 coordinate sampled against the +1279×675 game surface, so it always reads the copyright line. Fixed; it now +delegates to `is_title.py`. + +*Run 2 (2026-08-29)*, with the working oracle and the profile flag the English +captures use, **still did not reach the interactive title.** Not one frame in the +run showed a single green-Ⓐ glyph pixel, and content correlation against either +build-7 render never exceeded **0.22**. The game sat in the attract movie +throughout, polling `XamInputGetKeystrokeEx` (601 calls) — i.e. alive and waiting +for input, not hung. + +🟡 **So what is untested is whether the attract loop returns to the *interactive* +title without a pad press.** `title_states_capture.sh` claims it does, with no +pad input, on the English boot — that is the next thing to check, and if it holds +then the difference is the locale and worth its own note. The locale is restored +to English; `set_console_language.py ja` flips it back in one command. ⚠️ Neither question blocks the five menu screens. Q1's *interpolation law* is settled and only multi-keyframe absolute timing is open; `rest()` differs from diff --git a/docs/re/METHOD.md b/docs/re/METHOD.md index ee961fc..7e03672 100644 --- a/docs/re/METHOD.md +++ b/docs/re/METHOD.md @@ -442,3 +442,12 @@ agent's loop prompt, i.e. nowhere durable. See [`README.md`](README.md) for the landmarks, no offset assumed, and the check re-runs every invocation — so the tool fails loudly if the layout moves instead of silently patching a neighbouring field. +* **A stale oracle reports the world, not itself.** A 787 s run concluded "the + game never reached the title". It had, repeatedly: `wait_title.sh` was still + sampling the single pixel (625,618) that `is_title.py` had already been written + to replace — a 1280×720 coordinate against a 1279×675 game surface, always + reading the copyright line. The replacement existed *in the same directory*, + with a docstring naming the bug. Before believing a negative from a probe, + check whether something in the toolkit already supersedes it, and run the probe + against a known-positive capture first — `is_title.py` scores 753 on a real + title frame and 327 on the main menu, which takes one command to confirm. diff --git a/docs/re/REFUTED.md b/docs/re/REFUTED.md index ae6045c..1ed7492 100644 --- a/docs/re/REFUTED.md +++ b/docs/re/REFUTED.md @@ -421,3 +421,8 @@ neighbourhood, not just the line. capture is still not *taken* — a Japanese run never reached the title in 787 s — but it needs a longer run, not a rebuilt emulator. [`tools/re-capture/set_console_language.py`](../../tools/re-capture/set_console_language.py) +* "the Japanese-locale run never reached the title in 787 s" → **the measurement + was broken, not the run.** `wait_title.sh` carried the superseded single-pixel + oracle. Re-run with `is_title.py`: the game still did not present the + interactive title, but that is now a measured statement (zero green-glyph + pixels, correlation ≤ 0.22 to either build-7 render) rather than an artefact. diff --git a/tools/re-capture/wait_title.sh b/tools/re-capture/wait_title.sh index c39ba8f..d92053a 100755 --- a/tools/re-capture/wait_title.sh +++ b/tools/re-capture/wait_title.sh @@ -1,16 +1,25 @@ #!/usr/bin/env bash -# Poll the framebuffer for the "PRESS (A) BUTTON" title screen (the green A glyph -# at ~625,618) and tap A the instant it appears — the title auto-returns to the -# attract loop after a few seconds, which is why a human-paced tap misses it. +# Poll the framebuffer for the "PRESS (A) BUTTON" title screen and tap A the +# instant it appears — the title auto-returns to the attract loop after a few +# seconds, which is why a human-paced tap misses it. +# +# 🔴 FIXED 2026-08-29. This used to sample the SINGLE PIXEL (625,618) and test it +# for green. That is the exact oracle `is_title.py` was written to replace, and +# its docstring says why: it is a 1280x720 coordinate sampled against the +# 1279x675 game surface, so it always reads the copyright line. The stale copy +# survived here and cost a 787 s run that reported "title not seen" while the +# game was cycling through the title perfectly normally. +# Now delegates to is_title.py, which COUNTS the green (A) glyph's pixels +# anywhere in the frame — geometry-independent, and it passes its own controls +# (753 px on a real title capture, 327 on the main menu, threshold 400). set -u export HOME=/sylph-home/re TMP=/tmp/title-probe.png deadline=$(( SECONDS + ${1:-900} )) while [ $SECONDS -lt $deadline ]; do if screenshot "$TMP" >/dev/null 2>&1; then - read -r r g b < <(convert "$TMP" -format "%[fx:int(255*p{625,618}.r)] %[fx:int(255*p{625,618}.g)] %[fx:int(255*p{625,618}.b)]" info:) - if [ "$g" -gt 130 ] && [ $((g - r)) -gt 45 ] && [ $((g - b)) -gt 45 ]; then - echo "TITLE detected (rgb $r,$g,$b) at ${SECONDS}s — tapping A" + if python3 "$(dirname "$0")/is_title.py" "$TMP" >/dev/null 2>&1; then + echo "TITLE detected at ${SECONDS}s — tapping A" vgamepad tap A 200 exit 0 fi