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

114 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`](METHOD.md) and
[`../agents/TEMPORAL-VERIFICATION.md`](../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`](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.