A human on a GPU at ~140 fps: "the logos just switch, there is no animation at
all." Measured from a real boot with --film at 0.05 s, then per-frame change:
splash moves 1.30 s of 7.95 s = 16.4 %
publisher splash 0.30 s of motion, then 3.20 s FROZEN
developer splash 0.35 s + 0.25 s, then 2.40 s FROZEN
distinct luma states in 7.95 s 26
A 45-unit build-in cannot be drawn in 26 states, and a fade does not hold one
picture for 3.20 s. The frame counter says 24.8 fps achieved; both are true --
the port is DRAWING 25 times a second and CHANGING almost never.
🔴 Why every check passed, which matters more than the bug:
frozen sweep drives the clock BY HAND -- proves the renderer can draw
pose N, never that the poses are drawn in sequence
settled compare 0.01 % against the capture -- a screen frozen 84 % of the
time matches a settled reference PERFECTLY, that is what
frozen means
achieved fps counts frames DRAWN -- the same pixels 25x/s scores
identically to animating
Every one measured throughput or a pose. None measured CHANGE. Same shape as
InputEventAction bypassing the input map: the instrument sat below the thing
that was broken, so the break could not appear in it.
tools/motion-census closes the class. It measures change and nothing else, and
its --selftest asserts it separates a fade (97.4 % moving) from a switch (2.6 %)
from a frozen film (0.0 %) -- a detector that cannot tell those apart would
report the same green line on all three.
Both briefs: this is the SOLE focus. The port reproduces before changing
anything and gates every fix on a film rather than a still. The decoder maps the
whole pipeline end to end -- disc bytes, the game's per-frame update (does it
interpolate between keyframes or hold?), what is submitted per frame, and what
Canary does to it before a capture records it -- delivered as a SERIES, not a
settled value.
The port should also record the refutation against itself: H2 reads ANSWERED on
the strength of the frozen sweep. The mechanism half stands, the blur is a baked
companion texture. The behaviour half does not.
5.5 KiB
Play-test, 2026-09-02 — the splash does not animate at all
This is the only thing either agent works on until it is fixed.
The human, watching the port on real hardware, on a GPU, at ~140 fps:
"The port does no blur animation at all! I cannot discern if there is any animation at all. The logos just switch without the animation."
Measured, not paraphrased
Filmed from a real boot at 0.05 s (--film), then per-frame change measured
with tools/motion-census:
| splash moves | 1.30 s of 7.95 s — 16.4 % |
| publisher splash | 0.30 s of motion, then 3.20 s frozen |
| developer splash | 0.35 s + 0.25 s, then 2.40 s frozen |
| distinct luma states in 7.95 s | 26 |
A 45-unit build-in cannot be drawn in 26 states, and a fade does not hold one picture for 3.20 s. This is a switch with a flicker on either side.
The frame counter says 24.8 fps achieved. Both are true: the port is drawing 25 times a second and changing almost never.
🔴 Why three instruments all said it was correct
This is the part that matters more than the bug, because it is the fourth time this shape has cost a milestone.
| instrument | what it proved | what it could not see |
|---|---|---|
frozen sweep (--time=, 3 units a step) |
the renderer CAN draw pose N | whether the poses are ever drawn in sequence, while running |
| settled comparison (0.01 % against the capture) | the resting pose is right | a screen frozen 84 % of the time matches a settled reference perfectly — that is what frozen means |
| achieved-fps counter | frames are being drawn | drawing the same pixels 25×/s scores identically to animating |
Every one measured throughput or a pose. Not one measured CHANGE.
That is why the port could write "the companion quads are drawn, verified by a
frozen sweep" and be simultaneously right and useless: the sweep drives the
clock by hand. It is the same defect as InputEventAction bypassing the input
map — the instrument sat below the thing that was broken, so the thing that
was broken could not appear in it.
tools/motion-census exists to close this class. It measures change and nothing
else, and its --selftest proves it separates a fade (97.4 % moving) from a
switch (2.6 %) from a frozen film (0.0 %) — because a detector that cannot tell
those apart would report the same green line on all three.
What both agents do now
Nothing else. Not the clock rate, not the plate, not blend, not audio. This first.
Port
- Reproduce it with
--film+motion-censusbefore changing anything, and quote the numbers. If your run does not reproduce 16.4 %, say so — the disagreement is then the finding. - Find why the clock does not advance the poses. Candidates, unranked and
none established: the keyframe interpolation returns the same pose for a
range of t;
rest()/plateau logic snapping to an endpoint; the group clock not integrating; interpolation between keyframes not happening at all (nearest-keyframe rather than lerp); the screen advancing by keyframe index instead of by time. - Every fix is gated by a film, never by a still. A change that improves a settled frame and leaves the film at 16 % has not fixed this.
motion-censusgoes intocheck-all, so a future regression fails a check instead of waiting for a human.
Decoder — map the whole graphics pipeline, end to end
The human's instruction, in their words: "get the whole graphics pipeline, from the xex/pe + the disc files to the final screen displayed, and take Xenia Canary processing into account too."
So: one continuous account, each stage with evidence and each labelled by the instrument that produced it —
disc bytes → RATC/T8aD decode → what the GAME CODE does per frame
→ the draw calls it submits → Canary's own processing
→ the presented frame
Specifically, and none of it inferable from a file alone:
- The game's per-frame update. Which code advances a UI group's clock, in what units, and what it does between keyframes — does it interpolate, or hold to the next key? That single question decides whether the port should lerp at all. It is in the image; find the function.
- What the game submits per frame during the splash — the draw list frame by frame, not one settled frame. If the alpha changes, it changes somewhere observable: a vertex colour, a PS constant, a blend factor, a texture swap. Name which, with the per-frame series.
- What Canary does to it. Present cadence, any resolve/scaling/gamma between
the guest's draw and the pixels a capture records. A capture is evidence about
Canary's output, and the difference between that and the guest's intent has
bitten this corpus before (the
kernel_display_gamma_typeentry).
⚠️ Deliver a per-frame SERIES, not a settled value. Follow
TEMPORAL-VERIFICATION.md: film it, align by
content, report ordering/counts/durations. The port needs to know what the
alpha trajectory is, and a single frame cannot carry one.
And this is a refutation the port should record against itself
BLOCKED.md H2 currently reads ✅ ANSWERED, on the strength of the frozen
sweep. The mechanism half stands — the blur is a baked companion texture, that
is decoded and correct. The behaviour half does not: the port draws those
quads and does not animate them, so "the companions are drawn" was true and
did not mean what the row used it to mean.