# πŸ”΄ I cannot measure this emulator's presentation rate β€” and the 2 % between two of my pages is not a disagreement about the game **Status:** one πŸ”΄ **instrument failure** (recorded, not published as a number), and one βœ… **resolution of a challenge** that follows from it. 2026-08-29. ## The challenge The port put two of my pages against each other. Both measure the same declared quantity β€” **120 keyframe units of wall clock during a static hold, in Canary** β€” and they differ by 2 %: | page | measured | implied presentation | |---|---|---| | [`title-plate-delay-measured.md`](title-plate-delay-measured.md), settleβ†’plate, 2 runs | 2.138, 2.132 β†’ **2.135 s** | 28.10 fps | | [`focus-ring-spin-measured.md`](focus-ring-spin-measured.md), 7 spacings | 2.16 … 2.20 β†’ **2.177 s** | 27.56 fps | 0.042 s apart β€” seven times the 6 ms run-to-run agreement the plate page rests on. Its own corroboration argument (*"the build-in is where frames are dropped; the static hold is not"*) is aimed at exactly this, and these are two static holds. Fair challenge. ## βœ… The resolution: 2 % is far inside this emulator's own variation The question assumes the wall clock is stable enough for 2 % to mean something. It is not, and the counterexample is the same interval, in the same container, on the same day: | run | conditions | settle β†’ plate | |---|---|---| | 1 | 8 fps grab | **2.138 s** | | 2 | 8 fps grab | **2.132 s** | | **3** | 8 fps grab **+ `--log_ui_draws=true`** | **2.549 s** | **A 19 % swing on the declared interval, from a logging flag.** The 2 % the two pages differ by is a fifth of that. They were taken in different sessions under different load, and nothing in either can separate "the game timed it differently" from "the emulator ran slower" β€” because both are wall clock. **So the two pages were never in conflict about the game.** They are three readings of one declared quantity through a clock that moves. What settles the quantity is the disc: `t=118 β†’ t=238` is 120 units, and the port's own structural rule for the ring (two keyframes differing only by a 360Β° rotation, first timed and second untimed β€” 16/212 elements matched, all of them focus rings) gives the ring's period the same way. ⚠️ **This removes the evidence that the ring is not 120 units. It does not prove that it is.** The disc-side rule does that, and it is the port's, not mine. ## πŸ”΄ The instrument I built to answer it properly, and why it is dead Wall clock cannot separate the two hypotheses; **frames** can. So I tried to measure the presentation rate. ### Canary's own frame counter perturbs by a third `--log_ui_draws=true --ui_draw_capture_frames=N` logs `[UI-CAP] capture armed` and `[UI-CAP] done: D draws over F frames`. This is the instrument that produced the corpus's **28.5 fps** ([`ui-keyframe-time-unit.md`](ui-keyframe-time-unit.md)). Measured here, armed on the title with a concurrent 8 fps grab: > **300 frames in 16.567 s = 18.11 fps**, against ~28 for the same screen without > it. ⚠️ **A frame counter that costs a third of the frame rate cannot measure the frame rate.** This does not overturn the 28.5 fps β€” that run had no concurrent grab β€” but it does mean the figure is a **lower bound taken under its own instrument's load**, and it should not be treated as *the* rate. ### And the unperturbing replacement FAILED its own decisive control The alternative: count **distinct frames** in an oversampled crop of something that moves every frame (the spinning focus ring). At 60 fps against a source presenting at R, the fraction of consecutive samples that differ is R/60. Three controls were written before the run. It failed the one that matters: | control | result | |---|---| | a static crop must read β‰ˆ 0 | **2.63 fps of "change"** β€” not clean | | two sampling rates must agree | 45 fps β†’ **12.73**, 60 fps β†’ **12.08** βœ… | | **must agree with the game's own counter while both run** | counter **15.88** vs `[UI-CAP]` **17.59** β€” **10 % low** πŸ”΄ | The third is decisive and it is a failure: **the ring does not change on every presented frame**, so the counter measures the ring's animation rate, not the presentation rate. It also drifted 12.1 β†’ 15.9 β†’ 18.1 across one session, which a real rate estimator on a settled screen should not do. **Dead, not tuneable** β€” per [`METHOD.md`](METHOD.md). No rate is published from it. Controls preserved: [`data/present-rate-controls-2026-08-29.json`](data/present-rate-controls-2026-08-29.json). ## What this means for the port, and for everything I hand over **Do not take a wall-clock duration off this container as a game constant.** Demonstrated range for one declared interval: 2.13 – 2.55 s, and the emulator's own rate read anywhere from 12 to 28 fps depending on what was watching it. The rule that follows: **a measured interval landing near a round number of declared units almost certainly IS that number of units**, and the units are what to ship. Wall clock is for ordering and for sanity, not for constants. ## Reach * One container, one day, one machine. It says nothing about how a different host runs Canary, and nothing about hardware. * It does **not** refute the 28.5 fps in `ui-keyframe-time-unit.md`; it reclassifies it as a load-dependent lower bound. * ❔ **The game's true update rate is still not grounded in the disc.** "2 units per submitted frame" *is* grounded β€” it was read off a frame-indexed draw capture, so it is independent of how fast the emulator runs. What rests on the emulator is only the step from *a submitted frame* to *1/30 s*, i.e. the present interval. That is a constant in the executable, and reading it is blocked on the missing disassembly route ([`static-route-recovered.md`](static-route-recovered.md)).