# Which movie plays where — the boot intro, the attract loop, the new-game intro **Status:** ✅ `CONFIRMED`. The bindings are **decoded** from the movie manifest, and the attract movie is independently **measured** from captured frames. One part — whether playback is skippable — is 🟡 and the corpus contradicts itself about it; that is written down rather than resolved by assertion. Answers [MISSION Q9](../port/MISSION.md), and contributes to Q6. ## The manifest names the boot-side slots — decoded The movie manifest (`dat/tables.pak` entry `0x5b983a08`, schema `0x067025b9`, [`movie_manifest.rs`](../../crates/sylpheed-formats/src/movie_manifest.rs)) is an array of slots whose **key is the semantic role**, with a parallel array of value records in the same order. Its first eight slots are the whole boot-side flow: | slot key | movie | also bound | |---|---|---| | `LOGO1` … `LOGO4` | `logo1.wmv` … `logo4.wmv` | — | | **`ADVERTISE_MOVIE`** | **`ADV.wmv`** | `VOICE_ADV` | | `STAFF_ROLL` | `SYLPH_HD720p_8M-CBR_2ch.wmv` | subtitle table | | **`MS00A`** | **`S00A.wmv`** | `SUBTITLE_S00A`, `VOICE_S00A`, a `pwterop_s01a.prt` overlay | | `MS01A` | `S01A.wmv` | `SUBTITLE_S01A`, `VOICE_S01A` | The alignment is not in doubt here even though the manifest has valueless slots elsewhere: `logo1..4` zip 1:1 onto `LOGO1..4`, and `MS00A`→`S00A.wmv`, `MS01A`→`S01A.wmv` are the manifest's own anchor rule. **The `logo1`–`logo4` slots are bound to `.wmv` files that are not on the disc** — already established, and the reason the developer splash is a screen, not a video. ## ✅ The boot intro and the attract movie are the same asset There is **no separate boot-intro slot**. `ADV.wmv` is bound to `ADVERTISE_MOVIE` — it *is* the advertise movie, and the boot simply plays it first. For the port that means one video, not two. ### Measured independently, from captured frames Frames captured 5 s apart during an attract cycle were matched against five candidate movies by frame signature (32×18 normalised grayscale, movie frames cropped to the 675 of 720 rows the game surface shows, 1 fps sampling). `tools/re-capture/frame_match.py`; full table in [`data/attract-frame-match.txt`](data/attract-frame-match.txt). **15 of 19 attract frames matched `ADV.wmv`, and the matched timestamps advance monotonically at the sampling rate** — 39, 45, 56, 62, 75, 80, 85, 92, 102, 108, 113, 119, 131, 137 s — ending at 137 s, which is `ADV.wmv`'s full length, after which the title returned. That is not a similarity score, it is a playhead. **The control was run first and behaves the same way.** Frames captured during the *boot* movie — known to be `ADV.wmv` — matched `ADV` at 116, 121, 129, 134 s. Its failure mode is worth stating: on near-black frames the correlation collapses (one control frame scored 0.000, another tied `S13A` 0.984 against `ADV` 0.926). Those are exactly the 4 attract frames that did not match. **A dark frame carries no signature; it is not evidence for the runner-up.** ### 🔴 This corrects an earlier claim of mine Two iterations ago I recorded the attract movie as "≈85 s, so probably not `ADV.wmv`'s 137 s". That was wrong, and the mistake was arithmetic on an unobserved start: my sampling began when the movie was already **39 s in**, so what I timed was the *tail* of it, not the whole thing. ## ✅ The new-game intro is `S00A.wmv` Slot `MS00A` — the prologue story intro, 93.87 s, with its own subtitle table, `VOICE_S00A`, and a text overlay. Decoded from the manifest, **not** measured: Ⓐ on `NEW GAME` hangs the emulator ([`menu-navigation-semantics.md`](menu-navigation-semantics.md)), so this binding has not been watched happening. ## 🟡 Skippable — the corpus contradicts itself, and I did not settle it * [`canary-scripted-input-traps.md`](canary-scripted-input-traps.md) states plainly that "Ⓐ during a movie skips the movie, every time". * But `boot_menu.sh` / `skip_intro.sh` as they stand **deliberately do not tap during a movie**, logging `movie … -> waiting it out (tapping breaks the title)`, and the same document records run G: 88 Ⓐ presses through the boot left a permanent black screen. Both cannot be the whole story. **The test**: boot, tap Ⓐ exactly once well inside the movie, and record whether the title arrives early. One boot, and it was not run this iteration. ## ✅ What ends the attract movie Nothing intervenes: it **plays to its end**. The last matched frame is `ADV` at 137 s — the file's full duration — and the title is back on the next sample. So the attract cycle is: title, idle ~8–10 s, fade to black, `ADV.wmv` in full, back to the title (which redraws `PRESS Ⓐ BUTTON`). ## What this contributes to Q6 The manifest is **data the game reads** to sequence the boot side: the slot keys are in play order and the key *is* the role. That is not the whole driver — it says what plays, not what decides to advance — but it is the first file-side piece of Q6's second half, and it means the boot-side asset order does not have to be authored. ## ✅ Skippable — settled 2026-08-28: **one Ⓐ skips the movie** The test named above was run, and the answer is unambiguous. | | | |---|---| | baseline: title arrives with **no** input | ~193 s, ~196 s, ~193 s (three boots) | | **one Ⓐ tapped at ~45 s into the boot** | **title at ~57 s** | The press is provably the cause and provably singular: Canary's own `[RE-INPUT] XamInputGetKeystrokeEx reached the driver` counter went **3 → 4** across the tap, so exactly one keystroke was delivered, and the title arrived ~12 s later instead of ~150 s later. **And the skipped-to title is fully functional**, which is the part that matters for the harness folklore: it draws the `PRESS Ⓐ BUTTON` plate (2 408 plate pixels by the same probe used elsewhere), and a second Ⓐ opened the main menu normally ([`title-after-single-A-skip.png`](captures/newgame-path/title-after-single-A-skip.png)). ### So what is `skip_intro.sh` protecting against? Not a single tap. The failure recorded in [`canary-scripted-input-traps.md`](canary-scripted-input-traps.md) is run G — **88 presses at 4 s intervals through the whole boot** — which left a permanent black screen. Hammering breaks it; one press does exactly what the button is for. The scripts' `waiting it out (tapping breaks the title)` comment is **too broad**, and it costs every scripted boot ~2.5 minutes. ## ✅ `S00A.wmv` watched — measured 2026-08-28 The manifest's `MS00A → S00A.wmv` has now been confirmed against the running game. The first attempt, with 5-second screenshots, gave an ambiguous partial playhead; re-run with **`ffmpeg x11grab` at 10 fps** and matched every 0.5 s, it is unambiguous: | capture t | `S00A` score @ playhead | `ADV` (runner-up) | |---|---|---| | 5.0 s | **0.998** @ 1.0 s | 0.787 @ 126.5 s | | 6.0 s | **0.999** @ 1.5 s | 0.820 @ 126.5 s | | 7.5 s | **1.000** @ 3.0 s | 0.836 @ 126.5 s | | 9.0 s | **0.999** @ 4.5 s | 0.823 @ 126.5 s | | 12.0 s | **0.998** @ 7.0 s | 0.985 @ 34.5 s | | 16.0 s | **0.999** @ 10.0 s | 0.886 @ 37.5 s | | 17.5 s | **0.967** @ 11.0 s | 0.460 @ 87.0 s | Across the 25 consecutive samples from capture 5.0 s to 17.5 s the `S00A` playhead is **strictly non-decreasing** — 1.0, 1.5, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 5.5, 6.0, 6.5, 7.0, 7.0, 7.5, 8.0, 8.5, 9.0, 9.0, 9.5, 10.0, 10.5, 11.0 — advancing at essentially real time, with scores at or above 0.96. **`S00A` is the top match on 23 of the 27 frames that carry signal** (contrast > 35; the other 25 of 52 frames are the transition and are correctly ignored). So the new-game intro is `S00A.wmv`: **decoded** from the manifest and now **measured** off the game. It begins ~4.5 s after Ⓐ on the save slot. ### 🟡 An aside worth recording: `ADV.wmv` reuses `S00A` footage In the window `S00A` 5.5–10 s, `ADV` also scores 0.97–0.99 — at its *own* monotonically advancing playhead, 33.5–37.5 s. Two different movies both matching strongly with two consistent playheads is not noise; it reads as **the boot movie being a trailer cut from the story cutscenes**, `S00A` among them. That would explain why the sparse first attempt kept flipping between them. Not investigated further. ### ⚠️ Sparse sampling was the whole problem The earlier attempt sampled every 5 s and produced contrast 23–37 frames, a playhead that would not join up, and one high-contrast frame preferring `ADV`. The same question at 0.5 s spacing answers itself at 0.999. **The movie was never ambiguous; the sampling was.** ### The run was killed before the mission load An earlier run of this path disappeared at ~145 s with **no crash line in its own log** — routine `MEM-WATCH rss=1153MB` to the end — so an external kill, not a guest fault, and the second this session. The `DELTASABER` plates of [`ui-title-build-map.md`](ui-title-build-map.md) need a mission load and were not reached.