than loop The port agent ranked a plate-free capture of build 4 above any further static RE, so that came first. B from the main menu returns to the title and the plate fades in a beat later, which opens a clean window. Recorded at 20 fps from the press: the art appears at 1.10 s, builds in to 3.70 s, sits settled and unobstructed until 5.00 s, and the plate arrives at 5.10 s -- the band jumps from 282 to 3755 bright pixels. Committed the frame at 4.0 s as the reference for the cyan glow slab they report drawing and the game not having. Their other sub-question -- whether a keyframe group loops or holds -- falls out of the decoded sweeps plus a measurement I already had, and the two agree. ptloop01's final keyframe parks pteff03.t32 at x=1521 and ptloop02's parks pteff03a.t32 at x=-839, both off-screen on a 1280-wide design; and over 18 s of settled title the centre tiles sit at sd <= 0.01 when a looping group would recross the screen every 7.5 s. So groups HOLD at the last keyframe. The loop*.rat name is misleading. Also recorded, in the corpus rather than only in their report: the rest_plateau bug, with their exact identifying condition -- the final untimed keyframe has the same pose as the last timed one -- the six elements it misses on main_menu, and the bracket it drops. That closes an open question ui-paint-order-key.md has carried for a while about ptframe1 and ptframe2 resting at alpha 0 while the capture shows the frame plainly. Same two elements, same cause. Not fixed yet; the change is in ui_layout's rest(). And a METHOD line I would not have written myself: two renderers agreeing is not evidence the field is right. Their composite and screen render matched to 3/255 on main_menu and both omitted two elements the game draws, because both read one field through one decoder.
17 KiB
Which GP_TITLE build is which screen — measured against the running game
Status: ✅ CONFIRMED for the four screens the boot path actually shows
(title art, PRESS Ⓐ BUTTON, main menu, EXTRAS); 🟡 PROBABLE for their
Japanese twins; ❔ open for the two DELTASABER plates.
Answers MISSION Q2. The previous statement — "build 4
title, 5 main menu, 6/8/9 submenus" — is partly wrong and is withdrawn:
build 8 is the Japanese main menu, not a submenu, and GP_TITLE holds
exactly one submenu (EXTRAS), in two languages.
The archive is eight screens, each shipped twice
GP_TITLE.pak has 16 entries; sylpheed-cli screen list calls 12 of them
composable builds. The 16 fall into eight pairs, and each pair's two members
have near-identical sizes and name hashes that differ by a constant — one
character of the name apart:
| entry | hash | bytes | build idx | pair |
|---|---|---|---|---|
| 0 | 01a2db9c |
483 958 | 0 | A |
| 1 | 0ff0b8a8 |
483 958 | 1 | A |
| 2 | 285d8849 |
267 014 | 2 | B |
| 3 | 369773cb |
267 014 | 3 | B |
| 4 | a60fcb85 |
12 278 666 | 4 | C |
| 7 | b483e6e6 |
13 363 328 | 7 | C |
| 5 | a715f485 |
6 977 437 | 5 | D |
| 8 | b58a0fe6 |
6 931 653 | 8 | D |
| 6 | a81c1d85 |
6 549 126 | 6 | E |
| 9 | b69038e6 |
6 548 438 | 9 | E |
| 10 | cdba806e |
426 473 | — | F |
| 13 | db2ea1f8 |
423 333 | — | F |
| 11 | cec0a96e |
999 643 | — | G |
| 14 | dc34caf8 |
999 643 | — | G |
| 12 | cf2a8ccd |
1 774 639 | 10 | H |
| 15 | dd56d99b |
1 774 639 | 11 | H |
For the three pairs whose members differ visibly — C, D, E — the difference is
English versus Japanese: build 7 is the title art with the katakana subtitle
プロジェクト シルフィード, build 8 the main menu reading 新規 / ロード /
チュートリアル / オプション / エクストラ, build 9 the EXTRAS submenu as
エクストラ. That is the whole of the language split we can see. In pairs A, B and
H the two members render byte-identical PNGs — the archive still carries two
copies, but the artwork does not change with the language.
Pairs F and G are the four entries screen list does not classify as builds by
default. They are the developer splash, and they render — see below.
The map
Contact sheet of every render:
captures/title-builds/title-build-contact-sheet.png.
| build | what it is | confirmed how |
|---|---|---|
| 0, 1 | a DELTASABER / SYLPHEED A.I. plate low-left on black, no background |
❔ not observed running. Never seen in the boot path, the main menu, EXTRAS or MISSION SELECT |
| 2, 3 | the PRESS Ⓐ BUTTON plate — an overlay build of its own, not a state of build 4 |
✅ seen composited over build 4 on the live title, at the same rect our render puts it |
| 4 | title art, English (PROJECT SYLPHEED, ™, (C)2006,2007 SQUARE ENIX) |
✅ live-title-press-a.png |
| 7 | the same, Japanese | 🟡 renders as the JP twin of build 4; the container runs an English locale, so it was not seen |
| 5 | main menu, English: NEW GAME / LOAD GAME / TUTORIAL / OPTIONS / EXTRAS, footer Ⓐ : OK |
✅ live-main-menu.png — element for element |
| 8 | the same, Japanese | 🟡 as above |
| 6 | the EXTRAS submenu, English: MISSION SELECT / MOVIE THEATER / BACK, footer Ⓐ : OK Ⓑ : Back |
✅ live-extras.png |
| 9 | the same, Japanese | 🟡 as above |
| 10, 11 | the same DELTASABER plate as build 0, over a dark circuit-line background |
❔ not observed running |
✅ The splash — the four "non-build" entries, rendered
screen list --all widens the enumeration to every composable bundle and shows
all 16 entries. The four that the default listing drops are the two halves of
the developer splash, each shipped twice:
| entry | elements / sprites | what it is |
|---|---|---|
| 10, 13 | 3 / 2 | the white SQUARE ENIX publisher logo |
| 11, 14 | 7 / 6 | GAME ARTS / SETA / studio anima — the developer logos |
splash-entries-rendered.png.
Rendered with screen render --all --primitives --black. Entry 11's seven
elements are the three logos, their three _eff glows and the
palogo_eff0.prm black backdrop — exactly the composition
structures/ui-paint-order-key.md measured
for the splash.
✅ Confirmed against the running game — 2026-08-28
The 🟡 above ("no framebuffer capture to diff against") is closed. Recording the
boot from the moment the window appears, at 2 fps, catches the splash before the
movie:
live-splash-publisher.png,
live-splash-developer.png.
Edge-correlated against the renders, with the other half as a negative control:
| capture | vs entry 10 | vs entry 11 |
|---|---|---|
| publisher frame (t ≈ 2.0 s) | 0.9146 @ (0,0) | 0.027 ✗ |
| developer frame (t ≈ 6.0 s) | −0.033 ✗ | 0.9792 @ (0,0) |
Both halves match their own render at zero shift and are firmly rejected by the
other. The 13/14 twins score 0.876 / 0.966 — near-identical artwork, so this
test cannot tell a pair apart, only a screen from a different screen.
✅ The splash's timing is DECODED, and the capture confirms it
Re-recorded at 10 fps (the 2 fps pass below was ±0.5 s and could not see ramps at all). The splash fades, both ways — it does not cut — and the bundle's own keyframes say so:
$ sylpheed-cli screen info --all --build 10 GP_TITLE.pak
1 palogo_sqex.t32 7 kf [15 30 235 239 251 255 -]
2 palogo_sqex_eff.t32 4 kf [15 30 45 -] (the glow, child of 1)
$ ... --build 11
1 palogo_gamearts.t32 7 kf [15 30 190 194 206 210 -] (seta, anima identical)
2 palogo_gamearts_eff 4 kf [15 30 45 -]
Under Q1's 1 unit = 1/60 s:
| declared | measured at 10 fps | |
|---|---|---|
SQUARE ENIX ramp in |
15 → 30 = 0.25 s |
rise 0.4 → 0.8 s |
SQUARE ENIX hold |
30 → 235 = 3.42 s |
≈ 3.5 s (0.8 → 4.3 s) |
SQUARE ENIX fade out |
235 → 255 = 0.33 s |
≈ 0.3 s (4.4 → 4.7 s) |
| developer hold | 30 → 190 = 2.67 s |
≈ 2.4 s (5.6 → 8.0 s) |
| developer fade out | 190 → 210 = 0.33 s |
≈ 0.3 s (8.1 → 8.4 s) |
The offset between declared and measured start is ≈ 0.35 s, which is simply that
the recording's t = 0 is when the window appears, not when the guest starts
drawing. Everything downstream of that lines up.
The overshoot is the glow. The measured rise peaks (6.21) at 0.8 s and settles
back (5.39) by 1.1 s, which looks like a bloom. It is the _eff child element:
its keyframes are 15 → 30 → 45, so it ramps in after the logo and then back
down, while the logo itself holds. Decoded, not a rendering artifact.
So the port can read the splash's timing off the disc rather than author it — the first screen's animation is not a measurement it has to trust.
The wall-clock sequence, for orientation
SQUARE ENIX on screen |
≈ 0.5 → 4.0 s after the window appears |
| black | ≈ 4.5 s |
GAME ARTS / SETA / studio anima |
≈ 5.0 → 7.5 s |
| black | ≈ 9.0 s |
ADV.wmv begins |
≈ 9.5 s |
⚠️ The frames at ≈ 9.5–12.5 s show SQUARE ENIX again in cyan. That is not a
third splash — it is the intro movie's own opening, which the milestone-2 notes
describe as "white SQUARE ENIX + cyan glow + red diamonds". A capture-only reading
would have recorded a third logo screen that does not exist.
So the first of the five screens now has a reference composite, a framebuffer capture, and its on-screen durations.
Reach of the two negatives. Builds 0/1 and 10/11 were looked for in: the whole
boot sequence (a 5 s-cadence filmstrip from launch to the title, ~190 s), the
title, the main menu, the EXTRAS submenu, the LOAD GAME slot list, the
transition into MISSION SELECT (a 40-frame burst), and the attract cycle. They
appear in none of them. The obvious remaining candidate is a long load — a
mission launch — which is out of this objective's scope; they are most likely a
loading/AI-chatter plate. That is a hypothesis, not a result.
Three things the captures settle beyond the map
The live title is two builds composited. Build 4 draws the art; build 2 draws
PRESS Ⓐ BUTTON on top, and it fades in a beat later — a screenshot taken
2.5 s after arriving at the title has the art and no plate, one taken ~1 s later
has both. The port must treat the plate as its own timed element.
The attract-loop title carries the plate too. After ~8–10 s idle the title
fades to black, a full-motion video plays for ~85 s, and the title comes back —
with PRESS Ⓐ BUTTON
(live-attract-title-press-a-band.png).
This is consistent with, and adds nothing to, the draw-quad comparison in
canary-scripted-input-traps.md: the plate is
not the tell that distinguishes the boot title from the attract title.
EXTRAS is the only main-menu destination inside GP_TITLE. Ⓐ on EXTRAS
opens build 6 — measured. The other four destinations leave the archive: Ⓐ on
LOAD GAME opened a LOAD GAME slot list, and Ⓐ on MISSION SELECT inside
EXTRAS opened a MISSION SELECT screen, neither of which is a GP_TITLE
build. dat/ carries GP_SAVE_LOAD.pak, GP_TUTORIAL.pak, GP_OPTIONS.pak,
GP_MISSION_SELECT.pak and GP_MOVIE_THEATER.pak; that those are the archives
behind the other four buttons is an inference from the names, not a measurement.
How to reproduce
sylpheed-cli screen list "$SYLPHEED_DISC/dat/GP_TITLE.pak"
sylpheed-cli screen render --build 6 "$SYLPHEED_DISC/dat/GP_TITLE.pak" /tmp/b6.png
tools/re-capture/boot_menu.sh q2 # boots to the main menu, cursor on NEW GAME
tools/re-capture/pad.py dpad down 0.35 # x4 -> EXTRAS
tools/re-capture/pad.py tap A 0.30
Mind the d-pad hold — see METHOD.md.
✅ The title is not a still image — it loops, ≈ 2.2 s
Recording the title at 10 fps for 22 s shows the screen never settles. After the build-in it oscillates by about ±0.5 in mean luminance, continuously:
peaks at 5.6 7.8 10.0 12.7 15.2 17.1 19.2 21.3 s
intervals 2.2 2.2 2.7 2.5 1.9 2.1 2.1
mean 2.24 s
measured, n = 7 intervals, spread 1.9–2.7 s — peak-picking a low-amplitude signal is coarse, so read it as ≈ 2.2 s ± 0.4, not a precise period.
The mechanism is already decoded: build 4 declares ptloop01.rat /
ptloop02.rat, and loop*.rat is a looping sprite animation rather than a
composition (INDEX.md, UI screen layout row). So the title carries a
looping element by construction; what is new is that it runs at ≈ 2.2 s and never
stops.
✅ The loop records ARE decoded — and they are not what I measured
ptloop01.rat is an opt -linked leaf record: in build 4 the chunk opt
(size 0x0c) carries the name, immediately followed by a RATC blob at
0xbb5966 (ptloop02.rat the same at 0xbb5a82). Its pivot fields read
200/90, matching screen info's pivot (200,90) — the right blob.
The keyframes use the ordinary 40-byte block layout, starting at +0x68:
ptloop01 → pteff03.t32 |
ptloop02 → pteff03a.t32 |
|
|---|---|---|
| kf0 | t=150 x=−639 α=ff |
t=150 x=1721 α=00 |
| kf1 | t=540 x=−39 α=80 |
t=630 x=1111 α=80 |
| kf2 | t=600 x=1521 α=ff |
t=720 x=−839 α=ff |
| scale | 100 × 600 | 100 × 800 |
| span | 150 → 600 = 450 units = 7.5 s | 150 → 720 = 570 units = 9.5 s |
Y is constant at 270 and X runs off one edge to the other, so these are
horizontal light sweeps — loop01 left → right, loop02 right → left.
🔴 Two things I wrote last iteration are wrong
1. "A leaf record's keyframes are not in the build's 40-byte layout."
Withdrawn — they are, exactly. The scan that "found nothing" demanded 29
strictly-increasing times because I read the word at +0x004 (0x001e0000) as a
keyframe count. These records hold three keyframes. A filter that hard-codes
the expected count rejects the right structure; whatever the 30 is, it is not
the number of keyframes here.
2. "The ≈ 2.2 s oscillation is the ptloop elements." Withdrawn — I asserted
the link because build 4 declares those elements, not because anything showed it.
The decoded sweeps run 7.5 s and 9.5 s. A 22 s capture would show ~3 peaks
from a 7.5 s cycle; it showed 8. So the loops are not what the oscillation
measured.
✅ Identified: it is the PRESS Ⓐ BUTTON plate pulsing
A per-tile amplitude map over the capture (8 × 6 grid, 18 s after build-in) localises the 2.3 s period precisely:
| region | sd | dominant lag |
|---|---|---|
| band x ≈ 318–954, y ≈ 560–672 | 7.65 | 2.3 s |
| wordmark centre | 0.06 | — |
| bottom-right corner | 0.003 | — |
That band is the PRESS Ⓐ BUTTON plate's rest position (ptbtn00.rat, rest
(383,550), pivot (256,25)). It is build 2, composited over the title — not
build 4.
Decoding ptbtn00f.rat, the plate's highlight variant, gives the pulse directly:
| kf | t | alpha |
|---|---|---|
| 0 | 6 | 0x00 |
| 1 | 29 | 0x06 |
| 2 | 35 | 0x4a |
| 3 | 50 | 0x50 |
| 4 | 58 | 0x50 (hold) |
| 5 | 97 | 0x4a |
| 6 | 105 | 0x06 |
A glow that fades in to 0x50 and back out — exactly a "press start" pulse.
There is an eighth keyframe: fade 0x00ffffff at the same position — the glow
returns to fully transparent, so this is a closed cycle, not a one-shot ramp.
🟡 The cycle length is still not readable — and now that is an observation.
The eighth block's time slot contains the four bytes end , the record's ASCII
terminator: the record simply stops there and the value does not exist. So the
corpus's "a group's last block has no time of its own" rule holds here in a second
form — not the next group's index, but the chunk terminator.
Declared span is ≥ 105 units = 1.75 s; measured ≈ 2.3 s (≈ 138 units), which would need a final step of ≈ 33 units. That 33 is fitted to the measurement, not read from the file, and is recorded only so nobody re-derives it as if it were a decode.
❔ The word at +0x004 is not a keyframe count. It reads 0x003c0000 (60)
here with 8 keyframes, and 0x001e0000 (30) in the loop records with 3. Whatever
it is, it is not the count, and it is not decoded.
❔ The declared 4.08 s build-in was not tested
That was the intent of this recording and it did not work. The title was reached
by skipping the movie with Ⓐ, which cuts to black and brings the title up on a
path that may not be the normal one; and the visible rise (≈ 2.7 s, from t ≈ 0.8
to 3.5) is a luminance curve, which
screen-transitions.md already establishes is not
the fade quad's ramp. So ≈ 2.7 s neither confirms nor contradicts build 4's
declared 16 → 261 (4.08 s); the two are not measuring the same thing.
Testing it properly needs the title reached without a skip, and a way to separate the quad from the elements — neither of which this recording had.
✅ For the port: build 4 alone, and groups HOLD rather than loop
Both answers the port agent asked for, in one recording.
The capture — the title with no PRESS Ⓐ plate over it
Ⓑ from the main menu returns to the title and the plate fades in a beat later, which opens a clean window. Recorded at 20 fps from the press:
| title art appears | t ≈ 1.10 s |
| builds in | 1.10 → 3.70 s (mean 41.8 → 63.2) |
| settled, still no plate | 3.70 → 5.00 s |
| plate arrives | t ≈ 5.10 s (band jumps 282 → 3 755 bright px) |
live-title-build4-no-plate.png
is t = 4.0 s — build 4, settled, unobstructed. That is the reference for the
washed-out cyan glow slab the port reports drawing and the game not having.
✅ A keyframe group HOLDS at its last keyframe — it does not loop
This follows from the decoded sweeps plus a measurement, and the two agree:
ptloop01.rat's final keyframe putspteff03.t32at x = 1521 andptloop02.rat's putspteff03a.t32at x = −839 — both off-screen on a 1280-wide design. A group that holds therefore parks both sweep sprites out of view and nothing moves after the build-in.- Measured: over 18 s of settled title the centre tiles sit at sd ≤ 0.01 (per-tile map above). A looping group would recross the screen every 7.5 s and be unmissable.
So the name loop*.rat is misleading — in this build the records animate once
during the build-in and then rest off-screen. 🟡 This is about these groups on
this screen; nothing here says no group anywhere loops.