re: the title's build-in measured in the guest's draw stream -- the flashes are real
The settle-time decode was confirmed only against a SETTLED frame, which shows the end state is right and says nothing about whether the five flashes ever happen. This runs the oracle: a draw capture armed before the title exists, so the window contains the frames in which the screen is built. The flashes fire in a six-frame window and are absent from all 155 other sampled frames. `ptlogo_back2eff1` is drawn in exactly two frames at t = 54.0 against a decoded peak of t54-56; `ptlogo1` first appears at t = 42.2 against a decoded t42. Units-per-frame was taken from the GLOW's period alone, a different element, so the timings are not circular. The two holders are continuous from frame 134. The plate glow's quad carries a per-vertex colour whose alpha IS the element's fade alpha, so the ramp is read straight out of the guest: observed range 0..80 against a decoded peak of 80, exact and unfitted; period 51.158 presented frames over 20 cycle starts. Fitting the decoded ramp gives RMS 13.16 alpha levels against 38.18 for the same ramp REVERSED -- if the shape carried no information those would be equal, so the asymmetry is real and correctly directed. Further controls: symmetric triangle 15.73, flat 31.13. `ptlogo_back2eff3` was never drawn, and that is expected rather than a miss: a 2-unit flash peak is 0.85 of a presented frame, so catching one is a matter of phase. A port drawing all five every time shows more sweep than the console. METHOD.md gains the trap this cost: a 2D draw's identity is its vertex geometry, not its bound texture. These sprites sample shared pages, and matching texture dimensions produced a false negative (no flash is ever drawn) and a false positive (the intro movie's 640x360 YUV planes read as `ptbase2`) in the same pass. Also records the top-level restriction on the settle window, which the port raised and which is verified here: top-level [160,236] width 76, including the `ptloop` leaves [269,540] width 271 -- an instant past the end of every top-level element's timeline. Evidence committed as a derived per-frame series, not the 7 MB raw log. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
This commit is contained in:
@@ -1927,3 +1927,51 @@ every 5 s.
|
||||
Detail, census and the falsification test:
|
||||
[`docs/re/structures/ui-record-loop-length.md`](../re/structures/ui-record-loop-length.md).
|
||||
|
||||
## 2026-08-29 (later still) — the settle-time mechanism confirmed in the running game
|
||||
|
||||
✅ **measured.** The settle-time finding was previously confirmed only against a
|
||||
*settled* frame, which shows the end state is right and says nothing about whether
|
||||
the five flashes ever happen. They do. From a draw capture armed before the title
|
||||
exists:
|
||||
|
||||
| element | drawn in frames | → t units | decoded |
|
||||
|---|---|---|---|
|
||||
| `ptlogo_back2eff1` | **130–131** | **54.0 – 56.3** | flash, peak **t54–56** |
|
||||
| `ptlogo_back2eff2` | 133 | 61.0 | flash, peak t58–60 |
|
||||
| `ptlogo_back2eff4` | 133–135 | 61.0 – 65.7 | flash, peak t~64 |
|
||||
| `ptlogo_back2eff` / `ptlogo_back2` | 134–260 | 63.3 – … | **hold** |
|
||||
| `ptlogo1` | **125** | **42.2** | stops moving at **t42** |
|
||||
|
||||
The flashes occupy a six-frame window and are absent from all 155 other sampled
|
||||
frames. Units-per-frame came from the **glow's period alone** — a different
|
||||
element — so the timings are not circular.
|
||||
|
||||
🔴 **One thing for you to act on: do not draw all five flashes every time.** A
|
||||
flash's peak is 2 keyframe units, which at this run's pacing is **0.85 of a
|
||||
presented frame**. `ptlogo_back2eff3` was **never drawn** — not a miss, a phase
|
||||
effect. The console shows a *subset* of these on any given play; a port that draws
|
||||
all five will show more of the sweep than the real thing.
|
||||
|
||||
✅ **And your 120 is confirmed from the guest's own vertex data.** The glow quad's
|
||||
per-vertex colour alpha *is* the element's fade alpha: observed range **0…80**
|
||||
against a decoded peak of **80**, exact and unfitted; period **51.158 presented
|
||||
frames** over 20 cycle starts; the draw is omitted entirely while dark. Fitting the
|
||||
decoded ramp gives RMS 13.16 alpha levels against **38.18 for the same ramp
|
||||
reversed**, so the asymmetry is real and pointing the right way.
|
||||
|
||||
✅ **Your top-level restriction is right and is now in the page**, verified rather
|
||||
than taken: top-level gives `[160, 236]` (width 76), including the `ptloop` leaves
|
||||
gives `[269, 540]` (width 271) — a "settled instant" *after every top-level
|
||||
element has exited*. Thank you for catching that the description permitted the
|
||||
wrong reading.
|
||||
|
||||
🔴 **A trap worth having before you write any draw-stream tooling:** a 2D draw's
|
||||
identity here is its **vertex geometry, not its bound texture**. These sprites
|
||||
sample large shared pages. Matching texture dimensions told me first that no flash
|
||||
is ever drawn, and second that `ptbase2` and `pteff04` are drawn in frames 75–105 —
|
||||
those frames are the **intro movie**, whose YUV planes are 640×360 and whose target
|
||||
is 1280×720. Both wrong, neither loud.
|
||||
|
||||
Detail, controls and reach:
|
||||
[`docs/re/structures/ui-title-buildin-measured.md`](../re/structures/ui-title-buildin-measured.md).
|
||||
|
||||
|
||||
@@ -171,3 +171,4 @@ files, which is how the same ground got covered twice.
|
||||
| [`structures/ui-tie-break-cost-at-settle.md`](structures/ui-tie-break-cost-at-settle.md) | What the unknown paint-order tie-break costs, in pixels | ✅ **decoded**, closing the open half of Q3: at the settled instant the tie-break costs **at most 1 px at Δ1**, on the **Japanese title only** (`ptlogo2`×`ptlogo_tm`, 5 px shared ink); **exactly 0 px on all five port screens**. The earlier 24-pair bound was a `rest()` count — and 10 of the title's 11 tied pairs are between `ptlogo_back2eff1`…`eff5`, five transient flashes that are **transparent** on the settled screen ([`ui-settle-time.md`](structures/ui-settle-time.md)). Live pairs at settle: entry 4 → **1**, entry 7 → **2**, the four loading bundles → **0**. ✅ Not a knife-edge — sweeping every keyframe time and midpoint, the count is **flat across the whole settle window**, and the loading bundles' tie is live only at t17–t33. ✅ Controls: an overlapping *different*-key swap moves 25 310 / 268 698 / ~765 000 px on the entries reporting zero; zeros are explained by shared-ink counts (the `ptframe` pairs share **0 px** of ink). ⚠️ Entries 0/1/12/15 have **no live control** — their zeros rest on keyframe data, not a render. 🟡 Refutation attempt on the corpus's "24 pairs": **survives** as a rest-pose bound, 16/16 on entry 7. ❔ *Why* ties order as they do is still unknown — and now worth one pixel |
|
||||
| [`structures/ui-record-loop-length.md`](structures/ui-record-loop-length.md) | Where a looping record's cycle restarts — and the `PRESS Ⓐ` plate's real period | ✅ **decoded**: a nested record is itself a RATC bundle and its header **`+0x08` is the loop length**; its keyframes need not fill it, and the slack is a hold at the final pose. Disc-wide over **1 781** timed nested records: 92.3 % declare exactly their last keyframe time, **7.7 % declare more**, and **0 declare less** — the falsifier (a cycle cannot restart before its own last pose) never fires. 🔴 **The plate's `ptbtn00f` is 105 units of ramp inside a 120-unit cycle, so it holds dark for 15 units** — the port was shipping **105**, and the answer is **120**. ✅ Falsification test against the running game, using a pacing factor measured *independently* on the focus ring (declared 120 → **2.177 s**, factor **1.0885**): to reach the corpus's measured 2.12–2.34 s, 105 units needs a factor of **1.211–1.337** (🔴 excludes the ring's) while 120 needs **1.060–1.170** (✅ contains it). Different elements, different bundles, separate runs — tied only by both declaring 120. ⚠️ Says where a cycle *ends*, not which records cycle. ❔ the **top-level** `+0x08` (300 on every `GP_TITLE` entry, elements ending at 244–269) is a different question, untouched |
|
||||
| [`structures/ui-focus-record-pulse-census.md`](structures/ui-focus-record-pulse-census.md) | Every focus record whose glow pulses, and where `rest()` puts it | ✅ **decoded**, disc-wide: **1 130** focus records, **2 664** timed elements, **210 with a varying alpha** — of which **202** have `rest()` == the **peak** (burns bright forever) and **8** land **mid-ramp**. By pak: `PILOTLOG` 116, `MOVIE_THEATER` 54, `HANGAR_ARSENAL` 30, `LEADERBOARD` 8, **`GP_TITLE` 2**. 🟡 Bounds rather than refutes the port's "34 in the export, 2 varying, nothing to fix" — correct, and correct *because* `GP_TITLE` has 2; the pathology sits in the screens a wider port needs next. 🔴 The 8 mid-ramp ones are the worse mode: `py_ranking_btn01f` swings 255→127→255 and `rest()` returns **244**, neither extreme, which looks entirely plausible and nothing reports it. ✅ Control: `ptbtn01f` is genuinely constant (255 throughout) and is **not** flagged; two hits verified keyframe by keyframe. ⚠️ A pulsing element has no resting pose — the question is malformed, not mis-answered; `pose_at(t)` inside the record's declared cycle ([`ui-record-loop-length.md`](structures/ui-record-loop-length.md)) is the only well-formed query. ⚠️ 210 is a **floor**: focus records are matched by the `Xf.rat` name rule, and varying scale/rotation/position is not counted |
|
||||
| [`structures/ui-title-buildin-measured.md`](structures/ui-title-buildin-measured.md) | The title's build-in and the plate glow, read out of the guest's own draw stream | ✅ **measured** (Canary, `ARM=early` draw capture): the decoded *mechanism* is observed, not just its end state. **The five flashes fire in a six-frame window and are absent from all 155 other sampled frames**; `ptlogo_back2eff1` is drawn in exactly 2 frames at **t = 54.0** against a decoded peak of **t54–56**, and `ptlogo1` first appears at **t = 42.2** against a decoded **t42** — with units/frame taken from the **glow's period alone**, a different element. The two holders (`ptlogo_back2eff`, `ptlogo_back2`) are continuous from frame 134. ✅ The glow's per-vertex colour alpha IS its fade alpha: **observed range 0…80 against a decoded peak of 80**, exact and unfitted; **period 51.158 presented frames** over 20 cycle starts; fitting the decoded ramp gives RMS **13.16** against **38.18 reversed** (2.9×), so the asymmetry is real and correctly directed. Structure: frame **107** is a **27-draw composite**, the settled title is 10–11 draws naming no sprite — which is why arming at the title sees nothing. ⚠️ **`eff3` was never drawn and that is expected**: a 2-unit flash peak is **0.85 of a presented frame**, so catching one is a matter of phase — 🔴 a port drawing all five every time shows more sweep than the console does. 🔴 **Trap:** matching a bound texture's dimensions to a sprite fails both ways — it missed every flash *and* read the intro movie's 640×360 YUV planes as `ptbase2`. ❔ Run's frame rate not recorded, so nothing is stated in seconds; `eff5` vs `ptlogo_back2eff` not separated |
|
||||
|
||||
@@ -1059,3 +1059,24 @@ The general trap: **an aggregate computed per-element is not a state of the
|
||||
system.** Ask what instant a composite claims to depict, and check that every
|
||||
element was asked the same question. See
|
||||
[`structures/ui-settle-time.md`](structures/ui-settle-time.md).
|
||||
|
||||
## A 2D draw's identity is its geometry, not its bound texture
|
||||
|
||||
The title's sprites **sample large shared texture pages**, so the texture bound to
|
||||
a draw identifies a page and not an element. Matching a bound texture's dimensions
|
||||
against a decoded sprite's fails silently in both directions, and one pass here
|
||||
did both at once:
|
||||
|
||||
* **false negative** — "none of the five flash sprites is ever drawn". They are
|
||||
drawn; they simply never appear as their own texture.
|
||||
* **false positive** — "`ptbase2` (640×360) and `pteff04` (1280×720) are drawn in
|
||||
frames 75–105". Those frames are the **intro movie**, whose YUV planes and
|
||||
target happen to be 640×360 and 1280×720.
|
||||
|
||||
Re-run against the **quad's vertex rect** in design space and every element
|
||||
appears where the disc says it should. Canary's own capture code already carries
|
||||
this warning in a comment, and the corpus had already recorded that the settled
|
||||
title binds only 1280×768 pages — both were there to be read first.
|
||||
|
||||
The general shape: **a coincidence of size is not an identification.** Before
|
||||
matching on one attribute, ask what else in the frame shares it.
|
||||
|
||||
3184
docs/re/data/title-glow-alpha-per-frame.csv
Normal file
3184
docs/re/data/title-glow-alpha-per-frame.csv
Normal file
File diff suppressed because it is too large
Load Diff
@@ -73,6 +73,23 @@ This is a genuine test rather than a fit: the ring and the plate are different
|
||||
elements in different bundles, measured in separate runs, and the only thing tying
|
||||
them together is that both declare a 120-unit cycle.
|
||||
|
||||
## ✅ Measured in the running game
|
||||
|
||||
The glow's quad carries a per-vertex colour whose **alpha is the element's fade
|
||||
alpha**, so the ramp can be read straight out of the guest's draw stream
|
||||
([`ui-title-buildin-measured.md`](ui-title-buildin-measured.md)):
|
||||
|
||||
* **observed alpha range 0 … 80, against a decoded peak of 80** — exact, unfitted;
|
||||
* **period 51.158 presented frames** over 20 consecutive cycle starts;
|
||||
* the draw is **omitted entirely** while the glow is dark, which is the 11↔10
|
||||
draw alternation visible in the settled title;
|
||||
* fitting the decoded ramp gives RMS 13.16 alpha levels against **38.18 for the
|
||||
same ramp reversed** — the asymmetry is real and in the decoded direction.
|
||||
|
||||
This does not re-measure the period in seconds (the run's frame rate was not
|
||||
recorded), so the falsification below stands on the corpus's wall-clock timings
|
||||
rather than on this run.
|
||||
|
||||
## What this replaces
|
||||
|
||||
* 🔴 **105 is wrong** and the port should stop shipping it. The number is **120**,
|
||||
|
||||
@@ -26,6 +26,21 @@ vocabulary the file has.
|
||||
`UiBuild::settle_window()` returns the interval, whose width is how much
|
||||
confidence the midpoint deserves.
|
||||
|
||||
🔴 **Gather the times from the TOP-LEVEL elements only — not from nested leaf
|
||||
records.** The port raised this after reproducing `[160, 236]` from its own
|
||||
export, and it is worth stating because the implementation reads correctly either
|
||||
way while only one is right. Including `GP_TITLE` build 4's `ptloop` leaves, whose
|
||||
cycles run to 600 and 720, gives **`[269, 540]`** instead — a "settled instant"
|
||||
that lies *past the end of every top-level element's timeline*, i.e. after the
|
||||
screen has exited. Verified here: top-level `[160, 236]` width 76, with leaves
|
||||
`[269, 540]` width 271. A leaf loops on its own clock and says nothing about when
|
||||
the screen stops changing.
|
||||
|
||||
✅ **Confirmed against the running game.** The mechanism this page decodes — five
|
||||
transient flashes that fire and vanish — is observed in the guest's own draw
|
||||
stream, with `ptlogo_back2eff1` drawn in exactly two frames at t = 54.0 against a
|
||||
decoded peak of t54–56: [`ui-title-buildin-measured.md`](ui-title-buildin-measured.md).
|
||||
|
||||
## The case that found it
|
||||
|
||||
`GP_TITLE` build 4. Seven elements share the light-arc band behind the logo:
|
||||
|
||||
134
docs/re/structures/ui-title-buildin-measured.md
Normal file
134
docs/re/structures/ui-title-buildin-measured.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# The title's build-in, measured in the guest's own draw stream
|
||||
|
||||
**Classification: measured.** Xenia Canary, `ui_draw_capture.sh ARM=early
|
||||
FRAMES=9000`, 2026-08-29. Evidence:
|
||||
[`title-glow-alpha-per-frame.csv`](../data/title-glow-alpha-per-frame.csv) — the
|
||||
per-frame series the numbers below come from. (The 7 MB raw draw log is a scratch
|
||||
capture and is not committed.)
|
||||
|
||||
## What this tests
|
||||
|
||||
[`ui-settle-time.md`](ui-settle-time.md) decodes the title's light arc as **five
|
||||
staggered two-frame flashes** (`ptlogo_back2eff1`…`eff5`) that fire around t54–66
|
||||
and are gone by t110, with `ptlogo_back2eff` and `ptlogo_back2` holding for the
|
||||
rest of the screen. That decode was confirmed only against a **settled** frame:
|
||||
posing at the settle time matched the console, which shows the *end state* is
|
||||
right and says nothing about whether the flashes ever happen.
|
||||
|
||||
[`ui-record-loop-length.md`](ui-record-loop-length.md) decodes the `PRESS Ⓐ`
|
||||
glow as a **120-unit cycle** containing a 105-unit ramp that peaks at **alpha 80**.
|
||||
|
||||
Both are predictions about the running game. This is the run.
|
||||
|
||||
## 🔴 First, the trap that nearly produced a false negative
|
||||
|
||||
The obvious instrument — match a bound texture's dimensions to a decoded sprite's
|
||||
— **does not work, and fails silently in both directions.**
|
||||
|
||||
A first pass reported that none of the five flashes are ever drawn. It also
|
||||
reported `ptbase2` (640×360) and `pteff04` (1280×720) drawn during frames 75–105.
|
||||
Both were wrong. Those frames are the **intro movie**: four full-screen quads per
|
||||
frame sampling a pair of 640×360 planes and a 1280×720 target — a video decode
|
||||
whose plane sizes happen to collide with two sprite sizes. And the flashes were
|
||||
missing because the title's sprites **sample large shared texture pages**, so the
|
||||
bound texture identifies a page, not an element.
|
||||
|
||||
Canary's own capture code says so in a comment, and the corpus had already
|
||||
recorded that the settled title's textures are all 1280×768. **The identity of a
|
||||
2D draw here is its vertex geometry, not its texture.** Re-run against the quad
|
||||
rects, everything appears.
|
||||
|
||||
## The structure of the title in the draw stream
|
||||
|
||||
| frames | draws/frame | what |
|
||||
|---|---|---|
|
||||
| 2–105 | 3–5 | splashes, then the intro movie |
|
||||
| **107** | **27** | 🔴 the title **composited**, once |
|
||||
| 109–167 | 6 → 14 | the build-in |
|
||||
| 168–1217 | 10–11 | the settled title |
|
||||
| 1218– | 4–5 | back to the attract loop |
|
||||
|
||||
The settled screen is 10–11 draws that never name a sprite; the composite happens
|
||||
in a single 27-draw frame. **A capture armed at the title therefore sees nothing** —
|
||||
which is why `ARM=early` exists.
|
||||
|
||||
## The flashes are real, and they are transient
|
||||
|
||||
Matching quads by design-space rect over frames 100–260, and converting frames to
|
||||
keyframe units with **2.346 units/frame — derived from the glow's period alone,
|
||||
a different element**, taking the composite spike (frame 107) as t=0:
|
||||
|
||||
| element | drawn in frames | → t units | decoded |
|
||||
|---|---|---|---|
|
||||
| `ptlogo_back2eff1` | **130–131** | **54.0 – 56.3** | flash, peak **t54–56** ✅ |
|
||||
| `ptlogo_back2eff2` | **133** | **61.0** | flash, peak t58–60 |
|
||||
| `ptlogo_back2eff3` | **never** | — | flash, peak t62–64 ⚠️ |
|
||||
| `ptlogo_back2eff4` | **133–135** | 61.0 – 65.7 | flash, peak **t~64** ✅ |
|
||||
| `ptlogo_back2eff` / `eff5` | 134–260 | 63.3 – … | 255 at t64–66, **holds** ✅ |
|
||||
| `ptlogo_back2` | 134–260 | 63.3 – … | 255 at t80, **holds** ✅ |
|
||||
| `ptlogo1` | **125**–148 | **42.2** | stops moving at **t42** ✅ |
|
||||
|
||||
**The flashes fire inside a six-frame window and are absent from every one of the
|
||||
other 155 frames sampled.** The two holders are present continuously from frame
|
||||
134 onward. That is the decoded mechanism, observed.
|
||||
|
||||
⚠️ **`eff3` was never drawn, and that is expected rather than a miss.** A flash's
|
||||
peak is 2 keyframe units, and at 2.346 units per presented frame that is **0.85 of
|
||||
a frame** — sub-frame. Whether any given flash is sampled at all depends on phase.
|
||||
Four of five were caught here; a second run would likely catch a different four.
|
||||
🔴 **A port that draws all five every time will show more of this sweep than the
|
||||
console does.**
|
||||
|
||||
## The glow's ramp, read out of the guest
|
||||
|
||||
The plate glow's quad carries a **per-vertex colour whose alpha is the element's
|
||||
fade alpha**, so the ramp can be read directly rather than inferred from pixels.
|
||||
|
||||
* **Observed alpha range: 0 … 80. Decoded peak: 80.** Exact, and not fitted.
|
||||
* **Period: 51.158 presented frames**, from the first to the last of **20
|
||||
consecutive cycle starts** (individual periods 49–53).
|
||||
* The draw is **omitted entirely** while the glow is dark — which is what the
|
||||
11↔10 draw alternation in the settled title is.
|
||||
|
||||
Fitting the decoded 8-keyframe ramp to the 972 measured frames, with **one
|
||||
disclosed free parameter** (a constant phase offset):
|
||||
|
||||
| curve | RMS residual, alpha levels |
|
||||
|---|---|
|
||||
| **the decoded ramp**, phase +2.25 units (= **+0.96 frames**, sub-frame) | **13.16** |
|
||||
| the decoded ramp, no phase fit | 13.68 |
|
||||
| a symmetric triangle of the same period and peak | 15.73 |
|
||||
| flat at the mean | 31.13 |
|
||||
| 🔴 **the decoded ramp REVERSED** | **38.18** |
|
||||
|
||||
The reversal control is the one that matters: if the shape carried no
|
||||
information, forwards and backwards would fit equally. They differ by **2.9×**, so
|
||||
the measured ramp has the decoded ramp's asymmetry — fast rise, slow fall — in the
|
||||
decoded direction.
|
||||
|
||||
⚠️ The +0.96-frame phase is the expected bias, not a correction: a cycle start is
|
||||
detected at the first frame with a non-zero alpha, and the decoded curve leaves
|
||||
zero part-way through a frame.
|
||||
|
||||
## Reach and what is not settled
|
||||
|
||||
⚠️ **One run, one machine.** 2.346 units per presented frame is *this run's*
|
||||
pacing, not a property of the game. The internal ratios are what transfer.
|
||||
|
||||
❔ **The absolute frame rate of this run was not measured** — Canary logged no fps
|
||||
and the log has no timestamps — so nothing here is stated in seconds. It did not
|
||||
need to be: every comparison above is a ratio of measured quantities.
|
||||
|
||||
❔ **`ptlogo_tm` was never matched.** At 37×17 it is below the rect tolerance used;
|
||||
absence here is not evidence.
|
||||
|
||||
⚠️ **`eff5` and `ptlogo_back2eff` are the same rect at the same position and were
|
||||
not separated.** Distinguishing them needs the per-vertex alpha, which the decode
|
||||
says differs — not attempted.
|
||||
|
||||
## Reproducing
|
||||
|
||||
```bash
|
||||
FRAMES=9000 MAXDRAWS=5000000 ARM=early tools/re-capture/ui_draw_capture.sh 900 /tmp/uicap
|
||||
python3 tools/re-capture/buildin_timeline.py /tmp/uicap/xenia_re_ui_draws_01.log
|
||||
```
|
||||
Reference in New Issue
Block a user