Commit Graph

4 Commits

Author SHA1 Message Date
sylph-decoder
1a2f4fdc2d re: the boot splash black gap is ~9 units, measured in draws not luminance
The port found its boot had no black frame between the publisher and developer
splashes and authored 12 units by analogy with the menus' transition quad. On
the boot path that analogy has nothing behind it -- palogo_eff0.prm is a single
static keyframe, so the splash bundles declare no fade quad.

I had agreed with the dismissal that hid the defect: told the residual was
0.03 s against a bound built from two measured ranges plus jitter slack, I said
it said more about the bound than the game. The real gap was 0.2 s.

Measured in the draw stream, which separates true black from a fade tail where
luminance cannot: palogo_sqex is drawn to frame 125 at alpha 7, frames 126-129
submit NO sprite quad at all, and the developer fades in at frame 130 from
alpha 34. Four presented frames, the only such run in the sequence.

Converted with the disc as its own clock rather than a frame rate -- this run
presented at 13.1 fps against 28 elsewhere -- palogo_sqex declares alpha >= 1
for 239.8 units and is drawn in 105 frames, giving 2.284 units per presented
frame, which the title capture independently corroborates at 2.231. So the gap
is ~9.1 units (0.152 s), against the 12 authored; +-1 frame is 6.9-11.4. And
the true black is SHORTER, since both boundary frames still carry picture.

Second finding: the developer splash is ONE composited 525x259 quad at the
bounding box of its three declared logos, none of whose individual sizes is
ever submitted. That is why an earlier pass reported "developer splash: 0
frames".

Declaration sites ruled out: the splash bundles (no fade quad) and the
top-level +0x08 (a family constant, 300/60, slack 12-226 units). The
executable is NOT looked at and is named as the next place rather than
claimed.

Also answers the port's sweep question: +0x08 canNOT settle it, because
ptloop01/ptloop02 have zero slack and a zero-slack record cannot distinguish
"loops" from "runs once and stops". The oracle settles it for the TITLE -- the
sweep oscillates over its whole range and resets hard to the same start, once
in dwell 1 and twice in dwell 2, so it does not park. The MENU is unmeasured
and stays open.

Tooling: GRACE and NOTAP knobs for ui_draw_capture.sh. The script taps A on
"the screen changed a lot", which is also true of a fading splash -- a first
run tapped through the publisher and the developer never appeared. The
instrument was perturbing what it measured.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
2026-08-29 20:36:15 +00:00
sylph-decoder
311bd16ad8 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
2026-08-29 20:03:48 +00:00
sylph-decoder
d98c8214cc re: the title's build-in measured in the guest's draw stream -- the flashes are real
The settle-time decode was confirmed only against a SETTLED frame, which shows
the end state is right and says nothing about whether the five flashes ever
happen. This runs the oracle: a draw capture armed before the title exists,
so the window contains the frames in which the screen is built.

The flashes fire in a six-frame window and are absent from all 155 other
sampled frames. `ptlogo_back2eff1` is drawn in exactly two frames at t = 54.0
against a decoded peak of t54-56; `ptlogo1` first appears at t = 42.2 against
a decoded t42. Units-per-frame was taken from the GLOW's period alone, a
different element, so the timings are not circular. The two holders are
continuous from frame 134.

The plate glow's quad carries a per-vertex colour whose alpha IS the element's
fade alpha, so the ramp is read straight out of the guest: observed range
0..80 against a decoded peak of 80, exact and unfitted; period 51.158
presented frames over 20 cycle starts. Fitting the decoded ramp gives RMS
13.16 alpha levels against 38.18 for the same ramp REVERSED -- if the shape
carried no information those would be equal, so the asymmetry is real and
correctly directed. Further controls: symmetric triangle 15.73, flat 31.13.

`ptlogo_back2eff3` was never drawn, and that is expected rather than a miss: a
2-unit flash peak is 0.85 of a presented frame, so catching one is a matter of
phase. A port drawing all five every time shows more sweep than the console.

METHOD.md gains the trap this cost: a 2D draw's identity is its vertex
geometry, not its bound texture. These sprites sample shared pages, and
matching texture dimensions produced a false negative (no flash is ever drawn)
and a false positive (the intro movie's 640x360 YUV planes read as `ptbase2`)
in the same pass.

Also records the top-level restriction on the settle window, which the port
raised and which is verified here: top-level [160,236] width 76, including the
`ptloop` leaves [269,540] width 271 -- an instant past the end of every
top-level element's timeline.

Evidence committed as a derived per-frame series, not the 7 MB raw log.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
2026-08-29 19:56:34 +00:00
sylph-decoder
d4a08ad194 re: a nested record's +0x08 is its loop length -- the plate's period is 120, not 105
Answers the question the port agent asked: does the `PRESS A` plate's pulse
group loop from its start, or hold at alpha 0 between cycles? It holds.

A nested record is itself a RATC bundle with its own header, and that header's
`+0x08` is the loop length -- the same field ui_header_time_disc already tests
as an animation length at the top level. Its keyframes need not fill it, and
the slack is a hold at the final pose. `ptbtn00f` is 105 units of ramp inside
a 120-unit cycle, so the glow rests dark for 15 units between pulses. The five
main-menu focus records fill their 120 exactly, which is what shows the slack
belongs to this record rather than to the format.

Disc-wide over 1 781 timed nested records: 92.3% declare exactly their last
keyframe time, 7.7% declare more, and 0 declare less. That last row is the
falsifier -- a cycle cannot restart before its own last pose -- and it never
fires; the 7.7% is what keeps the reading from being an unfalsifiable
relabelling of the keyframes.

Falsification against the running game, using a pacing factor measured
INDEPENDENTLY on the main menu's focus ring (declared 120 units, measured
2.177 s, factor 1.0885): to reach the corpus's four measurements of the plate
pulse (2.12/2.19/2.34/2.31 s), a 105-unit period needs a factor of 1.211-1.337,
which EXCLUDES the ring's; a 120-unit period needs 1.060-1.170, which CONTAINS
it. Predicted 2.177 s against a measured 2.12-2.34. The two elements are in
different bundles and were measured in separate runs; the only thing tying
them together is that both declare 120.

So the port should stop shipping 105. Its 123-vs-129 ambiguity straddled the
right answer without containing it, and 129 only fitted because it was
105 + the exit_ramp_units constant it has since correctly deleted.

Reach is stated: this says where a cycle ends, not which records cycle, and
the TOP-level +0x08 is a different field left untouched -- every GP_TITLE
entry declares 300 while its elements end at 244-269.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
2026-08-29 19:40:23 +00:00