From 06c69b3143b21d618a5dcefafb6403a8fe64742b Mon Sep 17 00:00:00 2001 From: sylph-decoder Date: Tue, 1 Sep 2026 18:43:13 +0000 Subject: [PATCH] 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 Claude-Session: https://claude.ai/code/session_01Jc4pciRArGHfxGGhEbwp5t --- docs/re/guest-frame-rate-preregistration.md | 113 ++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 docs/re/guest-frame-rate-preregistration.md diff --git a/docs/re/guest-frame-rate-preregistration.md b/docs/re/guest-frame-rate-preregistration.md new file mode 100644 index 00000000..4a8543c3 --- /dev/null +++ b/docs/re/guest-frame-rate-preregistration.md @@ -0,0 +1,113 @@ +# 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 ~27–28 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.