its timing is on the disc Q7. Every title-side screen carries a full-screen black .prm quad that paints last, and its keyframe group IS the transition: black at T0, clear by T1, clear until T2, then back to black on exit. Read with the corpus's start-of-a-ramp rule and Q1's time unit that gives 0.87s for EXTRAS, 0.97s for the main menu, 4.08s for the title -- from the file, not from a stopwatch. The disc-wide check is per-pak all-or-nothing rather than the 41% the headline count suggests, and GP_TITLE's 6 of 12 is the useful row: the six builds carrying a fade quad are exactly the six SCREENS, and the six without are exactly the six overlays. GP_DIALOG is 0 of 133. That is independent corroboration of the overlay finding from two iterations ago. One piece is NOT on the disc and says so: the fade-OUT length. The fourth keyframe has no time slot, because a group's last block stops four bytes short. Measured instead, at 30fps, ~0.4s and the same both directions. And a warning I earned: the luminance rise after a transition is NOT the quad's ramp. The incoming screen's own elements animate in after the quad has cleared -- 1.47s observed against a declared 0.97s. Time the fade from where the frame is pure black. Rig: screenshot samples at 0.5 Hz and cannot see a 0.4s fade at all, which is why an earlier burst called this an instant cut. ffmpeg x11grab at 30fps instead; both go in METHOD.
5.4 KiB
What happens between two screens — a fade through black, and where its timing lives
Status: ✅ CONFIRMED. The quad and its ramp are decoded (a keyframe
group on the disc, with a disc-wide check); the wall-clock timings are
measured off the running game at 30 fps. One piece is undecodable from this
field and is called out below.
Answers MISSION Q7.
The mechanism — decoded
Every title-side screen carries a full-screen untextured primitive that is
black, and paints last: pteff00.prm in GP_TITLE, pfeff00.prm in
GP_SAVE_LOAD. That it sorts last was already established
(structures/ui-paint-order-key.md); what is
new here is that its keyframe group is the transition.
The group is always four blocks, and always this shape:
| block | alpha | meaning |
|---|---|---|
| 1 | 0xff at t = T0 |
the screen starts black |
| 2 | 0x00 at t = T1 |
ramp to fully clear — the screen fades in |
| 3 | 0x00 at t = T2 |
clear; this is the resting pose, the quad is invisible |
| 4 | 0xff, no time |
ramp back to black — the screen fades out on exit |
Read with the corpus's rule that a keyframe is the start of a ramp
(structures/ui-resting-pose.md).
$ tools/re-capture/fade_quads.py 4 5 6 # GP_TITLE
build 4 (title) pteff00.prm t=16 α=255 t=261 α=0 t=269 α=0 t=— α=255
build 5 (main menu) pteff00.prm t=12 α=255 t= 70 α=0 t= 80 α=0 t=— α=255
build 6 (EXTRAS) pteff00.prm t=12 α=255 t= 64 α=0 t= 74 α=0 t=— α=255
Under Q1's 1 unit = 1/60 s: the screen holds black
for 0.20 s, then fades in over 0.87 s (EXTRAS), 0.97 s (main menu)
or 4.08 s (the title).
❔ The fade-OUT duration is not in this field
The fourth block has no time — a group's last block stops 4 bytes short and
that word is already the next group's element index
(ui_layout.rs documents the
packing). So the disc gives the ramp's target (black) and not its length. That
duration is measured below, and the port is authoring it.
The disc-wide check, and what it shows about overlays
Over every GP_*.pak, counting bundles that have a .prm element and ≥8
elements (screen-sized rather than a two-element fragment):
40 of 97 carry a 255 → 0 → 255 quad; 56 of the 60 found disc-wide have exactly 4 keyframes.
41 % sounds weak until it is read per pak, where it is nearly all-or-nothing:
| pak | with quad / screen-sized |
|---|---|
GP_MISSION_SELECT, GP_MOVIE_THEATER, GP_OPTIONS, GP_TUTORIAL, GP_SYSTEM |
2/2 each |
GP_BUNK, GP_CHALLENGE |
6/6 |
GP_STAGE_CLEAR |
4/4 |
GP_SAVE_LOAD |
10/12 |
GP_TITLE |
6/12 |
GP_DIALOG |
0/133 |
GP_DEBRIEFING_PILOTLOG |
4/102 |
GP_TITLE's 6 of 12 is the interesting row, and it is not a gap. The six
that carry the quad are exactly the six screen builds — title, main menu and
EXTRAS, English and Japanese. The six that do not are exactly the six
overlays: the PRESS Ⓐ BUTTON plate and the two DELTASABER plates
(ui-title-build-map.md). An overlay composited onto a
screen has no transition of its own, so it has no fade quad — which is
independent corroboration that those builds are overlays rather than screens.
GP_DIALOG's 0/133 says the same thing about dialog boxes.
The timing — measured
Recorded with ffmpeg -f x11grab -framerate 30 over the game surface, mean
frame luminance per frame; raw data in
captures/transitions/transition-luminance.csv,
filmstrip in
transition-filmstrip.png.
main menu → EXTRAS (Ⓐ) |
EXTRAS → main menu (Ⓑ) |
|
|---|---|---|
| press → first visible change | 0.07 s | 0.37 s |
| fade-out to black | 0.367 s | 0.400 s |
| pure black (luminance 0.02) | 0.233 s | 0.167 s |
| luminance rise until settled | 0.567 s | 1.467 s |
The fade-out is the number the file cannot give, and it comes out the same both ways: ~0.4 s, i.e. ~24 units under Q1's rule.
The black hold is consistent with the file's 12 units (0.20 s) but does not confirm it — the plateau spans the tail of the outgoing screen's fade-out and the head of the incoming screen's black, and this measurement cannot separate them.
⚠️ The luminance rise is not the quad's ramp
The two columns differ by 2.6× where the quad's declared ramps differ by only 1.12× (58 units vs 52). The filmstrip says why: the background reappears first and the labels arrive after it, so what the luminance curve is timing is the incoming screen's own element animations, not the fade quad. Quoting 1.47 s as "the main menu's fade" would be wrong. The quad's ramp is decoded; the screen's build-in is a separate, longer thing.
For the port
- a screen change is: fade the outgoing screen to black over ~0.4 s, hold black briefly, then fade the incoming screen in over its own declared ramp while its elements play their own keyframes;
- the fade-in ramp is read from the file (
T1 − T0on the screen's fade quad); - the ~0.4 s fade-out and the black hold are authored from this page — the disc does not carry them.