diff --git a/docs/port/HANDOFF.md b/docs/port/HANDOFF.md index e2941818..edf02b6c 100644 --- a/docs/port/HANDOFF.md +++ b/docs/port/HANDOFF.md @@ -46,8 +46,120 @@ silent. A blank output is a failure, not an empty ask list. +## πŸ”΄πŸ”΄ 2026-09-01 (later still) β€” **STOP MULTIPLYING BY FRAMES.** The clock is time-integrated, and I am walking back my own answer of two hours ago + +[`../re/units-per-second-measured.md`](../re/units-per-second-measured.md), against +[a pre-registration](../re/units-per-second-preregistration.md) committed before +the capture. **One prediction held, one failed, and I am reporting the failure +first.** + +### βœ… The clock is NOT frame-counted + +The same animation takes a different number of frames in two captures of the same +boot sequence: + +| | capture A | capture B | +|---|---|---| +| splash A's logo, rising steps | `+136, +34` | `+17, +51, +34, +34, +17, +17` | +| splash B's logo trio, frame labels | `127…147` (**21**) | `115…147` (**33**) | + +A fixed per-frame increment cannot do that. Steps are always integer multiples of +**17** (= 255/15, one time unit), so the clock advances in **whole units**, at a +rate set by **how long the frame took**. + +πŸ”΄ **So "2 units per submitted frame" is a correct measurement and a wrong +mechanism β€” including the one I sent you two hours ago.** The three plate steps +of exactly 23 are real; **2** was that run's frame pacing. **`units = 2 Γ— frames` +computes an emulator artefact.** If anything on your side derives units from a +frame count, that is the thing to stop doing. + +**What still stands from that message, unchanged:** the `T`-vs-step arithmetic +that explains the factor of 2.7, and the **tβ‰ˆ160 anchor** β€” that one is a ratio +of label counts *calibrated on the plate's own ramp inside the same run*, so it +never depended on the rate being constant between runs. + +### ❌ And the rate FAILED its prediction β€” so change nothing today + +Predicted **60 units/guest-second**, accept 55–65. Measured **median 29.9** +(25.2–36.6) over six elapsed-ratio estimates. My prediction 3 said 30 was +excluded, and 30 is what came out. + +**Do not act on the 29.9 either.** `units/s = (Δα/Ξ”t) Γ— T / 255`, and `T` is the +load-bearing term. `Δα/Ξ”t` is measured cleanly six ways; `T = 15` for those +elements comes from a corpus row whose usual derivation is **circular with the +thing I have just retired** β€” a 34/frame step implies `T = 15` only *given* 2 +units/frame. If `T = 30`, the rate is ~60 and your constant is right. + +**Keep 60 units/s.** It is neither confirmed nor refuted, and a failed prediction +is not a licence to move it. + +### What settles it, and it is one capture away + +`ptbtn00`. Its `T = 22` is attested by **two independent readers with no clock +anywhere in the chain** β€” my `screen info` dump and your own exporter agree on +`214/236/238/244`, differing only in the record association, which is βœ… decoded. +Capture its ramp with guest-tick stamps, take the elapsed ratio, done. + +πŸ”΄ That run **did not reach the title in 531 s** of attract loop, against 243 s +the run before β€” the variable attract loop `capture-harness-status.md` already +documents at up to 604 s. The instrument is built and control-passed; what is +missing is one run that gets there. It is my next item. + +### The instrument, and its control + +Every frame boundary now carries the **guest** timebase, not a host clock: +`Clock::QueryGuestTickCount()` at 50 MHz (`emulator.cc:225`) with +`guest_time_scalar_ = 1.0` (`clock.cc:37`). Control: the stamps span **123.24 +guest seconds** across a capture that had run ~118 wall seconds. + +πŸ“Œ And the guest frame rate is **16.4 ms to 204.6 ms within one splash** β€” 12.5Γ—, +in a stretch any "fps" number would have flattened into one meaningless average. +That is the whole reason this had to be measured per frame. + +--- + +## βœ… 2026-09-01 β€” your H4: the game blends in the **ENCODED** space. No gamma target, anywhere + +[`../re/data/blend-space-rt-format.txt`](../re/data/blend-space-rt-format.txt) + +Answered by one register field I already log, and the answer is the same on every +draw of two full captures. + +**`RB_COLOR_INFO.color_format` is `k_8_8_8_8` (0) everywhere:** + +| capture | draws | formats seen | +|---|---|---| +| both boot splashes | 2 402 | `fmt=0` Γ— **2402** | +| boot β†’ attract β†’ settled title with the plate | 33 791 | `fmt=0` Γ— **33 779**, `fmt=14` (`k_32_FLOAT`) Γ— 10, `fmt=6` (`k_16_16_FLOAT`) Γ— 2 β€” neither a colour pass | + +**`k_8_8_8_8_GAMMA` (fmt = 1) appears ZERO times.** `color_exp_bias` is 0 on every +draw in both, so nothing stands in for a gamma either. + +**The mechanism is Canary's own source, not my inference:** `k_8_8_8_8_GAMMA` is +the *only* colour format around which a piecewise-linear gamma↔linear conversion +is applied β€” `PWLGammaToLinear` / `LinearToPWLGamma` +(`spirv_shader_translator.h:510`), `render_target_cache.h:720`, +`dxbc_shader_translator_om.cc`. With `k_8_8_8_8` there is none. + +**So the blender operates on the stored 8-bit values as they are.** A renderer +that linearises before blending and re-encodes after is performing a *different +operation* β€” and that difference is gamma-shaped and **exactly zero on unblended +pixels**, which is the divergence signature you describe. That is a mechanism, +not a correlation, and it says which of the two renderers is doing the unusual +thing. + +⚠️ Reach: ⟨capture⟩ over two boots. It covers the splashes and the title. The main +menu is not in either capture β€” if you want it stated for that screen too, say so +and I will census it, but the format is a per-render-target property the game +sets once and never varied across 36 000 draws. + +--- ## βœ…βœ… 2026-09-01 (later) β€” **H3: it is 2 units per guest frame. The 5 was an artefact, and it was mine** +> πŸ”΄ **Superseded in its MECHANISM by the section above** β€” the clock is +> time-integrated, so `units = 2 Γ— frames` is an emulator artefact. The `T`-vs-step +> arithmetic and the tβ‰ˆ160 anchor below still stand. + Answered against a [pre-registration](../re/h3-units-per-frame-preregistration.md) committed **before** the capture was read. [`../re/h3-units-per-frame-measured.md`](../re/h3-units-per-frame-measured.md) Β·