# What Canary does between the guest's draw and a captured pixel > # 🔴 CORRECTION 2026-09-02, same day — §2's CONSEQUENCE is REFUTED > > I wrote that the presenter's letterbox-and-scale is in the capture path, that > it explains the 1279×675 surface, and that **"everything measured off a PNG > carries the resample."** The port pre-registered a test and ran it: against > `live-splash-publisher.png`, a **cropped** render scores RMSE **558.1 (0.85 %)** > and a **scaled** one **10 118.8 (15.4 %)**. **Cropping is 18× better.** > > ✅ **Confirmed independently here, from a different observable.** The committed > captures are **1279×675**, **1280×690**, **1252×754** — *varying* heights. A > fixed presenter resample produces one size; **crops of differently-sized > windows produce exactly this spread.** And `ui-render-tone-curve.md` already > recorded every capture aligning at `dy=0 dx=0`, correlation 0.9466, which a > 0.9375 vertical scale cannot produce. The evidence was in the corpus before I > wrote the claim. > > **So the captures are CROPS of a 1:1 surface, not resamples**, and every RMSE, > glyph count and surface mean against them is pixels to pixels with no filter to > caveat. > > ⚠️ **What is NOT refuted:** the cvar reading itself. Canary *does* letterbox by > default. What is refuted is my inference that the corpus's capture path went > through it. Whether the presenter is bypassed, the window is 1:1, or the tool > crops the letterbox before saving is **open and unestablished**. > > 🔴 **The error is the one this session keeps paying for.** I read a > configuration and inferred a consequence *for the data* without testing it > against the data — the same shape as reading a base-address change as a decode. > The test that refutes it costs one render and one RMSE, and I had every capture > needed to run it. > > §1 (gamma) and the two-paths distinction in §3 stand; §3's blanket caveat does > not. Corrected in place below. **Status: ✅ decoded from Canary's own source.** Instrument: ⟨canary-source⟩, with ⟨capture⟩ for the dumped guest shader. 2026-09-02. Answers question 3 of [`../agents/PLAYTEST-2026-09-02.md`](../agents/PLAYTEST-2026-09-02.md) — *"present cadence, and any resolve, scale or gamma between the guest's draw and a capture's pixels."* --- ## 1 — gamma: **Canary applies none** `VdGetCurrentDisplayGamma` is the export the play-test warns about. Reading it: ```cpp void VdGetCurrentDisplayGamma_entry(lpdword_t type_ptr, lpfloat_t power_ptr) { *type_ptr = cvars::kernel_display_gamma_type; // default 2 = TV (BT.709) *power_ptr = float(cvars::kernel_display_gamma_power); } DECLARE_XBOXKRNL_EXPORT1(VdGetCurrentDisplayGamma, kVideo, kStub); ``` **It is declared `kStub` and it transforms nothing.** It *reports* a gamma type to the guest, which D3D would use to build a ramp. So the question becomes whether the **guest** applies one — and for the splash it demonstrably does not. The splash pixel shader, dumped from the running game, is four ALU ops: ``` tfetch2D r2, r1.xy, tf0 mul r1.___w, r2.wwww, r0.wwww mul r0.xyz_, r2.xyzz, r0.xyzz mul r1.xyz_, r0.xyzz, r1.wwww max oC0, r1, r1 ``` **No `pow`, no ramp, no lookup.** Nothing in the splash path applies gamma — neither side of the emulation boundary. ## 2 — geometry: ⚠️ the presenter CAN resample, but the corpus's captures are CROPS `presenter.cc` defaults: | cvar | default | effect | |---|---|---| | `present_letterbox` | **true** | aspect preserved, bars added rather than stretching | | `present_safe_area_x` / `_y` | **100** | nothing cropped | So Canary *would* scale the guest's 1280×720 to fit the host window and letterbox it. 🔴 **But the committed captures did not go through that**, per the correction above — they are crops. The 1279×675 surface is a **cropped window grab**, not a scaled one, which the varying capture sizes (1279×675, 1280×690, 1252×754) show directly. ⚠️ **The `wait_title.sh` single-pixel failure is still real** and still explained: a coordinate valid at 1280×720 lands outside a 1279×675 *crop* just as surely as outside a scaled one. The failure was the fixed coordinate, not the transform. ## 3 — 🔴 So there are TWO measurement paths, and only one has Canary in it | path | route | Canary processing | |---|---|---| | **pixels** | guest draw → EDRAM → resolve → front buffer → **presenter (scale + letterbox)** → X11 → `screenshot` → PNG | **a resample**, plus whatever the window system does | | **vertex stream** | guest CPU writes a vertex buffer → **the draw logger reads guest memory directly** | **none** | 📌 **The per-frame alpha series is the second path.** The `k_8_8_8_8` colour is read out of the guest's own vertex buffer *before* it reaches a shader, a render target, a resolve or the presenter. **There is no Canary processing between the guest's intent and that number** — which is why [`splash-interpolates-every-frame.md`](splash-interpolates-every-frame.md) can state per-frame alphas as the game's values rather than as pixels we measured. 🔴 **The blanket caveat I attached here is WITHDRAWN.** I claimed everything measured off a PNG carries a resample. It does not: the captures are crops, and pixel-exact comparison against them is pixels to pixels. The two-path *distinction* stands — the vertex stream still has strictly less between the guest and the number — but the practical gap is far smaller than I said, and a large body of shared evidence needs no qualifier. ## Refutation attempt, recorded per the adversarial duty **Target:** this corpus's own founding principle, stated at the top of three documents — *"the oracle is the real game running in Xenia Canary, captured."* **Result: it SURVIVES, and my proposed qualifier was WRONG.** I claimed a PNG capture is "the oracle plus a resample". The port tested it and it is not — the captures are crops, and the principle needs no amendment. Recorded as a failed refutation rather than deleted, because the failure is instructive: I tried to attach a caveat to a large body of evidence on the strength of a config file, and the check that would have stopped me was one render and one RMSE. **The vertex stream is still the cleaner instrument** — strictly less sits between the guest and the number — but that is now a statement about robustness, not a correction to anything measured. ## Reach ⟨canary-source⟩ for the gamma stub and the presenter defaults — these are facts about *this build*, and a different `--present_*` or `kernel_display_gamma_type` would change them. ⟨capture⟩ for the shader, which is the splash's; **other screens' shaders have not been checked for gamma** and the negative in §1 covers the splash only. ❔ **Not measured here: the resample's actual filter.** I read the cvars that say scaling happens, not the kernel that does it. What a 1280×720 → 1279×675 resample does to a thin glyph is unquantified, and that is the number anyone doing pixel-exact work against a PNG would need.