Files
Sylpheed/docs/re/structures/tbm-submenu-not-reached.md
sylph-decoder ddc2a8e36b re: a .tbm DRAWS -- the TUTORIAL screen captured, and the 'inert' reading refuted
Closes the open second reading in ui-forced-backdrop.md: that a .tbm contributes
no pixels, leaving 24 of its 62 deciding verdicts harmless rather than correct.

The TUTORIAL screen was reached and captured. It carries a full-screen blue
circuit/hex background. GP_TUTORIAL build 0's element 0 is pubase.tbm with pivot
(640,360) -- 1280x720, the only full-screen TEXTURED element in the bundle; the
one other full-screen element is pueff00.prm, an untextured primitive the colour
census puts at pure black. Our render of the same build is the identical layout
on pure black, 6.0-6.4 % inked against the game's 99.7 %. The only difference is
the background and the only thing it can be is the .tbm.

So the 24 .tbm verdicts are correct rather than harmless, and they are
load-bearing in the full sense. Reach: one .tbm observed; the class question is
settled, the ten other families are not individually seen.

Also: screen render is wrong on every screen carrying a .tbm -- it drops the
background silently, with no diagnostic.

And the identification is worth its own METHOD entry. Two statistical identifiers
were built. Masked correlation FAILED its control, picking EXTRAS over the known
main menu by 0.004 because the shared background dominates. A high-passed variant
PASSED by 1.28x, which is not a margin that licenses identifying an unknown, so it
was not used. The screen says TUTORIAL across the top. Ask whether the artefact
already states the answer before building a matcher.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 10:53:34 +00:00

145 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ✅ A `.tbm` DRAWS PIXELS — the `TUTORIAL` screen, captured and identified
**Classification: not an answer.** Recorded per *"do not improvise around a
blocker"*, and because the *reason* both runs failed is the same mistake three
times over.
## The question
[`ui-forced-backdrop.md`](ui-forced-backdrop.md) has **24** of its 62 deciding
verdicts on `.tbm` elements. `compose` draws **nothing** for a `.tbm` — no
resolvable sprite — so those verdicts are *"correct or inert"* and the two cannot
be separated. A capture of a screen carrying one would separate them.
**And no focus detector is needed**, which is what makes this cheap now.
[`s00a-drive-blocked-by-focus.md`](../s00a-drive-blocked-by-focus.md) records that a
per-row brightness statistic **failed its own control**, and that wrap-around makes
counting presses useless. But *every* main-menu destination except `EXTRAS` lands on
an archive holding a `.tbm` decider — `GP_SYSTEM` (`pqbase`), `GP_TUTORIAL`
(`pubase`), `GP_SAVE_LOAD` (`px_replay_base`), `GP_DIALOG` (`pcbase`). So press Ⓐ on
whatever is focused and identify the screen **from the capture**.
## What happened
| run | approach | result |
|---|---|---|
| 1 | **timed** the title→menu transition (tap, wait 8 s) | 8 s later still the **title** — glyph 714, the plate's pulse trough. The second tap did the transition; the "submenu" capture is the menu. **Void.** |
| 2 | **detected** the menu (glyph 250420 for 6 samples; menu is 327, plate is 7141520) | menu found at 357.2 s, glyph **327** exactly. Tapped at 358.0 s. 12 s later: **still the menu.** |
## 🔴 The second tap was never delivered
| | |
|---|---|
| `[file-pad] vk=5800` lines | **2** — that is *one* press, down and up |
| `[RE-INPUT] -> user=0 vk=5800` | one down, one up |
| `swallowed by IsUIActive` | **0** — not the sign-in path |
The tap came **0.8 s after the menu appeared**, while the guest was still loading
it. A **0.12 s** press is missed outright if the guest does not poll during that
window. The pad driver reports what *it* emitted; the guest never asked.
⚠️ **So "the press did nothing" and "there was no press" look identical from the
screen**, and only the log separates them. Any driven run that presses and waits
must **confirm delivery in the log** before interpreting the result — otherwise a
missed press reads as a screen that did not respond.
## The pattern worth more than the run
This is the **third** time in one iteration that timing was used where detection was
required — the title→menu wait, the menu→submenu wait, and the press itself
(assumed delivered rather than confirmed). The first two were caught because the
screen was recognisable; the third only because the log records deliveries.
📌 Each fix has the same shape: **replace "wait long enough" with "watch for the
thing".** The title detector, the menu detector and the delivery check are all that
substitution, and each was written only after the timed version had already produced
a confident wrong answer.
## ✅ Run 3 — all three fixes applied, all three needed, submenu reached
```
[ 288.6s] TITLE (glyph 1520)
[ 289.7s] A delivered (attempt 1) ← confirmed from [RE-INPUT], not from the pad
[ 295.4s] MENU (glyph 327) ← detected, not timed
[ 299.3s] A delivered (attempt 1)
[ 303.4s] SUBMENU: 87.1 % of pixels differ from the menu, glyph 314
```
**The capture is 99.7 % inked**, uniformly top to bottom — a full-screen background
([capture](../captures/title-builds/live-submenu-unidentified.png),
[numbers](../data/tbm-submenu-reached.txt)).
**Our renderer, on the archives carrying a `.tbm` decider:**
| archive | builds | inked |
|---|---|---|
| `GP_SAVE_LOAD` | 19 | **1.9 3.0 %** |
| `GP_TUTORIAL` | 3 | **6.0 6.4 %** |
| `GP_SYSTEM` | 0, 1 | 78.4 % |
So two of the three render essentially nothing where the game draws a full screen.
## ✅ It is `TUTORIAL`, and the screen names itself
**Read off the framebuffer** — the same method Q4 used to measure all five menu
buttons. The capture says `TUTORIAL`, lists `BASIC CONTROLS … BACK`, and carries a
**full-screen blue circuit/hex background**.
`GP_TUTORIAL` build 0's element 0 is **`pubase.tbm`, pivot (640, 360)** — 1280×720,
the only full-screen *textured* element in the bundle; the one other full-screen
element is `pueff00.prm`, an untextured primitive that the colour census puts at
**pure black**. Our render of the same build is the **identical layout on pure
black** — 6.06.4 % inked against the game's 99.7 %.
**So a `.tbm` draws, and the "inert" reading in
[`ui-forced-backdrop.md`](ui-forced-backdrop.md) is refuted.** Its 24 `.tbm`
deciders are correct rather than harmless. ⚠️ One `.tbm` observed; the class question
is settled, the ten other families are not individually seen.
🔴 **And `screen render` is wrong on every screen carrying a `.tbm`** — it drops the
background silently.
## 🔴 The instrument I built for this failed, and reading the screen was better
**Correlation cannot discriminate when the candidate renders are near-blank.**
**Correlation cannot discriminate when the candidate renders are near-blank.** An
almost-empty image has no structure to correlate against, so all 19 `GP_SAVE_LOAD`
builds score **0.004 … 0.010** — a ranking with no information in it. ⚠️ **A
matching statistic is useless against a hypothesis that predicts an empty image**,
and that is precisely the hypothesis under test. The instrument is disabled by the
thing it was brought in to detect.
🔴 **Two repair attempts, and the honest outcome.** Masking the correlation to the
pixels the render *does* ink **failed its control**: asked to identify the known main
menu, it picked `EXTRAS` over the menu by **+0.0040** — the shared background
dominates. High-passing first **passed** the control but by **1.28×**
(+0.0276 against +0.0215), where the port's method on the same class of problem
separated by 4.7×. **A control that passes by 1.28× is not a licence to identify an
unknown**, so it was not used. Looking at the picture settled in one step what two
statistics could not.
🔴 **And the focus could not be read either.** Against the two labelled menu
captures the whole-frame mean absolute difference is **2.52** (NEW GAME) and
**2.48** (OPTIONS) — 1.6 % apart, far too weak to call.
[`s00a-drive-blocked-by-focus.md`](../s00a-drive-blocked-by-focus.md) already
records a per-row brightness statistic failing its control; this is a **second**
statistic failing on the same problem, which makes focus identification a real
open item rather than an oversight.
**One thing worth keeping regardless:** the game surface sits at **y = 45** in the
1280×720 display frame — `m[45:45+675, 0:1279]` fits the committed 1279×675 captures
to a mean absolute difference of **2.5**. That is the alignment the earlier
cross-geometry floor comparison got wrong.
## What is now validated, and what the next run needs
✅ Working: the plate-pulse title detector (three runs); the **menu detector**, glyph
**327**, matching `live-main-menu.png` exactly; and delivery confirmation from
`[RE-INPUT]`.
**Next run:** hold Ⓐ longer than 0.12 s, **confirm the `[RE-INPUT]` line appears**,
retry if it does not, then detect the submenu **by change** rather than by timer —
a submenu load may also pass through a `pgloading_*` screen, so "different from the
menu" is the signal, not a fixed wait.