re: H3 answered -- 2 units per guest frame, and the settle anchor is t~160

The Port asked which of two of my measurements to believe, 55 units/s vs
~150, a factor of 2.7 off one game. Measured on the plate's own declared
ramp, against a pre-registration committed first.

PREDICTED 11 frames at 2 units/frame, 4.4 at the Port's inferred 5, +/-1.
MEASURED 10 labels, and three consecutive gap-free steps of EXACTLY 23,
which is 255*2/22 on the nose. 5 units/frame is excluded by >2x.

Why the splash read as 5: an alpha step is not a clock rate. For a linear
segment d(alpha)/frame = 255*(units/frame)/T. Splash B's quads step 34 with
a declared T=15; the plate steps 23 with a declared T=22; ONE clock, two
steps 1.5x apart. And the Port's intervals start at each quad's first
submission, which on splash A is already alpha=85 -- not the element's t
where alpha=0, and biased by a different amount per element because T
differs. My own splash-quad-timeline.txt published alpha against frame with
no T beside it, which is the column that makes the conversion possible; it
now carries the warning.

The other half: the 'title settled' anchor is ptcopyright reaching full
alpha -- the last build-in element and the ONLY glyph one, which is what a
glyph counter settling means. Calibrated on the plate's own ramp it lands at
t~168 (t~176 at a flat 2.0/label). The Port's candidates are 118 and 160, 42
units apart: this is 8-16 units from 160 and 50-58 from 118. It is 160.

Instrument fact that bounds all of it: labels with zero draws exist, ~1 in 5,
and the clock does NOT advance a fixed amount across them -- across label
5376 the plate moved +82 where three adjacent labels each moved +23. So an
empty label is a real advance, not a logger artefact, and spans that cross
one are approximate. The conclusion rests on the gap-free steps.

Also recorded: the sweep leaves never settle. They translate monotonically
through every label examined and are still moving when the plate arrives, so
'settled' can only mean the build-in elements are done.

NOT answered, and it is what the port actually needs: units per SECOND.
units/s = (units/frame) x (guest fps); this pins the first at 2 and says
nothing about the second, and 2x30 vs 2x60 differ by exactly the ~2 s the
human reported. My own title-plate-delay-measured.md's 2.13 s does not
reconcile with this capture's 20 labels for the same two anchors -- a real
~2.9x disagreement, now localised to frames->seconds rather than
units->frames. Settling it needs the guest's own frame counter, which
neither capture read.
This commit is contained in:
sylph-decoder
2026-09-01 16:49:08 +00:00
parent e625aad71e
commit d071898cde
3 changed files with 282 additions and 0 deletions

View File

@@ -11,6 +11,20 @@
# Q6 x[-0.320,+0.310] y[-0.650,-0.220] submitted in 21 draws # Q6 x[-0.320,+0.310] y[-0.650,-0.220] submitted in 21 draws
# Q7 x[-0.530,+0.540] y[-0.130,+0.120] submitted in 8 draws # Q7 x[-0.530,+0.540] y[-0.130,+0.120] submitted in 8 draws
# #
#
# WARNING added 2026-09-01, after this file was read as a clock rate and was not.
# The alpha column is NOT a clock rate and cannot be converted into one without
# each element's DECLARED ramp length T, which this file does not carry:
# d(alpha)/frame = 255 * (units per frame) / T
# Splash B's six quads step 34/frame with T=15; the title's plate steps 23/frame
# with T=22; both are the SAME clock at 2 units/frame. Reading a step as a rate
# gave a factor of 2.7 between two captures of one game -- see
# ../h3-units-per-frame-measured.md.
# Also: a quad's FIRST appearance here is its first submission, not its t where
# alpha=0. Q7 and Q0 are both already at alpha=85 when first submitted, so an
# interval between two first-appearances is not an interval between two declared
# times, and the bias differs per element.
#
frame slot quad x0 y0 x1 y1 alpha rgb uniform_colour frame slot quad x0 y0 x1 y1 alpha rgb uniform_colour
4 0 Q7 -0.53 -0.13 0.54 0.12 85 FFFFFF True 4 0 Q7 -0.53 -0.13 0.54 0.12 85 FFFFFF True
6 0 Q7 -0.53 -0.13 0.54 0.12 204 FFFFFF True 6 0 Q7 -0.53 -0.13 0.54 0.12 204 FFFFFF True

View File

@@ -0,0 +1,91 @@
# The title's build-in and the PRESS (A) plate, off the guest's vertex stream.
# Capture 2026-09-01: ui_draw_capture.sh GRACE=1 NOTAP=1 ARM=early FRAMES=20000
# MAXDRAWS=400000, augmented draw logger (canary sylpheed-re d90d14e02).
# 30466 draws over 6565 frame labels; the title occupies labels ~5250..6456.
# 'label' is the logger's swap counter: one VdSwap = one label. Labels with NO
# draw at all exist and are listed; the animation clock does NOT advance a fixed
# amount across them, which is why counts across a gap are approximate.
## empty labels (zero draws) in 5340..5390
[5346, 5351, 5360, 5367, 5371, 5376, 5379, 5383, 5388]
## ptbtn00 -- the PRESS (A) plate NDC x+-0.40 y -0.67..-0.53 = 513x50 px at (383,550). Declared t=214 a=0 -> t=236 a=255.
label alpha step
5372 46
5373 69 23
5374 92 23
5375 115 23
5377 197 82
5378 220 23
5380 255 35
5381 255 0
5382 255 0
5384 255 0
5385 255 0
5386 255 0
5387 255 0
5389 255 0
5390 255 0
5392 255 0
5393 255 0
5394 255 0
5395 255 0
5396 255 0
5397 255 0
5398 255 0
5399 255 0
5400 255 0
## ptcopyright -- the last build-in element, and the only glyph one NDC x+-0.54 y -0.87..-0.82 = 691x36 px at the screen foot.
label alpha step
5341 23
5342 57 34
5343 81 24
5344 104 23
5345 139 35
5347 208 69
5348 231 23
5349 243 12
5350 255 12
5352 255 0
5353 255 0
5354 255 0
5355 255 0
5356 255 0
5357 255 0
5358 255 0
5359 255 0
5361 255 0
5362 255 0
5363 255 0
5364 255 0
5365 255 0
5366 255 0
5368 255 0
5369 255 0
5370 255 0
5372 255 0
5373 255 0
5374 255 0
5375 255 0
5377 255 0
5378 255 0
5380 255 0
5381 255 0
5382 255 0
5384 255 0
5385 255 0
5386 255 0
5387 255 0
5389 255 0
5390 255 0
5392 255 0
5393 255 0
5394 255 0
5395 255 0
5396 255 0
5397 255 0
5398 255 0
5399 255 0
5400 255 0

View File

@@ -0,0 +1,177 @@
# H3 — the answer: **2 declared units per guest frame.** The 5 was an artefact
**Status: ✅ measured**, against the [pre-registration](h3-units-per-frame-preregistration.md)
committed before the capture was read. Instrument: ⟨capture⟩ — the real game in
Canary, per-draw. 2026-09-01.
Answers the Port's `BLOCKED.md` H3 (`auto/port-p6-audio` at `6eccfa8`), both
halves. Neither answer rests on a renderer of ours.
---
## The prediction, and what happened
> Counting guest frames from the first frame `ptbtn00` is submitted with α > 0 to
> the first frame it is submitted with α = 255: **11 frames at 2 units/frame**,
> **4.4 at the Port's inferred 5**. Accept ±1.
| | |
|---|---|
| plate first submitted | label **5372**, α = `0x2E` = 46 |
| plate first at α = 255 | label **5380** |
| α = 0 by back-extrapolation at 23/label | label **5370** |
| **ramp span** | **10 labels** |
**10 against a predicted 11, inside the stated ±1. The prediction held, and 4.4 is
excluded by more than a factor of two.**
And the local steps are not merely close — they are exact:
```
label 5372 5373 5374 5375 [5376] 5377 5378 [5379] 5380
alpha 46 69 92 115 — 197 220 — 255
step +23 +23 +23 (+82) +23 (+35, clamped)
```
`255 × 2 / 22 = 23.18`. **Three consecutive steps of exactly 23** is 2.0 declared
units per frame on the nose, on the element the play-test complains about, on a
screen that is not a splash. `ui-keyframe-time-unit.md`'s ✅ law reproduces.
## Why the splash read as 5, and why that reading cannot work
The Port derived 5 units/frame from three intervals of my splash timeline. The
derivation is sound arithmetic on an unsound premise, and the premise is one I
handed them:
**An alpha step is not a clock rate.** For a linear segment,
```
Δα per frame = 255 × (units per frame) / T T = the segment's declared length
```
so two elements with different `T` show different `Δα` at an *identical* clock.
The disc says exactly that, and all three numbers now agree at one clock:
| element | `Δα` per frame, measured | implied `T` at 2 units/frame | declared `T` |
|---|---|---|---|
| splash B's six quads | **34** | 15.0 | **15** — the value `ui-keyframe-time-unit.md` already records |
| `ptbtn00`, the plate | **23** | 22.2 | **22** (`t=214 → 236`) |
Two screens, two step sizes 1.5× apart, **one clock**. Reading either step as a
rate gives a different answer, which is the whole of the factor of 2.7.
The second defect is the anchor. The Port's intervals start at a quad's *first
submission*, and on splash A the first submission of `Q7` is already **α = 85**
and of `Q0` **α = 85** — neither is that element's `t` for α = 0. An interval
between two biased onsets is not the interval between two declared times, and the
bias is not equal because the two elements have different `T`.
⚠️ **This is mine to have caused.** `splash-quad-timeline.txt` published alpha
against frame with no `T` beside it, which is precisely the column that makes the
conversion possible. It now says so.
## The other half — the "title settled" anchor is **t ≈ 160**, not t = 118
The Port asks which of two declared times my operational anchor — *glyph counter
first reads its no-plate value 154* — corresponds to. The same capture answers it,
because the draw stream names which element is which.
**`ptcopyright` is the last element to finish building in, and it is the only
glyph element on the screen.** A glyph counter settling *is* that element
reaching full alpha:
```
label 5341 5342 5343 5344 5345 [5346] 5347 5348 5349 5350 → 255 thereafter
alpha 23 57 81 104 139 — 208 231 243 255
```
Calibrating on the plate's own declared ramp (α=46 ↔ t=217.97, α=255 ↔ t=236, so
2.25 units/label over that stretch):
| anchor | label | implied declared t |
|---|---|---|
| `ptcopyright` reaches α = 255 | 5350 | **t ≈ 168** (t ≈ 176 at a flat 2.0/label) |
| the Port's candidate A | | t = 118 — **50 to 58 units away** |
| the Port's candidate B | | t = 160 — **8 to 16 units away** |
**It is candidate B.** The margin is not marginal: the two candidates are 42 units
apart and the measurement sits within a third of one gap of B and more than a
whole gap from A.
⚠️ **And the Port's own note says this is the reading under which `clock:
"shared"` collapses.** I am reporting what the game does; what that costs the
port's model is theirs. It is not evidence against the measurement.
📌 Also from this stream, for whoever defines "settled" next: **the sweep leaves
never settle.** The two off-screen-wide quads translate monotonically through
every one of the 100 labels examined and are still moving when the plate arrives.
"The title has settled" can only ever mean *the build-in elements have finished*,
never *the screen has stopped changing*.
## The instrument fact that bounds all of this
**Labels with zero draws exist, and the animation clock does not advance a fixed
amount across them.** In `5340…5390` the empty labels are
`5346, 5351, 5360, 5367, 5371, 5376, 5379, 5383, 5388` — about one in five.
Across the empty label `5376` the plate's alpha moved **+82**, where three
adjacent occupied labels each moved **+23**. That is ~3.5 nominal steps for one
missing label, not one and not two. So:
* an empty label is **not** a logger artefact — the clock really did advance
across it, by more than a step; and
* frame counts that span a gap are **approximate**, and every count on this page
that does so is quoted as such.
This is why the ramp span is quoted as *10 labels* and the conclusion rests on the
three **gap-free** steps of exactly 23 rather than on the span alone.
## 🔴 What is still NOT answered, and it is the part the port actually needs
**Units per *second* is not settled by this, and my own two captures disagree
about it by roughly the factor that started this.**
`units/second = (units/frame) × (guest frames/second)`. This page pins the first
factor at **2**. It says nothing about the second, and the second is where the
disagreement now lives:
* the port uses **60 units/s**, i.e. 2 × 30 fps;
* 2 × 60 fps would be **120 units/s**, which would put the plate at 1.97 s instead
of 3.93 s — and *"about two seconds early"* is the size of the thing the human
reported;
* this capture produced **6 565 labels in ~241 s ≈ 27.2 labels/s**, which is
Canary's presentation rate, **not** the guest's nominal rate, and cannot
distinguish a 30 Hz guest running at full speed from a 60 Hz guest running at
half.
⚠️ And `title-plate-delay-measured.md`'s 2.13 s does not reconcile with this
capture: settled → plate onset is **20 labels ≈ 0.73 s** here against **2.13 s**
there. The two anchors are the same events, so that is a real ~2.9× disagreement
between two of my own captures, and it is now localised — **not** in units→frames,
which this page settles, but in **frames→seconds**. That page's number is a
wall-clock duration read off a screenshot stream, which
[`../agents/TEMPORAL-VERIFICATION.md`](../agents/TEMPORAL-VERIFICATION.md) says
not to trust; this page's is a count. I am not withdrawing it on that ground
alone, and I am not reconciling them by argument.
**The experiment that settles it** is to read the guest's own frame counter or
vblank rate directly rather than any wall clock — guest memory and CPU state are
available and neither of these two captures used them. That is the next
iteration's first item.
## Reach
One capture, one boot, one title. The 2 units/frame figure now has two
independent screens behind it (the splashes' 34-with-T=15 and the plate's
23-with-T=22) and reproduces a law the corpus already held ✅ on a third route,
so I would expect it to be general. The **anchor** result is about `GP_TITLE`
build 4 specifically and does not generalise anywhere.
## Reproduce
```bash
GRACE=1 NOTAP=1 ARM=early FRAMES=20000 MAXDRAWS=400000 \
tools/re-capture/ui_draw_capture.sh 780 /sylph-home/re/titleplate
# the title arrives ~243 s in; leave the emulator up ~75 s more, then kill it
```
Series: [`data/title-plate-ramp.txt`](data/title-plate-ramp.txt).