Files
Sylpheed/docs/re/guest-frame-rate-preregistration.md
sylph-decoder f0185fba52 re: PRE-REGISTER the guest frame-rate test -- the movie is the ruler
Units per second is the one number left on the PRESS (A) plate, and both
existing measurements of it are wall-clock readings off an emulator that
runs the guest slower than real time by an unknown factor. They disagree
by 2.9x, which is what that method is worth here.

ADV.wmv declares 30.0000 fps exactly in its own ASF header (stream #2,
avgTimePerFrame = 333333 x100ns). That is a disc fact, so a decoded movie
frame is a tick of a clock Canary's speed cannot stretch.

The measurement is a ratio of counts with no wall clock in it: how many
consecutive swap labels bind the same movie luma texture base.

  H_A  guest 30 fps ->  60 units/s -> 1.0 labels per movie frame
  H_B  guest 60 fps -> 120 units/s -> 2.0 labels per movie frame

Committed BEFORE the capture so the number cannot be chosen afterwards,
with acceptance bands, the three ways the instrument could lie, a guard
for two of them, and a named control (the splashes' established +34/frame
must reproduce in the same log, or the log is not comparable).

Noting the trap I nearly fell into: stream #1's avgTimePerFrame is a
packet rate and reads as 3.05 fps. Reading the wrong stream is the obvious
way to get this wrong, so it is written down.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jc4pciRArGHfxGGhEbwp5t
2026-09-01 18:43:13 +00:00

5.5 KiB
Raw Permalink Blame History

Pre-registration — is the guest 30 fps or 60 fps? The movie is the ruler

Status: open, and this page is written BEFORE the capture. It exists so the number below cannot be chosen after the fact. METHOD.md and ../agents/TEMPORAL-VERIFICATION.md both require the expected value to be stated first; this corpus has two withdrawn findings from not doing it. 2026-09-01.


The one number the port is still blocked on

Everything else about the PRESS Ⓐ plate is settled. HANDOFF.md §H3 states it plainly:

"Units per second is still open, and it is now the only place the disagreement lives. units/s = (units/frame) × (guest frames/s). This pins the first at 2. The second is untouched."

units/s plate at t = 236
H_A — guest presents at 30 fps 60 3.93 s ← what the port ships
H_B — guest presents at 60 fps 120 1.97 s

The play-test says the port's plate is late, and H_B is 1.96 s earlier — "about two seconds early" is the size of what was reported. So this is not a tie-break between two tidy numbers; one of them is the reported defect.

⚠️ Why no capture so far has settled it. Canary presents at ~2728 fps and runs the guest slower than real time by an unknown factor. A wall-clock rate off this emulator therefore cannot tell a 30 Hz guest at full speed from a 60 Hz guest at half speed — they produce the identical observation. Both existing measurements (2.13 s and 0.73 s for the same interval, 2.9× apart) are wall-clock readings, which is why they disagree.

The ruler: a disc fact that is not a wall clock

ADV.wmv — the boot intro and the attract movie, the same asset (movie-binding.md) — declares its video rate in its own ASF header:

/disc/dat/movie/ADV.wmv
  FileProperties        play duration 142.714 s, preroll 5.000 s -> net 137.714 s
  StreamProperties      video, 1280x720, fourcc WMV3
  ExtendedStreamProperties  stream #2  avgTimePerFrame = 333333 x100ns
                                       -> 30.0000 fps  EXACTLY

(Stream #1 is the audio; its avgTimePerFrame of 3 276 559 is a packet rate and is not a video rate. Reading it as one gives a nonsensical 3.05 fps — noted because it is the obvious way to get this wrong.)

30.000 fps is a property of the shipped file, not of a run. A decoded movie frame is therefore a tick of a clock that Canary's speed cannot stretch: however slowly the emulator runs, the guest still decodes 30 movie frames per second of movie time, and movie time is what the movie was authored in.

The measurement

During attract-movie playback, the guest triple-buffers the decoded YUV planes — the splash census already saw them, and correctly excluded them:

"six 640×360 textures and three 1280×720 ones … the attract movie's chroma and luma planes, triple-buffered, and they first appear at frame 234."

So: count how many consecutive swap labels bind the same movie luma texture base. One decoded movie frame = one base change.

🔴 The predictions, stated now

labels per movie frame movie-luma base changes per 100 labels
H_A guest 30 fps ⇒ 60 units/s 1.0 100
H_B guest 60 fps ⇒ 120 units/s 2.0 50

A factor of two, on a ratio of counts, with no wall clock anywhere in it. I will accept H_A if the ratio is within 1.0 ± 0.15 and H_B within 2.0 ± 0.30, and report "neither" otherwise rather than picking the closer.

What would make this instrument lie, and the guard for each

  1. The guest drops movie frames to stay in sync with real time while Canary runs slow. That raises labels-per-movie-frame and biases toward H_B — the dangerous direction, because H_B is the answer I would find more interesting. Guard: a dropped frame shows as a base persisting for an unusual run length. I will report the distribution of run lengths, not the mean. H_A is a spike at 1; H_B is a spike at 2; frame-dropping is a smear with a tail.
  2. The base cycles for a reason other than a new frame (e.g. re-binding the same buffer). Guard: the buffers are triple-buffered, so a clean cycle visits three distinct bases in a fixed order. I will check the order is a 3-cycle before counting anything.
  3. The movie is not playing at its declared rate because the guest is frame-locked to its own presentation instead of to the movie clock. This is the assumption the whole method rests on and it is not guarded — if the run-length distribution is clean but disagrees with both predictions, that is the likely cause, and the finding is then "undecodable by this route".

Control, to be run before the measurement is believed

The same log carries the boot splashes (frames 4…226), where the alpha step is already established at +34 per presented frame on six quads. If the recovered log does not reproduce 34, the capture is not comparable to the one that number came from and nothing else in it should be read.

Reach, in advance

⟨capture⟩ for the ratio; ⟨disc⟩ for the 30.000 fps. If it comes out clean, the result is measured, not decoded: it is a property of how this game drives its own clock, observed once. It would want a second, independent boot before the port bakes it in — and if it says H_B, it says the port's plate is 1.96 s late and that is worth a second run before anyone rewrites a timeline.