re: the transition between screens is a fade through black, and most of

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.
This commit is contained in:
Sylpheed RE agent
2026-08-28 18:05:19 +00:00
parent 4dbfa22a0b
commit 43dba9d6e0
7 changed files with 625 additions and 6 deletions

View File

@@ -31,9 +31,9 @@ authored version can be deleted.
| Q2 | which build is which screen state | ✅ answered | `GP_TITLE` is **8 screens shipped twice, EN/JP**: 4/7 title art, 2/3 the `PRESS Ⓐ` plate, 5/8 main menu, 6/9 `EXTRAS`, 0/1 and 10/11 two unidentified `DELTASABER` plates — [`ui-title-build-map.md`](../re/ui-title-build-map.md) |
| Q3 | paint order for the six screens | ✅ answered | **decoded**: a `u16` layer key at `+0x0A` of each `T8aD` sprite header, stable-sorted with declaration index; unkeyed elements get an implied key. Confirmed on 5 measured orders + `EXTRAS` vs a capture. One residual: the **tie-break** is unknown and bites on one element of the title — [`structures/ui-paint-order-key.md`](../re/structures/ui-paint-order-key.md) |
| Q4 | button → GamePart | 🟡 mostly answered | **measured** which screen each button opens (4 of 5; `NEW GAME` untested — it hangs). The **GamePart id is a name match** onto the decoded id table, not a measurement — [`menu-navigation-semantics.md`](../re/menu-navigation-semantics.md) |
| Q5 | navigation semantics | ✅ answered | **measured**: opens on `TUTORIAL` (not the top); ⬆⬇ one step, **wraps both ends**; ⬅➡ do nothing; Ⓑ returns to the parent **with focus restored**; Ⓑ on the main menu → title; Ⓑ on the title → nothing — [`menu-navigation-semantics.md`](../re/menu-navigation-semantics.md) |
| Q5 | navigation semantics | ✅ answered | **measured**: initial focus varies boot to boot (2× `TUTORIAL`, 1× `NEW GAME`); ⬆⬇ one step, **wraps both ends**; ⬅➡ do nothing; Ⓑ returns to the parent **with focus restored**; Ⓑ on the main menu → title; Ⓑ on the title → nothing — [`menu-navigation-semantics.md`](../re/menu-navigation-semantics.md) |
| Q6 | boot sequence + what drives it | 🟡 partial | order observed, and the **attract cycle is timed**: ~810 s idle on the title → fade to black → ~85 s of video → title again, plate and all. The driver is still not decoded |
| Q7 | transitions | ❔ open | |
| Q7 | transitions | ✅ answered | a **fade through black**, drawn by the screen's own last-painting `.prm` quad. Fade-in ramp is **decoded** from its keyframes; the ~0.4 s fade-out is **measured** (not in the file) — [`screen-transitions.md`](../re/screen-transitions.md) |
| Q8 | menu audio bindings | ❔ open | cue table complete, event binding is not |
| Q9 | video binding + playback rules | 🟡 partial | `ADV.wmv` is the boot intro; new-game intro unidentified |
| Q10 | music-bank sub-wave roles (intro+loop?) | ❔ open | we concatenate blindly today |
@@ -97,10 +97,9 @@ authored version can be deleted.
* **Menu movement, measured off the running game.** ⬆⬇ move one item per press
and **wrap at both ends** (5-item main menu and 3-item `EXTRAS` both). ⬅➡ do
nothing. Ⓑ goes up one level **and restores focus to the item you came from**;
Ⓑ on the main menu returns to the title; Ⓑ on the title does nothing. The main
menu opens focused on **`TUTORIAL`**, the middle item — 🟡 reproducible in this
harness (2/2) but a third recorded run implies `NEW GAME`, so re-test before
hardcoding it. All **measured**, none of it on the disc.
Ⓑ on the main menu returns to the title; Ⓑ on the title does nothing. **Initial
focus is not stable**: three boots of the same script gave `TUTORIAL`,
`TUTORIAL`, `NEW GAME`. Do not hardcode it; pick one and say you picked it. All **measured**, none of it on the disc.
* **Each button's destination is measured; its GamePart id is not.**
`LOAD GAME` → the save-slot list, `TUTORIAL` → the lesson list, `OPTIONS`
the settings menu, `EXTRAS``GP_TITLE` build 6, `EXTRAS ▸ MISSION SELECT`
@@ -108,6 +107,18 @@ authored version can be deleted.
GamePart ids (`3`, `25`, `8`, `5`, `7`) are the entries of the decoded id table
whose **names match the screens seen**; that binding is authored, not measured.
* **A screen change is a fade through black.** Each screen carries a full-screen
black `.prm` quad that paints last (`pteff00.prm` / `pfeff00.prm`) whose
keyframe group *is* the transition: black at `T0`, clear by `T1`, clear until
`T2`, then back to black on exit. ✅ decoded, with a disc-wide check — and in
`GP_TITLE` exactly the six **screen** builds carry it while the six overlays do
not. The fade-in length is `T1 T0` and is read from the file (0.87 s for
`EXTRAS`, 0.97 s main menu, 4.08 s title). ❔ **The fade-OUT length is not on
the disc** — the last keyframe has no time slot; **measured ~0.4 s**, twice.
The black hold measures 0.170.23 s. ⚠️ Do not time the fade-in off a capture's
brightness: the incoming screen's own element animations dominate it and run
much longer than the quad.
* **The GamePart id table** — 29 entries at `.rdata 0x820A1630`, confirmed by the
executable's own registration strings. ✅ This is the screen vocabulary; which
button reaches which entry is Q4 and is *not* part of it.

View File

@@ -150,6 +150,7 @@ files, which is how the same ground got covered twice.
| [`ui-paint-order-third-permutation.md`](ui-paint-order-third-permutation.md) | A third measured paint order — tool built and validated, screen not reached | ✅ the reader works and is CONFIRMED against both previously |
| [`ui-quad-class-foothold.md`](ui-quad-class-foothold.md) | The guest's UI quad class — a foothold found from the capture's vertex layout | 🟡 PROBABLE for the identification below (it is a static read, but |
| [`menu-navigation-semantics.md`](menu-navigation-semantics.md) | The title menu — how it moves, and where each button goes | ✅ measured: wraps both ends, Ⓑ restores focus, ⬅➡ inert; 4 of 5 destinations driven. 🟡 GamePart id is a name match, ❔ `NEW GAME` untested |
| [`screen-transitions.md`](screen-transitions.md) | Between two screens — a fade through black, and where its timing lives | ✅ the fade quad's keyframe group is decoded (disc-wide: per-pak all-or-nothing; `GP_TITLE` = the 6 screens, not the 6 overlays); the ~0.4 s fade-OUT is measured, not on the disc |
| [`ui-title-build-map.md`](ui-title-build-map.md) | Which `GP_TITLE` build is which screen state | ✅ CONFIRMED for title / `PRESS Ⓐ` / main menu / `EXTRAS` against live captures; the archive is 8 screens × EN/JP, and "6/8/9 are submenus" is withdrawn |
| [`ui-title-paint-order-capture.md`](ui-title-paint-order-capture.md) | The title screen's paint order, measured from the guest's draw submissions | ✅ CONFIRMED — the order in which the running game paints the title |
| [`upstream-baseline.md`](upstream-baseline.md) | A stock-upstream baseline runs Stage 02 crash-free | ✅ CONFIRMED — upstream canary_experimental + only the pad |

View File

@@ -140,3 +140,15 @@ agent's loop prompt, i.e. nowhere durable. See [`README.md`](README.md) for the
Detect the **focus ring** in the gutter left of the labels instead
(`tools/re-capture/menu_focus.py`, 254 vs <82 — no threshold tuning needed),
and look at the PNG before believing either.
* **`screenshot` samples at 0.5 Hz — it cannot time an animation.** Measured:
~2 s per grab (an `import` of the root plus an ImageMagick crop). A 0.4 s fade
falls entirely between two samples, which is why a 40-frame burst across a
screen change looked like an instant cut. For anything timed, record the
display instead: `ffmpeg -f x11grab -framerate 30 -video_size <W>x<H> -i
:98+<X>,<Y> -t <secs>`, then read per-frame statistics off the file. Take the
geometry from `xwininfo -root -tree`, the same way `bin/screenshot` does.
* **A screen's brightness curve is not its fade quad.** The incoming screen's own
elements animate in *after* the transition quad has cleared, so mean luminance
keeps rising long after the fade is over — 1.47 s against a declared 0.97 s on
one screen. Time the fade from where the frame is *pure black*, and take the
ramp itself from the keyframes.

View File

@@ -35,6 +35,11 @@ neighbourhood, not just the line.
## Screens, classes and RTTI
* "the transition between menu screens is a cut" → it is a **fade through
black**; a 0.5 Hz screenshot burst simply samples too slowly to see it.
[`screen-transitions.md`](screen-transitions.md)
* "the main menu's initial focus is fixed" → three boots of one script gave
`TUTORIAL`, `TUTORIAL`, `NEW GAME`.
* "the title menus drop d-pad presses shorter than ~0.3 s" → **refuted by my
own data.** The menu **wraps at both ends**; every press registered, and the
"missing" step was the wrap. See [`menu-navigation-semantics.md`](menu-navigation-semantics.md).

View File

@@ -0,0 +1,421 @@
frame,seconds,mean_luminance
0,0.0000,26.045
1,0.0333,26.054
2,0.0667,26.051
3,0.1000,26.054
4,0.1333,26.049
5,0.1667,26.054
6,0.2000,26.052
7,0.2333,26.053
8,0.2667,26.046
9,0.3000,26.053
10,0.3333,26.049
11,0.3667,26.052
12,0.4000,26.047
13,0.4333,26.050
14,0.4667,26.048
15,0.5000,26.049
16,0.5333,26.047
17,0.5667,26.049
18,0.6000,26.048
19,0.6333,26.048
20,0.6667,26.045
21,0.7000,26.048
22,0.7333,26.049
23,0.7667,26.048
24,0.8000,26.046
25,0.8333,26.048
26,0.8667,26.048
27,0.9000,26.049
28,0.9333,26.047
29,0.9667,26.048
30,1.0000,26.048
31,1.0333,26.048
32,1.0667,26.047
33,1.1000,26.048
34,1.1333,26.047
35,1.1667,26.047
36,1.2000,26.046
37,1.2333,26.046
38,1.2667,26.046
39,1.3000,26.047
40,1.3333,26.046
41,1.3667,26.047
42,1.4000,26.047
43,1.4333,26.048
44,1.4667,26.047
45,1.5000,26.049
46,1.5333,26.050
47,1.5667,26.052
48,1.6000,26.051
49,1.6333,26.052
50,1.6667,26.052
51,1.7000,26.052
52,1.7333,26.052
53,1.7667,26.055
54,1.8000,26.056
55,1.8333,26.056
56,1.8667,26.055
57,1.9000,26.058
58,1.9333,26.059
59,1.9667,26.059
60,2.0000,26.057
61,2.0333,26.062
62,2.0667,26.022
63,2.1000,22.032
64,2.1333,21.744
65,2.1667,17.909
66,2.2000,13.996
67,2.2333,13.966
68,2.2667,11.113
69,2.3000,8.072
70,2.3333,7.862
71,2.3667,6.270
72,2.4000,3.375
73,2.4333,1.771
74,2.4667,0.020
75,2.5000,0.020
76,2.5333,0.020
77,2.5667,0.020
78,2.6000,0.020
79,2.6333,0.020
80,2.6667,0.020
81,2.7000,5.985
82,2.7333,5.991
83,2.7667,5.990
84,2.8000,5.991
85,2.8333,5.986
86,2.8667,7.432
87,2.9000,9.300
88,2.9333,9.283
89,2.9667,9.484
90,3.0000,11.294
91,3.0333,11.263
92,3.0667,11.606
93,3.1000,12.608
94,3.1333,12.807
95,3.1667,12.790
96,3.2000,14.517
97,3.2333,18.497
98,3.2667,26.935
99,3.3000,27.008
100,3.3333,27.010
101,3.3667,27.039
102,3.4000,27.036
103,3.4333,27.083
104,3.4667,27.239
105,3.5000,27.294
106,3.5333,27.293
107,3.5667,27.294
108,3.6000,27.289
109,3.6333,27.291
110,3.6667,27.290
111,3.7000,27.291
112,3.7333,27.289
113,3.7667,27.292
114,3.8000,27.291
115,3.8333,27.292
116,3.8667,27.291
117,3.9000,27.294
118,3.9333,27.291
119,3.9667,27.293
120,4.0000,27.290
121,4.0333,27.292
122,4.0667,27.291
123,4.1000,27.292
124,4.1333,27.290
125,4.1667,27.293
126,4.2000,27.293
127,4.2333,27.293
128,4.2667,27.292
129,4.3000,27.297
130,4.3333,27.296
131,4.3667,27.297
132,4.4000,27.296
133,4.4333,27.299
134,4.4667,27.300
135,4.5000,27.302
136,4.5333,27.301
137,4.5667,27.304
138,4.6000,27.304
139,4.6333,27.304
140,4.6667,27.302
141,4.7000,27.306
142,4.7333,27.308
143,4.7667,27.309
144,4.8000,27.309
145,4.8333,27.312
146,4.8667,27.311
147,4.9000,27.311
148,4.9333,27.310
149,4.9667,27.317
150,5.0000,27.319
151,5.0333,27.321
152,5.0667,27.322
153,5.1000,27.327
154,5.1333,27.327
155,5.1667,27.328
156,5.2000,27.327
157,5.2333,27.333
158,5.2667,27.334
159,5.3000,27.335
160,5.3333,27.334
161,5.3667,27.344
162,5.4000,27.347
163,5.4333,27.350
164,5.4667,27.351
165,5.5000,27.359
166,5.5333,27.359
167,5.5667,27.360
168,5.6000,27.358
169,5.6333,27.365
170,5.6667,27.366
171,5.7000,27.369
172,5.7333,27.367
173,5.7667,27.383
174,5.8000,27.386
175,5.8333,27.387
176,5.8667,27.386
177,5.9000,27.399
178,5.9333,27.400
179,5.9667,27.402
180,6.0000,27.400
181,6.0333,27.413
182,6.0667,27.414
183,6.1000,27.415
184,6.1333,27.413
185,6.1667,27.432
186,6.2000,27.434
187,6.2333,27.438
188,6.2667,27.436
189,6.3000,27.449
190,6.3333,27.448
191,6.3667,27.451
192,6.4000,27.449
193,6.4333,27.466
194,6.4667,27.471
195,6.5000,27.472
196,6.5333,27.470
197,6.5667,27.480
198,6.6000,27.478
199,6.6333,27.480
200,6.6667,27.476
201,6.7000,27.509
202,6.7333,27.510
203,6.7667,27.516
204,6.8000,27.514
205,6.8333,27.519
206,6.8667,27.519
207,6.9000,27.518
208,6.9333,27.516
209,6.9667,27.538
210,7.0000,27.537
211,7.0333,27.539
212,7.0667,27.538
213,7.1000,27.558
214,7.1333,27.556
215,7.1667,27.558
216,7.2000,27.554
217,7.2333,27.577
218,7.2667,27.576
219,7.3000,27.577
220,7.3333,27.572
221,7.3667,27.596
222,7.4000,27.598
223,7.4333,27.603
224,7.4667,27.597
225,7.5000,27.610
226,7.5333,27.611
227,7.5667,27.613
228,7.6000,27.607
229,7.6333,27.621
230,7.6667,27.621
231,7.7000,27.622
232,7.7333,27.617
233,7.7667,27.624
234,7.8000,27.626
235,7.8333,27.630
236,7.8667,27.622
237,7.9000,27.640
238,7.9333,27.637
239,7.9667,27.639
240,8.0000,27.633
241,8.0333,27.642
242,8.0667,27.639
243,8.1000,27.642
244,8.1333,27.637
245,8.1667,27.658
246,8.2000,27.653
247,8.2333,27.655
248,8.2667,27.649
249,8.3000,27.645
250,8.3333,27.648
251,8.3667,26.704
252,8.4000,23.887
253,8.4333,23.723
254,8.4667,16.471
255,8.5000,13.119
256,8.5333,13.102
257,8.5667,12.118
258,8.6000,10.955
259,8.6333,10.956
260,8.6667,5.365
261,8.7000,3.422
262,8.7333,3.416
263,8.7667,2.820
264,8.8000,0.020
265,8.8333,0.020
266,8.8667,0.020
267,8.9000,0.020
268,8.9333,0.020
269,8.9667,3.267
270,9.0000,5.012
271,9.0333,5.449
272,9.0667,7.339
273,9.1000,9.208
274,9.1333,10.415
275,9.1667,10.418
276,9.2000,10.462
277,9.2333,10.459
278,9.2667,10.569
279,9.3000,10.701
280,9.3333,10.868
281,9.3667,12.924
282,9.4000,14.688
283,9.4333,14.756
284,9.4667,17.184
285,9.5000,19.441
286,9.5333,19.438
287,9.5667,19.492
288,9.6000,19.492
289,9.6333,19.492
290,9.6667,19.508
291,9.7000,23.405
292,9.7333,23.417
293,9.7667,23.414
294,9.8000,23.416
295,9.8333,23.409
296,9.8667,23.467
297,9.9000,24.927
298,9.9333,24.929
299,9.9667,24.926
300,10.0000,25.788
301,10.0333,25.785
302,10.0667,25.789
303,10.1000,25.893
304,10.1333,25.908
305,10.1667,25.905
306,10.2000,25.905
307,10.2333,25.976
308,10.2667,25.986
309,10.3000,25.980
310,10.3333,25.981
311,10.3667,25.976
312,10.4000,25.984
313,10.4333,26.020
314,10.4667,26.022
315,10.5000,26.016
316,10.5333,26.021
317,10.5667,26.018
318,10.6000,26.020
319,10.6333,26.016
320,10.6667,26.021
321,10.7000,26.021
322,10.7333,26.021
323,10.7667,26.019
324,10.8000,26.022
325,10.8333,26.022
326,10.8667,26.022
327,10.9000,26.020
328,10.9333,26.025
329,10.9667,26.025
330,11.0000,26.025
331,11.0333,26.023
332,11.0667,26.029
333,11.1000,26.027
334,11.1333,26.028
335,11.1667,26.024
336,11.2000,26.024
337,11.2333,26.024
338,11.2667,26.024
339,11.3000,26.029
340,11.3333,26.029
341,11.3667,26.027
342,11.4000,26.029
343,11.4333,26.024
344,11.4667,26.027
345,11.5000,26.027
346,11.5333,26.027
347,11.5667,26.025
348,11.6000,26.031
349,11.6333,26.030
350,11.6667,26.033
351,11.7000,26.028
352,11.7333,26.032
353,11.7667,26.032
354,11.8000,26.032
355,11.8333,26.029
356,11.8667,26.034
357,11.9000,26.039
358,11.9333,26.041
359,11.9667,26.041
360,12.0000,26.040
361,12.0333,26.046
362,12.0667,26.047
363,12.1000,26.046
364,12.1333,26.050
365,12.1667,26.051
366,12.2000,26.051
367,12.2333,26.051
368,12.2667,26.051
369,12.3000,26.051
370,12.3333,26.051
371,12.3667,26.051
372,12.4000,26.050
373,12.4333,26.055
374,12.4667,26.056
375,12.5000,26.056
376,12.5333,26.055
377,12.5667,26.056
378,12.6000,26.056
379,12.6333,26.056
380,12.6667,26.055
381,12.7000,26.056
382,12.7333,26.056
383,12.7667,26.056
384,12.8000,26.055
385,12.8333,26.055
386,12.8667,26.056
387,12.9000,26.056
388,12.9333,26.056
389,12.9667,26.056
390,13.0000,26.055
391,13.0333,26.071
392,13.0667,26.072
393,13.1000,26.074
394,13.1333,26.082
395,13.1667,26.083
396,13.2000,26.083
397,13.2333,26.083
398,13.2667,26.083
399,13.3000,26.110
400,13.3333,26.111
401,13.3667,26.114
402,13.4000,26.113
403,13.4333,26.118
404,13.4667,26.119
405,13.5000,26.121
406,13.5333,26.119
407,13.5667,26.140
408,13.6000,26.140
409,13.6333,26.144
410,13.6667,26.142
411,13.7000,26.155
412,13.7333,26.157
413,13.7667,26.158
414,13.8000,26.157
415,13.8333,26.165
416,13.8667,26.165
417,13.9000,26.168
418,13.9333,26.165
419,13.9667,26.165
1 frame seconds mean_luminance
2 0 0.0000 26.045
3 1 0.0333 26.054
4 2 0.0667 26.051
5 3 0.1000 26.054
6 4 0.1333 26.049
7 5 0.1667 26.054
8 6 0.2000 26.052
9 7 0.2333 26.053
10 8 0.2667 26.046
11 9 0.3000 26.053
12 10 0.3333 26.049
13 11 0.3667 26.052
14 12 0.4000 26.047
15 13 0.4333 26.050
16 14 0.4667 26.048
17 15 0.5000 26.049
18 16 0.5333 26.047
19 17 0.5667 26.049
20 18 0.6000 26.048
21 19 0.6333 26.048
22 20 0.6667 26.045
23 21 0.7000 26.048
24 22 0.7333 26.049
25 23 0.7667 26.048
26 24 0.8000 26.046
27 25 0.8333 26.048
28 26 0.8667 26.048
29 27 0.9000 26.049
30 28 0.9333 26.047
31 29 0.9667 26.048
32 30 1.0000 26.048
33 31 1.0333 26.048
34 32 1.0667 26.047
35 33 1.1000 26.048
36 34 1.1333 26.047
37 35 1.1667 26.047
38 36 1.2000 26.046
39 37 1.2333 26.046
40 38 1.2667 26.046
41 39 1.3000 26.047
42 40 1.3333 26.046
43 41 1.3667 26.047
44 42 1.4000 26.047
45 43 1.4333 26.048
46 44 1.4667 26.047
47 45 1.5000 26.049
48 46 1.5333 26.050
49 47 1.5667 26.052
50 48 1.6000 26.051
51 49 1.6333 26.052
52 50 1.6667 26.052
53 51 1.7000 26.052
54 52 1.7333 26.052
55 53 1.7667 26.055
56 54 1.8000 26.056
57 55 1.8333 26.056
58 56 1.8667 26.055
59 57 1.9000 26.058
60 58 1.9333 26.059
61 59 1.9667 26.059
62 60 2.0000 26.057
63 61 2.0333 26.062
64 62 2.0667 26.022
65 63 2.1000 22.032
66 64 2.1333 21.744
67 65 2.1667 17.909
68 66 2.2000 13.996
69 67 2.2333 13.966
70 68 2.2667 11.113
71 69 2.3000 8.072
72 70 2.3333 7.862
73 71 2.3667 6.270
74 72 2.4000 3.375
75 73 2.4333 1.771
76 74 2.4667 0.020
77 75 2.5000 0.020
78 76 2.5333 0.020
79 77 2.5667 0.020
80 78 2.6000 0.020
81 79 2.6333 0.020
82 80 2.6667 0.020
83 81 2.7000 5.985
84 82 2.7333 5.991
85 83 2.7667 5.990
86 84 2.8000 5.991
87 85 2.8333 5.986
88 86 2.8667 7.432
89 87 2.9000 9.300
90 88 2.9333 9.283
91 89 2.9667 9.484
92 90 3.0000 11.294
93 91 3.0333 11.263
94 92 3.0667 11.606
95 93 3.1000 12.608
96 94 3.1333 12.807
97 95 3.1667 12.790
98 96 3.2000 14.517
99 97 3.2333 18.497
100 98 3.2667 26.935
101 99 3.3000 27.008
102 100 3.3333 27.010
103 101 3.3667 27.039
104 102 3.4000 27.036
105 103 3.4333 27.083
106 104 3.4667 27.239
107 105 3.5000 27.294
108 106 3.5333 27.293
109 107 3.5667 27.294
110 108 3.6000 27.289
111 109 3.6333 27.291
112 110 3.6667 27.290
113 111 3.7000 27.291
114 112 3.7333 27.289
115 113 3.7667 27.292
116 114 3.8000 27.291
117 115 3.8333 27.292
118 116 3.8667 27.291
119 117 3.9000 27.294
120 118 3.9333 27.291
121 119 3.9667 27.293
122 120 4.0000 27.290
123 121 4.0333 27.292
124 122 4.0667 27.291
125 123 4.1000 27.292
126 124 4.1333 27.290
127 125 4.1667 27.293
128 126 4.2000 27.293
129 127 4.2333 27.293
130 128 4.2667 27.292
131 129 4.3000 27.297
132 130 4.3333 27.296
133 131 4.3667 27.297
134 132 4.4000 27.296
135 133 4.4333 27.299
136 134 4.4667 27.300
137 135 4.5000 27.302
138 136 4.5333 27.301
139 137 4.5667 27.304
140 138 4.6000 27.304
141 139 4.6333 27.304
142 140 4.6667 27.302
143 141 4.7000 27.306
144 142 4.7333 27.308
145 143 4.7667 27.309
146 144 4.8000 27.309
147 145 4.8333 27.312
148 146 4.8667 27.311
149 147 4.9000 27.311
150 148 4.9333 27.310
151 149 4.9667 27.317
152 150 5.0000 27.319
153 151 5.0333 27.321
154 152 5.0667 27.322
155 153 5.1000 27.327
156 154 5.1333 27.327
157 155 5.1667 27.328
158 156 5.2000 27.327
159 157 5.2333 27.333
160 158 5.2667 27.334
161 159 5.3000 27.335
162 160 5.3333 27.334
163 161 5.3667 27.344
164 162 5.4000 27.347
165 163 5.4333 27.350
166 164 5.4667 27.351
167 165 5.5000 27.359
168 166 5.5333 27.359
169 167 5.5667 27.360
170 168 5.6000 27.358
171 169 5.6333 27.365
172 170 5.6667 27.366
173 171 5.7000 27.369
174 172 5.7333 27.367
175 173 5.7667 27.383
176 174 5.8000 27.386
177 175 5.8333 27.387
178 176 5.8667 27.386
179 177 5.9000 27.399
180 178 5.9333 27.400
181 179 5.9667 27.402
182 180 6.0000 27.400
183 181 6.0333 27.413
184 182 6.0667 27.414
185 183 6.1000 27.415
186 184 6.1333 27.413
187 185 6.1667 27.432
188 186 6.2000 27.434
189 187 6.2333 27.438
190 188 6.2667 27.436
191 189 6.3000 27.449
192 190 6.3333 27.448
193 191 6.3667 27.451
194 192 6.4000 27.449
195 193 6.4333 27.466
196 194 6.4667 27.471
197 195 6.5000 27.472
198 196 6.5333 27.470
199 197 6.5667 27.480
200 198 6.6000 27.478
201 199 6.6333 27.480
202 200 6.6667 27.476
203 201 6.7000 27.509
204 202 6.7333 27.510
205 203 6.7667 27.516
206 204 6.8000 27.514
207 205 6.8333 27.519
208 206 6.8667 27.519
209 207 6.9000 27.518
210 208 6.9333 27.516
211 209 6.9667 27.538
212 210 7.0000 27.537
213 211 7.0333 27.539
214 212 7.0667 27.538
215 213 7.1000 27.558
216 214 7.1333 27.556
217 215 7.1667 27.558
218 216 7.2000 27.554
219 217 7.2333 27.577
220 218 7.2667 27.576
221 219 7.3000 27.577
222 220 7.3333 27.572
223 221 7.3667 27.596
224 222 7.4000 27.598
225 223 7.4333 27.603
226 224 7.4667 27.597
227 225 7.5000 27.610
228 226 7.5333 27.611
229 227 7.5667 27.613
230 228 7.6000 27.607
231 229 7.6333 27.621
232 230 7.6667 27.621
233 231 7.7000 27.622
234 232 7.7333 27.617
235 233 7.7667 27.624
236 234 7.8000 27.626
237 235 7.8333 27.630
238 236 7.8667 27.622
239 237 7.9000 27.640
240 238 7.9333 27.637
241 239 7.9667 27.639
242 240 8.0000 27.633
243 241 8.0333 27.642
244 242 8.0667 27.639
245 243 8.1000 27.642
246 244 8.1333 27.637
247 245 8.1667 27.658
248 246 8.2000 27.653
249 247 8.2333 27.655
250 248 8.2667 27.649
251 249 8.3000 27.645
252 250 8.3333 27.648
253 251 8.3667 26.704
254 252 8.4000 23.887
255 253 8.4333 23.723
256 254 8.4667 16.471
257 255 8.5000 13.119
258 256 8.5333 13.102
259 257 8.5667 12.118
260 258 8.6000 10.955
261 259 8.6333 10.956
262 260 8.6667 5.365
263 261 8.7000 3.422
264 262 8.7333 3.416
265 263 8.7667 2.820
266 264 8.8000 0.020
267 265 8.8333 0.020
268 266 8.8667 0.020
269 267 8.9000 0.020
270 268 8.9333 0.020
271 269 8.9667 3.267
272 270 9.0000 5.012
273 271 9.0333 5.449
274 272 9.0667 7.339
275 273 9.1000 9.208
276 274 9.1333 10.415
277 275 9.1667 10.418
278 276 9.2000 10.462
279 277 9.2333 10.459
280 278 9.2667 10.569
281 279 9.3000 10.701
282 280 9.3333 10.868
283 281 9.3667 12.924
284 282 9.4000 14.688
285 283 9.4333 14.756
286 284 9.4667 17.184
287 285 9.5000 19.441
288 286 9.5333 19.438
289 287 9.5667 19.492
290 288 9.6000 19.492
291 289 9.6333 19.492
292 290 9.6667 19.508
293 291 9.7000 23.405
294 292 9.7333 23.417
295 293 9.7667 23.414
296 294 9.8000 23.416
297 295 9.8333 23.409
298 296 9.8667 23.467
299 297 9.9000 24.927
300 298 9.9333 24.929
301 299 9.9667 24.926
302 300 10.0000 25.788
303 301 10.0333 25.785
304 302 10.0667 25.789
305 303 10.1000 25.893
306 304 10.1333 25.908
307 305 10.1667 25.905
308 306 10.2000 25.905
309 307 10.2333 25.976
310 308 10.2667 25.986
311 309 10.3000 25.980
312 310 10.3333 25.981
313 311 10.3667 25.976
314 312 10.4000 25.984
315 313 10.4333 26.020
316 314 10.4667 26.022
317 315 10.5000 26.016
318 316 10.5333 26.021
319 317 10.5667 26.018
320 318 10.6000 26.020
321 319 10.6333 26.016
322 320 10.6667 26.021
323 321 10.7000 26.021
324 322 10.7333 26.021
325 323 10.7667 26.019
326 324 10.8000 26.022
327 325 10.8333 26.022
328 326 10.8667 26.022
329 327 10.9000 26.020
330 328 10.9333 26.025
331 329 10.9667 26.025
332 330 11.0000 26.025
333 331 11.0333 26.023
334 332 11.0667 26.029
335 333 11.1000 26.027
336 334 11.1333 26.028
337 335 11.1667 26.024
338 336 11.2000 26.024
339 337 11.2333 26.024
340 338 11.2667 26.024
341 339 11.3000 26.029
342 340 11.3333 26.029
343 341 11.3667 26.027
344 342 11.4000 26.029
345 343 11.4333 26.024
346 344 11.4667 26.027
347 345 11.5000 26.027
348 346 11.5333 26.027
349 347 11.5667 26.025
350 348 11.6000 26.031
351 349 11.6333 26.030
352 350 11.6667 26.033
353 351 11.7000 26.028
354 352 11.7333 26.032
355 353 11.7667 26.032
356 354 11.8000 26.032
357 355 11.8333 26.029
358 356 11.8667 26.034
359 357 11.9000 26.039
360 358 11.9333 26.041
361 359 11.9667 26.041
362 360 12.0000 26.040
363 361 12.0333 26.046
364 362 12.0667 26.047
365 363 12.1000 26.046
366 364 12.1333 26.050
367 365 12.1667 26.051
368 366 12.2000 26.051
369 367 12.2333 26.051
370 368 12.2667 26.051
371 369 12.3000 26.051
372 370 12.3333 26.051
373 371 12.3667 26.051
374 372 12.4000 26.050
375 373 12.4333 26.055
376 374 12.4667 26.056
377 375 12.5000 26.056
378 376 12.5333 26.055
379 377 12.5667 26.056
380 378 12.6000 26.056
381 379 12.6333 26.056
382 380 12.6667 26.055
383 381 12.7000 26.056
384 382 12.7333 26.056
385 383 12.7667 26.056
386 384 12.8000 26.055
387 385 12.8333 26.055
388 386 12.8667 26.056
389 387 12.9000 26.056
390 388 12.9333 26.056
391 389 12.9667 26.056
392 390 13.0000 26.055
393 391 13.0333 26.071
394 392 13.0667 26.072
395 393 13.1000 26.074
396 394 13.1333 26.082
397 395 13.1667 26.083
398 396 13.2000 26.083
399 397 13.2333 26.083
400 398 13.2667 26.083
401 399 13.3000 26.110
402 400 13.3333 26.111
403 401 13.3667 26.114
404 402 13.4000 26.113
405 403 13.4333 26.118
406 404 13.4667 26.119
407 405 13.5000 26.121
408 406 13.5333 26.119
409 407 13.5667 26.140
410 408 13.6000 26.140
411 409 13.6333 26.144
412 410 13.6667 26.142
413 411 13.7000 26.155
414 412 13.7333 26.157
415 413 13.7667 26.158
416 414 13.8000 26.157
417 415 13.8333 26.165
418 416 13.8667 26.165
419 417 13.9000 26.168
420 418 13.9333 26.165
421 419 13.9667 26.165

View File

@@ -0,0 +1,117 @@
# 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](../port/MISSION.md).
## 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`](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`](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](ui-keyframe-time-unit.md)'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`](../../crates/sylpheed-formats/src/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`](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`](captures/transitions/transition-luminance.csv),
filmstrip in
[`transition-filmstrip.png`](captures/transitions/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 T0` on 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.

52
tools/re-capture/fade_quads.py Executable file
View File

@@ -0,0 +1,52 @@
#!/usr/bin/env python3
"""Dump every `.prm` primitive's keyframe group (alpha + time) for a UI build.
The screen-transition fade lives here -- see docs/re/screen-transitions.md.
Usage: PAK=<pak> fade_quads.py [build...] (default: GP_TITLE, builds 2 4 5 6)"""
import struct, sys, glob, os, zlib
sys.path.insert(0, "/work/Syplheed-Reborn/tools/re-capture")
src = open("/work/Syplheed-Reborn/tools/re-capture/regn_decode.py").read()
exec(src.split("# ── POF0")[0])
DECL_AT, DECL_ENTRY, KF = 0x20, 60, 40
def be32(b,o): return struct.unpack_from(">I", b, o)[0]
def parse(bundle):
n = be32(bundle, 0x14)
names=[]
for i in range(n):
o = DECL_AT + i*DECL_ENTRY
names.append(bundle[o:o+28].split(b"\0")[0].decode("ascii","replace"))
groups={}
pos = DECL_AT + n*DECL_ENTRY
for _ in range(n):
if pos+8 > len(bundle): break
idx = be32(bundle,pos); frames = be32(bundle,pos+4)
if idx>=n or frames==0 or frames>4096: break
first = pos+12; end = first + frames*KF - 4
g=[]
for k in range(frames):
blk = first + k*KF
if blk+36 > len(bundle) or blk+36 > end: break
g.append(dict(fade=be32(bundle,blk), sx=be32(bundle,blk+16), sy=be32(bundle,blk+20),
x=struct.unpack_from(">i",bundle,blk+28)[0], y=struct.unpack_from(">i",bundle,blk+32)[0],
t=(be32(bundle,blk+36) if blk+40<=end else None)))
groups[idx]=g; pos=end
return names, groups
pak = os.environ.get("PAK", "/work/sylph_extract/dat/GP_TITLE.pak")
E = pak_entries(pak)
E = [b for h,b in E]
# build index -> pak entry index, from `screen list`: 0..9 then 12, 15
BUILDS = {0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,10:12,11:15}
want = [int(a) for a in sys.argv[1:]] or [2,4,5,6]
for b in want:
names, groups = parse(E[BUILDS[b]])
print(f"=== build {b} ===")
for i,nm in enumerate(names):
if not nm.endswith(".prm"): continue
g = groups.get(i, [])
print(f" [{i}] {nm} {len(g)} kf")
for k in g:
a=(k['fade']>>24)&0xff
print(f" t={str(k['t']):>5} fade=0x{k['fade']:08x} (alpha {a:3d}) scale={k['sx']}x{k['sy']} pos=({k['x']},{k['y']})")