re: PRE-REGISTER the decode-vs-rotate test, and add a content hash to the logger

The experiment guest-frame-rate-WITHDRAWN.md named. A triple buffer
rotating once per present visits the same three base addresses whether or
not anything was decoded into them, so base identity cannot separate
"decode per present" (30 fps guest, 60 units/s) from "rotate per present"
(60 fps guest, 120 units/s). A content hash can.

command_processor.cc now emits h=<FNV-1a over 4096 sampled bytes> beside
every sampled texture, omitted rather than faked when the address does not
translate, so a missing hash cannot read as a matching one. Incremental
build, one translation unit.

Predictions committed before the capture: consecutive presents with changed
luma content is ~1.00 under decode-per-present and ~0.50 under
rotate-per-present, with acceptance bands and "neither" reported rather
than rounded.

The control is the part I got wrong last time. A STATIC texture must hash
constant: the splash sprite page 0x11A50000 is a fixed atlas, and if its
hash varies between presents then reading guest memory at draw time races
the decoder and nothing in the log may be read. That fails loudly in the
direction which would otherwise manufacture the answer I previously
reached -- the property my last control lacked. A second control in the
other direction requires the movie luma hash NOT to be constant, which
would mean hashing the wrong bytes and would manufacture the opposite
answer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jc4pciRArGHfxGGhEbwp5t
This commit is contained in:
sylph-decoder
2026-09-01 19:21:04 +00:00
parent 69b233bd50
commit 0b98460772

View File

@@ -0,0 +1,69 @@
# Pre-registration — did the guest DECODE a frame, or just ROTATE a buffer?
**Written and committed BEFORE the capture.** 2026-09-01. This is the experiment
named by [`guest-frame-rate-WITHDRAWN.md`](guest-frame-rate-WITHDRAWN.md) as the
one that settles what that page withdrew.
---
## Why this exists
I measured "one movie luma **base address** change per present", read it as one
decode per present, and concluded 30 fps / 60 units/s. That was withdrawn: a
triple buffer **rotating** once per present visits the same three addresses
whether or not anything was decoded into them, so base identity cannot separate:
* **D — decode per present.** The guest decodes a new movie frame every present.
With `ADV.wmv` authored at 30.000 fps, the guest presents at 30 fps ⇒ **60
units/s** ⇒ the plate's `t = 236` is 3.93 s.
* **R — rotate per present.** The guest presents twice per decoded frame. Then it
presents at 60 fps ⇒ **120 units/s** ⇒ the plate is at 1.97 s and the port is
~2 s late, which is the size of the play-test complaint.
## The instrument
The draw logger now emits a **content hash** beside every sampled texture —
FNV-1a over 4096 bytes spread across the allocation, `h=` omitted rather than
faked when the address does not translate, so a missing hash can never read as a
matching one. Built and linked; `command_processor.cc` only.
## 🔴 The predictions, stated now
Over consecutive presents during attract-movie playback, the fraction of pairs
whose **luma content hash differs**:
| | fraction of consecutive presents with changed luma content |
|---|---|
| **D** — decode per present ⇒ 60 units/s | **≈ 1.00** |
| **R** — rotate per present ⇒ 120 units/s | **≈ 0.50** |
I will accept D within `1.00 0.10` and R within `0.50 ± 0.10`, and report
"neither" otherwise rather than taking the closer. Under R I additionally expect
the *repeat pattern* to be period-2 — each hash appearing on exactly two adjacent
presents — and I will report the run-length distribution, not just the fraction.
## 🔴 The control, and this time it tests the thing the last one did not
**A static texture must hash constant.** The splash sprite page `0x11A50000`
(1280×768) is a fixed atlas: it is uploaded once and sampled for both splashes.
If its hash varies between presents, the hash is unstable — reading raw guest
memory at draw time can race the decoder — and **nothing else in the log may be
read**. This control fails loudly in the direction that would otherwise
manufacture the D result, which is exactly the property my previous control
lacked.
Second control, the other direction: the movie's luma hash must **not** be
constant across the whole movie region either. A hash that never changes would
mean I am hashing the wrong bytes, and would manufacture R.
## What would still not be settled
Whether Canary's presentation cadence equals a real console's. This measures what
the guest does *here*. The vblank-interval evidence (one vblank 71.7 %, two
24.6 %) is consistent with R and is what motivated re-opening this, but it is host
time and cannot stand alone.
⚠️ And a third possibility the two hypotheses do not cover: the guest may decode
at a rate unrelated to both, in which case the fraction lands between the bands
and the honest answer is "neither", with the movie ruler abandoned rather than
stretched to fit.