Files
Sylpheed/docs/game/navigation.md
sylph-decoder 5a49511952 re: ptloop01/02 do not free-run on the settled title -- and the menu is not settled
sylpheed-port found ptloop01/02 free-running in their renderer on the menu path,
pinned them, and was explicit that pinning picks one pose rather than the game's:
"a capture question, not a harness one". It is, and it lands in my lane.

On the title it is now answered. Those leaves rest at (441,270) 200x90, INSIDE
the box the ptlogo_eff3 era adjudication uses, and across my two JP captures from
different sessions they are byte-identical: 0 of 18 000 px, max |d| 0, against a
whole-frame contrast of 116 492 px differing. So they are static at rest, and the
in-box between-session noise of 0.32 is not theirs -- the 645 differing pixels
all lie in a 30-row band at y 99..128, nowhere near the loop rect. That also
closes the reach caveat on the EN->JP noise transfer.

The MENU is a different bundle and is not settled. Build 5 declares the same rect
with a single static keyframe, and that is where their row drifted.
menu_loop_rest.sh was written to capture five settled menu frames and diff the
rect; it did not complete. The run reached a title at t=146 s and (A) did not
take across six attempts -- the documented intermittency where the attract loop's
title accepts nothing, unlike the boot title. Recorded rather than re-rolled.

Two committed main-menu captures cannot substitute: they differ across 57 % of
the surface (different geometries and capture paths), so the 88 % differing on
the loop rect measures the mismatch, not the loops. The control fails and the
comparison is void.

navigation.md gains the trap that cost this iteration a run: kill -9 on xenia
orphans /tmp/xenia-canary.lock, the next run-canary refuses to STDERR where a
polling script never looks, and a probe then sampled a dead display for 484 s
reporting `other` every 4 s -- because screen_id.py on an empty screen returns
`other` and "not the title yet" is indistinguishable from "there is no emulator".
Kill plainly so it clears its own lock, and assert the emulator is alive before
entering any wait loop.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 15:43:29 +00:00

17 KiB
Raw Blame History

Playing the game: every screen, and how you move through it

Written from the player's chair. What is on screen, what you press, what happens. This is the document you would hand someone who has never seen the game and wants to reach a mission — or who needs to script that journey.

Internal names (ptbtn03, GP_LOAD, build numbers) appear only as footnotes, because they are how we find things, not what the game shows anyone.

Status: filling in. §1§4 now carry what the committed oracle frames actually show; what is still is what no capture answers. This page exists to be filled in by playing, not to look finished.

⚠️ Fill this in from the real game

The oracle is Xenia Canary running the actual title, captured. Not sylpheed-cli, not the Explorer, not any renderer of ours — those are tools for verifying our decoding, they are hypotheses under test, and they have been wrong. A row here with no capture behind it is a guess wearing a table cell.

Describe what you saw. "The cursor starts on the second item" is worth more than any amount of reasoning about the layout data.

Confidence: seen in a capture · 🟡 inferred · unknown.


1. From power-on to the main menu

# What you see What you do What happens
1 SQUARE ENIX in white on black, the two dots in red, after it nothing fades on to the next logo
2 GAME ARTS, SETA and studio anima stacked on black nothing fades on into the cinematic
3 The opening cinematic skips it ends into the title
4 Title screen — the wordmark appears first, with no prompt; PRESS Ⓐ BUTTON fades in 2.13 s later, above the 2006/2007 Square Enix copyright line, and then pulses about every 2.2 s press goes to the main menu
5 Main menu see §2

The order is publisher then developer, confirmed in three cold boots (2026-08-29)SQUARE ENIX for ~4.3 s, a ~0.25 s black hold, then GAME ARTS / SETA / studio anima for ~3.5 s, and both dwells are declared on the disc (240 and 195 keyframe units). ⚠️ There is a third SQUARE ENIX wordmark about ten seconds in — bloomed, below centre — and it is the opening card of the intro movie, not a splash. the three frames side by side · boot-order-and-splash-dwell.md

Both logo screens are still pictures the game draws, not video — neither is a .wmv on the disc. Captures: publisher · developer · title.

⚠️ One Ⓐ skips the cinematic, and it is worth a lot of time: the title arrived at 57 s with the skip against 193 s without it .

⚠️ The title screen has two states that look identical. The one that ends the boot accepts Ⓐ. The one the attract loop returns to, after the game has sat untouched and looped back, accepts nothing — Ⓐ, START, B, BACK, X, Y, dozens of presses, no response. Nothing on screen distinguishes them . If you are scripting: use the first title after boot, and do not press anything during the boot.

⚠️ The title is not input-ready for about ten seconds after it appears . And even then Ⓐ registers roughly half the time, with nothing yet found that predicts which — budget retries. 🔴 Refutation attempt, 2026-08-29 — both halves of that came out wrong on the runs I could test. Two boots, Ⓐ pressed 7.29 s and 7.28 s after the title art settled (5.15 s and 5.15 s after the prompt appeared): accepted both times, first press, no retry, and each went straight on to the main menu. Ⓑ on the menu was then also accepted first press, both runs. ⚠️ Reach: n = 2, so "half the time" is only made unlikely (2/2 has p ≈ 0.25 under it), not excluded — but "not input-ready for about ten seconds" is contradicted outright, because 7.3 s worked twice. Keep the retry budget; drop the ten-second wait. Evidence: run 1 · run 2 · title-plate-delay-measured.md.

⚠️ The prompt takes 2.13 s to arrive, measured twice (2.138 s / 2.132 s). Timed from the moment the wordmark stops animating, not from the moment it first appears — the build-in itself varies by half a second between runs.


2. Main menu

Five options in a vertical stack, roughly centred, with a highlighted state on the focused one.

The focused option carries a small ring to the left of its label, and the ring turns — continuously, about once every 2.2 s. It has a bright head, so you can see it go round. It is the only thing moving on this screen once it has settled: the labels, the bracket and the footer are all completely still (temporal std exactly 0.000 over 20 s). Ⓑ five frames, 4 s apart · the measurement

position label what it opens
1 NEW GAME a DIFFICULTY prompt, then SELECT DATA
2 LOAD GAME the save-slot list
3 TUTORIAL the lesson list
4 OPTIONS the settings menu
5 EXTRAS a three-item submenu

Read off live-main-menu.png; destinations off q4-destinations.png and newgame-difficulty.png.

The screen is the title art gone dim, with the wordmark ghosted behind the list and a bracket of glowing rule-lines drawn around it. The focused item is bright white with a spinning ring to its left; the others are dim blue. Every item carries a small dot-in-circle at the left end of its underline — that is on all five all the time and is not the cursor.

Moving around

you press what happens
⬆ / ⬇ one item, and it wraps at both ends
⬅ / ➡ nothing
opens the focused item
🟡 back to the title — see the warning below

Which item is focused when the menu opens is not fixed. Four boots of the same harness opened on TUTORIAL, TUTORIAL, NEW GAME, NEW GAME. Do not assume the top item, and do not assume the middle one either.

⚠️ The main menu is the one screen whose footer does not offer Ⓑ. It reads ⊙ : Select Ⓐ : OK — every submenu adds Ⓑ : Back. Measured: zero red-Ⓑ glyph pixels anywhere in the frame, on two captures, with the same detector finding the glyph on EXTRAS and DIFFICULTY . But Ⓑ does leave it, and the objection that stood here is refuted (2026-08-29). This page used to say the title "returns on its own after ~810 s idle", so an observer could not tell Ⓑ from the timer. That timer belongs to the title, not to this screen: the main menu was held untouched for ≥ 60 s and never moved. Ⓑ is delivered and is the only input in ≥ 100 s before the return, so the ordering is measured — the latency is not (the measurement).

Internals: GP_TITLE.pak build 5; buttons ptbtn01ptbtn05 top to bottom.


3. The rest of the menus

One section each, in the shape of §2: what is on screen, what the cursor does, what each choice leads to, and what a wrong choice shows you.

New game

Ⓐ on NEW GAME does not start a mission. It opens DIFFICULTYEASY / NORMAL / HARD / BACK, opening focused on NORMAL — and Ⓐ there opens SELECT DATA, a save-slot picker headed Current Storage: Dummy HDD that asks you to choose a file for the auto-save. Pick one and a movie plays . DIFFICULTY

Load game

A vertical list of numbered slots, 8 rows visible, scrolling as a carousel — one capture shows the order 19, 20, 01, 02, 03, 04 with 01 focused, so the list runs past the end and back round to the start . Each row shows Difficulty, Flight Time and Clear Ratio; a Details panel to the right gives STAGE, Game Status, Points and Times Cleared, and an empty slot leaves every one of those blank . Current Storage: Dummy HDD sits along the top.

Its footer offers more than the other menus: ⊙ : Select Ⓐ : OK Ⓑ : Back Ⓧ : Delete Ⓨ : Select Storage . capture (left panel)

Still open: the overwrite / delete confirmation, and where its cursor starts.

Known: title → LOAD GAME → slot 01 → YES → READY ROOM → TAKE OFF reaches flight .

Tutorial

A list of lessons in two headed groups, with a one-line description shown on the left for whichever is focused — e.g. BASIC CONTROLS reads "Learn how to move and attack". Opens focused on the first entry.

group lessons
Level 1 BASIC CONTROLS, HEADS-UP DISPLAY, RADAR
Level 2 SUPPLY AND SPECIAL MOVES, RADIO ORDERS, ADVANCED CONTROLS
BACK

capture (middle panel)

Options (one level in)

GAME SETTINGS · CONTROL SETTINGS · SOUND SETTINGS · SCREEN SETTINGS · BACK, opening focused on the first . capture (right panel)

Still open: what is inside each of the four, what each setting ranges over, and whether a change needs confirming.

Extras

Three items: MISSION SELECT · MOVIE THEATER · BACK, opening focused on MISSION SELECT . The cursor wraps here too — it is a menu rule, not a per-screen one . capture

MOVIE THEATER has never been opened.

Mission select — and the "stuck cursor" is explained

The stage list on the left (8 rows visible of 16, with a scrollbar), a detail panel showing the stage's name, a picture, High Score and Best Time, and a Wide Area Space Map on the right with the named systems on it. The chosen difficulty is printed top-right. Footer: ⊙ : Select Ⓐ : OK Ⓑ : Back Ⓨ : Difficulty .

⚠️ "Stage select would not move" — sixteen d-pad presses never left Stage 01 — is now explained: the other fifteen stages were LOCKED . A locked row is drawn dimmer than an unfocused one: measured, the labels sit at three distinct brightnesses — focused 254, unlocked 183, locked 104 — and on a save with the story unlocked the same rows read 183, with the cursor able to reach Stage16 at the bottom of the scrolled list. the measurement · locked · unlocked · at Stage16

So: if you are scripting a run, check what the save has unlocked before concluding the list is broken. Whether the list wraps past Stage16, and whether a locked row is skipped or simply unreachable, is not settled.

Briefing and Ready Room

What you read, what you choose, and what finally launches the mission.

Hangar / Arsenal

How a weapon is fitted, how one is bought, what a purchase prompt says.


4. Prompts, confirmations and alerts

The interrupting layer — and the thing most likely to break a scripted run, because it looks like a menu and does not behave like one.

prompt when where the cursor starts notes
Save game? after a mission YES
Do you want to develop this weapon? Arsenal, on purchase
overwrite / delete confirmation saving, loading
"not enough points" or similar refusal Arsenal does it need dismissing

⚠️ A short d-pad tap is ignored inside a prompt. Sixty milliseconds moves the cursor on a menu and does nothing in a dialog . So a script that works through the menus will silently accept the default in every prompt it meets — which is how you end up overwriting a save you meant to keep. Confirm which side the cursor is on before pressing Ⓐ.


4b. What a screen change looks like measured, three of them

Every screen carries a full-screen black quad (pteff00.prm) that paints last. A screen change is that quad ramping to opaque on the way out, and the incoming screen's own copy of it starting opaque and clearing on the way in — so a transition is two screens' quads, not one shared effect. The outgoing ramp's length is on the disc and matches the game three for three; the black between them does not, and is not a constant.

you press going outgoing ramp black between incoming clears over
main menu → title 5 frames none — they cross-fade 8 frames
title → main menu 4 frames ~3 frames 5 frames
EXTRAS → main menu 5 frames 2 frames, fully blank 5 frames

⚠️ Ⓑ is not "the cancel animation". Ⓑ out of the main menu cross-fades — the title is already drawing while the menu is still fading — while Ⓑ out of EXTRAS goes properly black first. Same button, two different-looking moves, and if you are scripting against "the screen goes black" one of them will not do it.

⚠️ Ⓐ off the title is slow to start. About 25 rendered frames (~0.8 s) pass between a delivered press and anything changing on screen; the other two start immediately. A script that presses and then looks 0.5 s later sees the title still up and can conclude the press was dropped.

Timings are in rendered frames at ~30 Hz, from the emulator's own draw stream, so they do not stretch when the emulator runs slow — screen-transitions.md · data/fade-three-transitions.txt.

5. Flying

Not started, and the game teaches it better than we could: play the in-game tutorials and write down what they say. They are the game's own explanation of its controls, which is exactly the document we want.

To fill in: the control map, and whether there is more than one scheme · throttle and boost · targeting — ⚠️ target select is Ⓐ pressed twice; a sweep that only ever tapped once concluded targeting was automatic, and was wrong · switching weapons · the pause menu and what it offers · what the HUD tells you, element by element · how a mission ends, win or lose, and what you see next.


6. If you are scripting this

Traps that read as bugs but are not, all measured :

  • F10 opens Xenia's own menu bar, and while any emulator UI is up the game is handed an empty keystroke before any pad driver is asked. The controller looks dead and is not.
  • A signed-in profile is required--create_profile_if_none.
  • A trace consumer that exits stalls the emulator, which also reads as a dead pad.
  • Cold boot is slow; ~25 s once the shader and code caches are warm.
  • pkill -f xenia_canary kills the shell that ran it, because -f matches the whole command line and your own bash -c contains the pattern. The script dies before the emulator does, silently, with no output at all. Kill by process name: ps -o pid= -C xenia_canary | xargs -r kill -9. (The same trap is in METHOD.md for pgrep wait-loops; it cost another launch on 2026-08-30.)
  • kill -9 on xenia ORPHANS /tmp/xenia-canary.lock, and the next run-canary refuses with "an emulator is already running" — to stderr, where a polling script never looks. A probe of mine then sampled a dead display for 484 s, reporting other every 4 s, because screen_id.py on an empty screen returns other and "not the title yet" is indistinguishable from "there is no emulator". Kill with a plain kill so it can clear its own lock; if you must use -9, rm -f /tmp/xenia-canary.lock after. And assert the emulator is alive before entering any wait loopps -C xenia_canary — so the loop cannot spend its whole deadline on nothing.
  • screen_id.py reports menu during the attract loop. Two boots on 2026-08-30 logged menu at t=106 s and t=418 s while the game was still in the intro movie. A wait-loop that breaks on menu will act on the wrong screen; the loops here break on title for that reason.
  • screen_id.py cannot tell EXTRAS from the main menu — both are dark blue GP_TITLE screens and it answers menu for either. Use which_title_screen.py, which separates them by ~11 RMSE against ~18 within-class, and read the margin: a margin under ~1 means "neither", which is what you get on a screen outside GP_TITLE entirely.