Files
Sylpheed/docs/re/focus-ring-spin-measured.md
sylph-decoder 4fa3099249 re: the main menu's focus ring spins continuously -- period 2.18 s, measured
Answers the port's ask: ptbtneff01 is ANIMATED while a button is focused, not
drawn once and held. The existing page said 'the ring SPINS' from one frame at a
large angle, which is equally consistent with a static draw at a fixed angle.

No angle is quoted anywhere. The 360-bin angular estimator written for this
FAILED its own control -- a synthetic 30 deg came back as 0 deg (peak 0.596)
while 90/180/270 came back exactly -- so it was not used. What settles it needs
no angle: total annulus brightness is conserved to 0.4 % while individual
angular bins swing by 24, i.e. brightness moving AROUND the ring, which excludes
a pulse. The temporal-std map is a clean annulus, falling to ~1 both inside and
outside the stroke, which excludes positional jitter.

Period from the profile's autocorrelation: eight evenly spaced peaks, mean
2.177 s over nine revolutions. Even spacing is the internal check a drifting
instrument cannot pass. That is 120 units = 60 frames = 2.00 s at a true 30 Hz.

Also measured, same run: the ring is the ONLY moving thing on the settled main
menu -- temporal std is exactly 0.000 on every unfocused button, the labels and
the footer. And the ring's centre, located from the std map at game
(520.7, 339.7), matches the declared leaf offset's prediction of (521, 340).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KNR5Y79D1T4bBr6gJQaWFP
2026-08-29 11:50:32 +00:00

5.8 KiB
Raw Blame History

The main menu's focus ring spins continuously — period 2.18 s, measured

Status: measured (not on the disc as a period; the disc declares the ramp, the running game supplies the rate). Taken 2026-08-29 against Xenia Canary with the disc mounted at /disc.

Question this closes: the port asked whether ptbtneff01 — the 42×46 ring on the focused button — is animated while a button sits focused, or drawn once and held. It had shipped the ring at 0° and marked that known-wrong. structures/ui-button-focus-record.md already said "the ring SPINS" from one frame showing it at a large angle; that is consistent with a continuous spin and with a static draw at a fixed angle, so it did not answer the question asked.

What the ring actually does

Five single frames from one run, 4 s apart, focus held on TUTORIAL throughout:

five frames

The ring carries a bright head, and the head is at a different angular position in every frame. It is still moving 16 s in, so it does not ramp once and stop.

⚠️ The 20 s mean of the same run is a uniform circle (ring-20s-mean-uniform.png) — that is the spin smearing itself out, and it is why an averaged frame must never be read as a single frame. A human looking at the live game sees the head; the average does not have one.

The measurement, and why it is not an angle

🔴 No angle is estimated anywhere. The corpus's centroid estimator fails its own control by up to 19.8°, and a 360-bin angular cross-correlation written for this measurement also failed its control — a synthetic 30° rotation of a live frame came back as 0° (peak 0.596), while 90/180/270° came back exactly (peak 1.000), i.e. the estimator only resolves the exact pixel permutations. It was therefore not used.

What was used needs no angle. Two observables separate rotation from a brightness pulse, and both were taken in the same run:

observable rotation predicts pulse predicts measured
total annulus brightness conserved varies 0.4 % spread over 16 s (5 frames); 0.53 % over 359 frames
per-angular-bin brightness varies (a travelling feature) varies together per-bin sd 24.2, max 80.3, against a per-frame angular sd of 42.2

Brightness moves around the annulus while the total holds. A pulse is excluded.

The temporal standard deviation over 103 frames is an annulus and nothing else — dark inside, dark outside, peaking exactly on the ring's stroke (radial std: r 04 → 1.08, r 1013 → 36.75, r 2026 → 1.18):

std annulus

⚠️ A positional jitter would smear variation outside the stroke. It does not: variation falls to ~1 both inside and outside, so the ring is not moving, it is turning.

The period

A dense 359-frame filmstrip (24 s at 15.03 fps against a requested 15 fps — the consumer kept up exactly, so these timestamps are not backlogged) gives the annulus's 360-bin profile per frame, correlated against frame 0. A rotating ring returns to itself once per revolution, so the trace's period is the spin period — again with no angle estimated.

Autocorrelation local maxima, in seconds:

2.18  4.36  6.52  8.70  10.86  13.02  15.22  17.42
spacings: 2.18 2.16 2.18 2.16 2.16 2.20 2.20     mean 2.177 s

Eight consecutive evenly-spaced peaks over nine revolutions. A drifting instrument cannot produce even spacing, which is the internal check on the number.

Raw trace committed at data/focus-ring-period-corr.npy (rows: t, correlation-with-frame-0, annulus mean).

What the period is in the game's own units

⚠️ 2.18 s is wall-clock under this emulator, and the emulator is not running the game at 30 Hz. The corpus measures 27.628.8 fps here. ptbtneff01 declares its first keyframe at t = 120, and under the settled reading (1 unit = 1/60 s, 2 units per rendered frame) 120 units is 60 rendered frames — which at 27.628.8 fps spans 2.082.17 s. The measurement sits at the top of that band.

So the spin is one revolution per 120 units = 60 frames = 2.00 s at a true 30 Hz, and no new constant is needed to account for it. 🟡 The 2.18 s is consistent with the declared 120 rather than a re-derivation of it: the guest frame rate was not measured in this same run, so the agreement is consistency, not closure.

Two other things the same run measured

  • The focus ring is the ONLY moving thing on the settled main menu. Over 103 frames / 20 s untouched, temporal std is exactly 0.000 on every unfocused button box, on the NEW GAME label, and on the ptmsg footer. Only the focused button's box moves (std 4.46 against a background noise floor of 0.906). A port that draws the main menu statically plus a spinning ring is drawing everything that moves.
  • The ring is ptbtneff01, positionally confirmed. Its centre was located from the temporal-std map at game (520.7, 339.7). The declared leaf offset applied to button 3's rest position (542, 322) predicts (521, 340). That is a sub-pixel agreement between a decoded declaration and a live measurement, and it is what ties the annulus to the record rather than to "a circle near the cursor".

Reach

  • One run, one emulator, English locale, GP_TITLE build 5.
  • The period is measured on one focused button (OPTIONS, button 4) and the spin is shown on a second (TUTORIAL, button 3). Not checked on all five, and not checked on EXTRAS.
  • Says nothing about the direction of rotation — the estimator that would give a signed angle failed its control and was not used.