re: withdraw the eff3 explanation and the flash advice; add a calibration-free

test that refutes 105

Two claims shipped this morning are withdrawn, and the port had already acted
on one of them.

WITHDRAWN 1: "eff3 was never drawn because a 2-unit flash peak is sub-frame."
eff3's alpha is non-zero for t in (58,64), and the capture's frames 133 and 134
sit at t = 60.0 and 62.2 -- squarely inside that window, with eff2 and eff4
both drawn in the same frames. It should have been submitted and was not. The
absence is real and UNEXPLAINED; it is not sampling phase.

WITHDRAWN 2: "a port drawing all five flashes shows more sweep than the
console". No evidence behind it. The port checked against its own renderer and
found it draws them sequentially at their declared times, never more than two
at once -- which is exactly what frames 131-135 show the game doing. The
pile-up worth warning about was the rest() bug, now fixed.

Kept, at the port's request: a frame-by-frame comparison of the build-in WILL
disagree about which flash lands in which frame -- 2 units per submitted frame
against this run's 2.231 units per presented frame -- and neither side is
wrong. Without that stated, the discrepancy reads as a port defect.

Added, and stronger than the argument it replaces: a calibration-free test of
105 vs 120. The glow's draw is omitted when its alpha reaches zero, and the
smallest alpha actually submitted across 807 drawn frames is 1, so the culling
threshold is read off the data rather than assumed. Measured dark fraction
17.7% (173 of 980 settled frames); a 120-unit cycle with its declared 15-unit
hold predicts 14.4%; a 105-unit cycle predicts 2.2%. 105 is out by 8x and
would need a threshold of alpha 11 out of a peak of 80, while the capture
contains submitted draws at alpha 1..12. No frame rate, no pacing factor, no
wall clock.

Also recorded: a regression of five build-in events against their declared
times (residuals <=0.9 frames) recovers t=0 at frame 106.1 when the composite
spike, not in the fit, is frame 107 -- and that same slope makes the glow's
period imply a 114-unit cycle against a declared 120, which is unexplained.
And the vertex-alpha identity holds for the glow but does NOT generalise:
eff4 reads 255/127/254 on consecutive frames.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
This commit is contained in:
sylph-decoder
2026-08-29 20:03:48 +00:00
parent d98c8214cc
commit 311bd16ad8
4 changed files with 119 additions and 17 deletions

View File

@@ -86,9 +86,28 @@ alpha**, so the ramp can be read straight out of the guest's draw stream
* fitting the decoded ramp gives RMS 13.16 alpha levels against **38.18 for the
same ramp reversed** — the asymmetry is real and in the decoded direction.
This does not re-measure the period in seconds (the run's frame rate was not
recorded), so the falsification below stands on the corpus's wall-clock timings
rather than on this run.
### ✅ And a calibration-free test that refutes 105 outright
The measurements above still need a units-per-frame conversion. This one does not.
The glow's draw is **omitted entirely when its alpha reaches zero**, and the
smallest alpha actually submitted in 807 drawn frames is **1** — so the renderer's
culling threshold is 1, read off the data rather than assumed. The fraction of
settled frames with no glow draw is then a pure ratio within one measurement:
| | dark-frame fraction |
|---|---|
| **measured** (173 of 980 settled frames) | **17.7 %** |
| predicted by a **120**-unit cycle (15-unit dark hold) at threshold 1 | **14.4 %** |
| predicted by a **105**-unit cycle (no dark hold) at threshold 1 | **2.2 %** |
🔴 **105 is out by a factor of eight.** For a 105-unit cycle to produce 17.7 %
dark, the culling threshold would have to be **alpha 11 out of a peak of 80** — and
the capture contains submitted draws at alpha 1, 2, 3, 4, 5, 6, 7, 8, 9, 11 and 12,
which refutes any such threshold directly.
No frame rate, no pacing factor, no wall clock: the declared 15-unit dark hold is
visible in the draw stream as the frames where the game submits no draw at all.
## What this replaces

View File

@@ -72,12 +72,27 @@ a different element**, taking the composite spike (frame 107) as t=0:
other 155 frames sampled.** The two holders are present continuously from frame
134 onward. That is the decoded mechanism, observed.
⚠️ **`eff3` was never drawn, and that is expected rather than a miss.** A flash's
peak is 2 keyframe units, and at 2.346 units per presented frame that is **0.85 of
a frame** — sub-frame. Whether any given flash is sampled at all depends on phase.
Four of five were caught here; a second run would likely catch a different four.
🔴 **A port that draws all five every time will show more of this sweep than the
console does.**
🔴 **`eff3` was never drawn, and I do not know why. An earlier version of this
page said it was a sub-frame phase effect. That is WITHDRAWN.** `eff3`'s alpha is
non-zero for t ∈ (58, 64), and frames 133 and 134 sit at t = 60.0 and 62.2 —
squarely inside it, with `eff2` and `eff4` both drawn in those same frames. It
should have been submitted and was not. Whatever the reason, it is not sampling
phase.
🔴 **A second thing this page previously claimed, also withdrawn: that a port
drawing all five flashes shows "more sweep than the console".** There is no
evidence for that. The port draws them sequentially at their declared times, never
more than two at once, which is what frames 131–135 above show the game doing.
The pile-up worth warning about was the `rest()` bug, and that is fixed.
⚠️ **What a frame-by-frame comparison of the build-in WILL show, and it is not a
defect on either side.** The game's timeline is 60 units/s against a 30 Hz
present, so 2 units per submitted frame; this capture ran at **2.231 units per
presented frame**. A 2-unit flash peak therefore gets about one frame here and
would get more on a faster present. **A build-in compared frame-by-frame against
this capture will disagree about which flashes appear in which frame**, and
neither side is wrong. The settled comparison is unaffected — at t=198 none of the
five is drawn.
## The glow's ramp, read out of the guest
@@ -85,6 +100,11 @@ The plate glow's quad carries a **per-vertex colour whose alpha is the element's
fade alpha**, so the ramp can be read directly rather than inferred from pixels.
* **Observed alpha range: 0 … 80. Decoded peak: 80.** Exact, and not fitted.
* ⚠️ **This identity holds for the glow and does NOT generalise.** Read the same
way, `eff4` gives 255 at frame 133, 127 at 134 and 254 at 135 — non-monotonic,
so a per-vertex alpha is not simply the element's fade alpha for every element.
The glow's agreement (peak exactly 80) is evidence for the glow, not a decoded
rule about vertex colour.
* **Period: 51.158 presented frames**, from the first to the last of **20
consecutive cycle starts** (individual periods 49–53).
* The draw is **omitted entirely** while the glow is dark — which is what the
@@ -112,8 +132,20 @@ zero part-way through a frame.
## Reach and what is not settled
⚠️ **One run, one machine.** 2.346 units per presented frame is *this run's*
pacing, not a property of the game. The internal ratios are what transfer.
⚠️ **One run, one machine.** ~2.23 units per presented frame is *this run's*
pacing, not a property of the game — the game's own quantum is **2 units per
submitted frame** ([`ui-keyframe-time-unit.md`](../ui-keyframe-time-unit.md)). The
internal ratios are what transfer.
✅ **A validation worth stating: the fit recovers t=0 on its own.** Regressing the
observed frame of five events against their declared keyframe times (residuals
≤ 0.9 frames over t = 42…138) gives a slope of 2.231 units/frame and an intercept
at **frame 106.1** — and the composite spike, which was not part of the fit, is
frame **107**.
❔ **The glow's period implies a 114-unit cycle at that slope**, against a declared
120. The dark-fraction test below settles 120 against 105 without any calibration,
but the 5 % gap in the period is unexplained.
❔ **The absolute frame rate of this run was not measured** — Canary logged no fps
and the log has no timestamps — so nothing here is stated in seconds. It did not