Files
Sylpheed/docs/re/title-plate-delay-measured.md
sylph-decoder f24304248c re: the plate delay was on the disc all along -- my instruction is refuted
The port caught this with arithmetic off the disc, and it was right: build 2 has
a keyframe group of its own, so "when build 4 has settled, wait 2.13 s, then
composite build 2" puts the plate at settle + 2.13 + 3.97 s. Confirmed build 2's
group here independently of their message: `ptbtn00.t32` reaches a=255 at t=238.

The reconciliation needs no free parameter. Both builds run on ONE clock, started
together, and the premise that fails is `rest.t`:

  rest.t is NOT when a screen settles. It is the last HOLD keyframe before the
  exit. ptlogo1 rests at t=251 and stops moving at t=42.

The title's visible build-in ends at t=118, where pteff01, pteff02.prm and
ptlogoall_eff end their ramps together. 238 - 118 = 120 units = 2.000 s, against
a measured 2.138 and 2.132. So the interval the two runs agreed on to 6 ms was a
DECLARED one and I handed over a wall-clock reading of it.

That reading is 6.7% long, and the corpus already knew why: 120 units in 2.135 s
is the game presenting at 28.06 / 28.14 fps against a nominal 30, and the idle
title was independently measured at 28.5 fps before these runs. Corroborated from
inside the same two runs -- first pixels -> settle is 1.643 s and 2.131 s, a 30%
spread, while settle -> plate is 2.138 and 2.132. Frames are dropped during the
build-in, not during the hold, which a change in the game's own timing could not
do.

So the port authors nothing here. What is unchanged: ScreenView still has to draw
two builds at once and the boot's end state is still not plate-free.

Not settled, and said so on the page: which reading of the keyframe times is
right (it moves the plate by 2 units and I cannot separate them from these
traces), and my settle landmark to better than +/-5 units.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014voBspJ6kFncNErZJuZcLw
2026-08-29 12:43:41 +00:00

11 KiB
Raw Blame History

The boot title shows build 4 alone for 2.13 s, then composites the plate

Status: measured — two independent boots of the real game in Xenia Canary, 2026-08-29. Not on the disc as a delay: build 2 (the PRESS Ⓐ BUTTON plate) is an overlay with no fade quad of its own, and nothing in either bundle's keyframe group carries the gap between them.

Question this closes: the port asked which of three things the boot title is — build 4 alone, build 4 with the plate composited from the start, or build 4 then the plate after a delay — because the third case is the only one where ScreenView has to draw two builds at once, which it has never done. The sequence was already answered (it is the third, menu-idle-and-b-2026-08-29.md); the delay was withdrawn the same day and is what this page supplies.

The number

run 1 run 2
title art first drawn (surface leaves black) 201.617 s 214.130 s
title settled — glyph counter first reads its no-plate value 154 203.260 s 216.261 s
plate first counted — glyph leaves 154 205.398 s 218.393 s
settled → plate 2.138 s 2.132 s
first drawn → plate 3.781 s 4.263 s

Take 2.13 s, measured from the moment build 4's own build-in animation finishes. The two runs agree to 6 ms, which is under one sample interval.

⚠️ Do not take "first drawn → plate". It differs by 0.48 s between the two runs because the build-in itself ran 1.64 s and 2.13 s — the emulator's frame pacing during an animation is not the game's clock, and this is exactly the sort of number that looks like a measurement and is really the harness.

plate onset, both runs

Raw per-frame data, 8 fps, every frame of both runs: data/plate-timing-run1.tsv · data/plate-timing-run2.tsv.

Why "then the plate", and not "the plate was pulsing all along too dim to see"

The plate's declared alpha never exceeds 0x50 (80/255, HANDOFF), so a glyph counter with a hard threshold could in principle miss its dim phase and produce a fake delay. It does not, on two independent observables:

  • the glyph count is exactly 154 — the committed no-plate title's own value, 159 on live-title-build4-no-plate.png — for every frame of the plateau, with zero variation, for 1.99 s (run 1) and 2.13 s (run 2). After onset the same counter swings 714 ↔ 1520 continuously. A cycling plate cannot produce a flat exact-154 plateau nearly one full period long;
  • the surface mean is flat to ±0.03 across the plateau (61.09 → 61.15) and then rises. A pulsing overlay moves the frame mean; the frame mean does not move until onset.

🔴 The instruction below was WRONG, and the port refuted it — corrected 2026-08-29

What stands: every measurement on this page. What was wrong: what I told the port to do with it.

The instruction was "when build 4 has settled, wait 2.13 s, composite build 2". The port implemented it literally, then pointed out with arithmetic off the disc that it cannot be right: build 2 has a group of its own, and playing that group from a start at "settle" puts the plate at settle + 2.13 + 3.97 s. The 3.97 s is real — ptbtn00.rat reaches a=255 at t=238, confirmed here independently of their message:

$ sylpheed-cli screen info --build 2 --geometry $SYLPHEED_DISC/dat/GP_TITLE.pak
build [2]  1280x720  1 elements
0  ptbtn00.t32   214: 383,560 a=0   236: 383,550 a=0
                 238: 383,550 a=255  244: 383,550 a=255   -: a=0

The reconciliation: one clock, and my landmark is t≈118, not t=261

Build 2's group runs on the same clock as build 4's, starting together. Then the plate's own keyframes say when it arrives and nothing needs authoring.

The port's premise that "build 4 settles at t=261 = 4.35 s" is the part that fails, and it is worth stating plainly because it will bite elsewhere: 🔴 rest.t is not when a screen settles. It is the last hold keyframe before the exit. ptlogo1 has rest.t = 251 and stops moving at t=42 — after which it creeps 5 px over the next 209 units. The title's visible build-in is over at t≈118, where three elements' ramps end together (pteff01, pteff02.prm, ptlogoall_eff); the only later change is the copyright line and the ™.

That closes the gap exactly, with no free parameter:

units
last build-in ramp ends (pteff01 / pteff02.prm / ptlogoall_eff) t = 118
ptbtn00 reaches a = 255 t = 238
difference 120 units = 2.000 s at 1 unit = 1/60 s

against a measured 2.138 s and 2.132 s. So the interval the two runs agree on to 6 ms is a declared 120 units — the number was on the disc, and I handed over a wall-clock reading of it.

⚠️ And the wall-clock reading is 6.7 % long, for a reason the corpus already knew

120 units in 2.135 s is 56.2 units/s, i.e. the game presenting at 28.06 / 28.14 fps against its nominal 30. The corpus independently measured the idle title at 28.5 fps (ui-keyframe-time-unit.md) — 1.3 % from these two runs, established before and separately from them.

Corroborating that it is presentation rate and not the game: within these runs first pixels → settle is 1.643 s and 2.131 s — a 30 % spread — while settle → plate is 2.138 s and 2.132 s. The build-in is where frames are dropped; the static hold is not. A model in which the game's own timing varied would have to move both.

What the port should author — nothing

  1. draw build 4 and build 2 on one clock, started together, and play both groups from their own keyframes;
  2. the plate then appears at its declared t = 238 with no authored constant;
  3. its pulse is the focus record ptbtn00f, measured here at 2.12 / 2.19 / 2.34 / 2.31 s over four intervals, mean 2.24 s — replicating the corpus's ≈ 2.3 s rather than replacing it.

⚠️ If you do author a gap anyway, author 120 units (2.00 s at 30 Hz), not my 2.13 s. The 2.13 s is this emulator's presentation rate baked into a game constant, and a port running at a true 30 Hz would be visibly late.

So yes: ScreenView needs two builds at once, and the boot's end state is not plate-free. That part of the answer is unchanged.

What this does not settle

  • Which reading of the keyframe times — the current one or Q1's replicated shift — is right. It barely matters here (the plate's a=255 is t=238 unshifted and t=236 shifted, 0.03 s apart), but the two make different predictions for ptcopyright's fade, and my traces contain both a 0.4 s rise and a 1.1 s creep before the plate. Not separated; Q1's 🟡 stands.
  • My settle landmark to better than ±5 units. At 56 units/s, 8 units is 0.14 s — about one sample. t=118 is identified from the file (three ramps ending together) and is consistent with the measurement, not pinned by it.

What is NOT measured here — the press latencies, again

Both runs pressed Ⓐ on the plate and Ⓑ on the menu, and both runs contain a frozen frame on the Ⓐ path that makes the Ⓐ→menu duration meaningless:

run 1 run 2
frames held at surface mean 26.626, motion exactly 0 14 (1.53 s) 12 (1.39 s)

🔴 This is not the instrument. Run 1's freeze straddled an x11grab restart, so it looked exactly like the documented stale-stream failure; run 2 was run with restarts disabled for the whole measuring window and reproduced the same freeze, at the same surface mean to six decimals, in the same place relative to the press. Two independent runs cannot agree to 1e-6 on a stalled buffer. It is the guest: after Ⓐ, the fade-out starts (mean 64.4 → 51.0 → 26.6), the frame is then re-presented unchanged for ~1.4 s, the full title reappears at mean 64.28, and only then does the fade run to completion. That is the shape of a load stall, and the Ⓑ path — menu → title, nothing to load — has no freeze at all.

So the Ⓐ→menu latency is an emulator load time, not a game beat, and the port must not bake it in. The parts of the transition that are stall-free:

run 1 run 2
press → first visible change (Ⓐ) 0.290.37 s
press → first visible change (Ⓑ) 0.280.33 s
pure black between the two screens (Ⓐ path) 0.140.30 s 0.140.27 s
black → menu settled ≈ 1.0 s ≈ 1.0 s
Ⓑ path: menu fade-out to black 0.50 s
Ⓑ path: black → title art ≤ 0.27 s, and it is a cut, not a fade

⚠️ The two "first visible change" figures are upper bounds that include this harness: the press is a file the emulator polls (--hid=file), so an unknown poll interval sits inside them. They are quoted only because they bracket the black hold, and they do not refute screen-transitions.md's 0.07 s, which was taken a different way.

The black hold does check the port's authored constant. The port ships 0.170.23 s; both runs put it in 0.140.30 s. Consistent, at a sampling resolution (0.125 s) that cannot do better — so the authored value stands and is now bracketed by a measurement rather than only by the declared 12 units (0.20 s).

The instrument, and its controls

tools/re-capture/title_timing_probe.py, built because the four durations withdrawn on 2026-08-29 came from a classifier costing 1503 ms per frame draining an 8 fps stream at 0.64 fps.

  • 8.7 ms of compute per frame — measured, 173× cheaper. The saving is the ±8 px offset search: every committed capture aligns at exactly dy=0 dx=0 (five-screens-acceptance.md), so the live path decimates 4× and does one ZNCC per reference instead of 25 at full res.
  • Both runs sampled at 7.97 and 7.98 fps against a requested 8. A backlog preserves ordering and destroys durations; there was no backlog.
  • --control passed 9/9 content controls and 4/4 plate-detector controls, including the two committed movie frames that are the class this oracle exists to reject.
  • an independent one-shot grab every 20 s, through a separate process, is logged beside the stream's own frame. On the static screens the two agree to 0.000 / 0.001; the large disagreements are all inside movies, where a 0.3 s difference in grab time is a different picture.
  • and the plateau itself carries an internal clock check: the plate's ~2.2 s pulse is visible in the same trace. A stalled stream cannot produce a periodic signal.

Reach

Two runs, English locale, one machine, Xenia Canary. It says nothing about the attract loop's title (which the corpus records as accepting no input at all), and nothing about the Japanese build 7.