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
This commit is contained in:
110
docs/re/structures/boot-splash-gap-measured.md
Normal file
110
docs/re/structures/boot-splash-gap-measured.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# The black gap between the boot splashes — measured in draws, not luminance
|
||||
|
||||
**Classification: measured.** Xenia Canary, `ui_draw_capture.sh GRACE=1 NOTAP=1
|
||||
ARM=early`, 2026-08-29. Evidence:
|
||||
[`boot-splash-gap-draws.csv`](../data/boot-splash-gap-draws.csv).
|
||||
|
||||
## Why this was open
|
||||
|
||||
The port found that its boot had **no black frame at all** between the publisher
|
||||
and developer splashes, and authored **12 units** (0.200 s) 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 at all.
|
||||
|
||||
🔴 **And I had agreed with the dismissal that hid it.** Told that 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. It did not — the underlying gap was 0.2 s
|
||||
and the port had been missing it since P3. A plausible explanation for a small
|
||||
number is exactly how a real defect stays hidden.
|
||||
|
||||
## The measurement
|
||||
|
||||
Luminance cannot separate the outgoing screen's fade tail from true black. The
|
||||
**draw stream** can: it says exactly which frames submit a sprite quad at all.
|
||||
|
||||
| frames | what is submitted |
|
||||
|---|---|
|
||||
| 2 – 20 | `palogo_sqex_eff` (685×90) — the publisher's glow |
|
||||
| 21 – 125 | `palogo_sqex` (666×65) — the publisher wordmark, fading to alpha **7** |
|
||||
| **126 – 129** | 🔴 **nothing — 4 frames with no sprite quad at all** |
|
||||
| 130 – 153 | the developer splash, fading in from alpha **34** |
|
||||
|
||||
**The gap is 4 presented frames**, and it is the only such run anywhere between
|
||||
the first and last sprite of the sequence.
|
||||
|
||||
## Converting it without a frame rate
|
||||
|
||||
The run's presented rate is not usable — measured at **13.1 fps** while the title
|
||||
was up, against the corpus's 28 fps for other runs, and it is not stable enough to
|
||||
convert a 4-frame interval.
|
||||
|
||||
So the **disc's own timeline is the clock**. `palogo_sqex` declares alpha ≥ 1 from
|
||||
t ≈ 15.06 to t ≈ 254.9 — **239.8 units** — and is drawn in **105 frames**:
|
||||
|
||||
> **2.284 units per presented frame**, from the same screen in the same capture.
|
||||
> (The title capture, independently, gave 2.231.)
|
||||
|
||||
| | units | seconds at 60 units/s |
|
||||
|---|---|---|
|
||||
| if the gap were 3 frames | 6.9 | 0.114 |
|
||||
| **measured — 4 frames** | **9.1** | **0.152** |
|
||||
| if the gap were 5 frames | 11.4 | 0.190 |
|
||||
| *the port's authored value* | *12* | *0.200* |
|
||||
|
||||
**The measured gap is ~9 units, and 12 is at or just past the top of the
|
||||
quantisation range.** ⚠️ And the true black is *shorter* than this, not longer:
|
||||
the last publisher frame still carries alpha 7 and the first developer frame
|
||||
alpha 34, so both boundary frames contain some picture that this count treats as
|
||||
black.
|
||||
|
||||
## ✅ A second thing the draw stream shows: the developer splash is ONE quad
|
||||
|
||||
The developer bundle declares three logos — `palogo_gamearts` at (390,164),
|
||||
`palogo_seta` at (521,316), `palogo_anima` — and **none of their sizes is ever
|
||||
submitted**. What is submitted is a single **525×259 quad at (378,155)**, which is
|
||||
the bounding box of the three. The game composites them and blits the group.
|
||||
|
||||
This is why an earlier pass reported "developer splash: 0 frames" — it was
|
||||
matching individual logo sizes that the game never draws.
|
||||
|
||||
## Is the gap declared anywhere? Not that I can find
|
||||
|
||||
* ❌ **In the splash bundles.** `palogo_eff0.prm` is one static keyframe
|
||||
(`t0 a255`). No fade quad, no gap.
|
||||
* ❌ **In the top-level header `+0x08`.** It is a **family constant** — 300 for
|
||||
every title/splash entry in `GP_TITLE`, 60 for the loading bundles — and the
|
||||
slack against each bundle's last keyframe ranges from **12 to 226 units**
|
||||
(the main menu's is 220, i.e. 3.7 s). It cannot be a declared gap.
|
||||
* ❔ **In the executable — not looked at.** The corpus has the boot phase machine
|
||||
at `this+132`; whether a dwell or gap constant sits near it is untested. That is
|
||||
the next place, and I am naming it rather than claiming reach I do not have.
|
||||
|
||||
So the port is right to author this, and should author **~9 units** rather than 12.
|
||||
|
||||
## Reach
|
||||
|
||||
⚠️ **One boot, one machine.** The 4-frame count is quantised and the ±1 frame is
|
||||
the dominant uncertainty (6.9 – 11.4 units).
|
||||
|
||||
⚠️ The units-per-frame calibration assumes the guest's animation clock advances
|
||||
uniformly across the gap, which is the same assumption the rest of this corpus's
|
||||
frame→unit conversions make.
|
||||
|
||||
## 🔴 The instrument was perturbing what it measured
|
||||
|
||||
`ui_draw_capture.sh` taps Ⓐ whenever the screen changes a lot, to skip the attract
|
||||
movie. **That trigger is also true while a boot splash is fading.** A first run
|
||||
classified the publisher splash as a movie at t = 3 s, tapped through it, and the
|
||||
developer splash never appeared. Two knobs now exist and a boot run needs both:
|
||||
|
||||
* `GRACE=1` — the fixed 8 s wait before arming meant an `ARM=early` capture always
|
||||
missed both splashes, which run at ~1.2 – 9.5 s of guest time;
|
||||
* `NOTAP=1` — no input at all.
|
||||
|
||||
## Reproducing
|
||||
|
||||
```bash
|
||||
GRACE=1 NOTAP=1 FRAMES=9000 MAXDRAWS=5000000 ARM=early \
|
||||
tools/re-capture/ui_draw_capture.sh 300 /tmp/uicap-boot
|
||||
```
|
||||
@@ -121,6 +121,35 @@ visible in the draw stream as the frames where the game submits no draw at all.
|
||||
hold; it is what a four-sample wall-clock measurement of a ~2 s period in this
|
||||
emulator looks like.
|
||||
|
||||
## ❔ What this field does NOT settle: do the `ptloop` sweeps loop?
|
||||
|
||||
Asked by the port, hoping `+0x08` would decide it. **It does not.**
|
||||
|
||||
`ptloop01.rat` declares `+0x08` = **600** with keyframes reaching exactly t=600;
|
||||
`ptloop02.rat` declares **720**, keyframes to t=720. **Slack zero** — and a
|
||||
zero-slack record is precisely the case this field cannot discriminate: "loops at
|
||||
600" and "runs once for 600 and stops" produce the identical header. 92.3 % of
|
||||
records on the disc are in that state.
|
||||
|
||||
✅ **The oracle answers it for the title, and the answer is that they keep
|
||||
moving.** Tracking the sweep quad across two title dwells in a draw capture:
|
||||
|
||||
| | sweep draws | x range (NDC) | backward jumps to the start |
|
||||
|---|---|---|---|
|
||||
| title dwell 1 (frames 138–1220) | 1008 | −3.02 … −0.33 | **1** (frame 1161) |
|
||||
| title dwell 2 (frames 5963–7025) | 908 | −3.02 … +0.42 | **2** (frames 6370, 6822) |
|
||||
|
||||
The x position oscillates across the whole range for the entire dwell and resets
|
||||
hard to the same start value (−2.38). A run-once-and-park would show one traverse
|
||||
and then a constant x. **It does not park.**
|
||||
|
||||
⚠️ **This is the TITLE, and the port asked about the MAIN MENU.** Both declare
|
||||
`ptloop01`/`ptloop02` with the same 600/720, but I have not captured the menu, and
|
||||
the port's own evidence — an idle menu capture matching best with the sweeps
|
||||
off-screen — points the other way. Either the menu's sweeps behave differently, or
|
||||
"best match" is doing badly at detecting an absence, which the port said itself.
|
||||
**Unresolved for the menu; measured for the title.**
|
||||
|
||||
## Reach
|
||||
|
||||
⚠️ **This says where a cycle ends, not that every record cycles.** 92.3 % of
|
||||
|
||||
Reference in New Issue
Block a user