This repository has been archived on 2026-09-16. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Syplheed-Reborn/docs/port/MISSION.md
Sylpheed RE agent 6d246c7a97 re(ui): finish the top-level rotation census; record the JP-capture blocker
Two threads had converged on needing one capture this container cannot
take, so this iteration records that and finishes something reachable.

BLOCKED, written into MISSION.md rather than worked around: Q1's keyframe
time association and the rest() rule for plateau-less elements both now
hinge on a running capture of GP_TITLE build 7, the Japanese title. The
console language is not settable here -- user_language appears only as
DECLARE_int32 at four call sites with no DEFINE anywhere in the tree, and
it is absent from the registered cvars in xenia-canary.config.toml. There
is no flag to pass, and guessing one is specifically unsafe: run-canary's
own header records that xenia calls ShowSimpleMessageBox from
ParseLaunchArguments before logging starts, so a bad flag blocks forever
with an empty log. Rebuilding canary to add the cvar would be improvising
around the blocker; it needs a human decision. Neither question blocks
the five menu screens.

FINISHED: the disc-wide top-level rotation count, left running four
iterations ago as a shell loop over `screen info --geometry` that never
completed (it decodes every texture per build). Walking the placement
region directly takes seconds.

  top-level elements with a keyframe group   15 493
  carrying a non-zero rotation                2 152  (13.89 %)

Both controls pass: GP_TITLE build 4 reports 0 (its rotations are the
nested ptloop records) and GP_DIALOG build 0 reports the expected two.

The control earned its place -- the first version indexed the pak with a
`screen list` BUILD number and got 0 for a screen that has two, because
GP_DIALOG build 0 is entry 2. GP_TITLE maps 1:1, which is how the
assumption survived. METHOD line added.

Two free corroborations of the rotation decode. The rotated population is
dominated by tactical-map ship icons -- pbb_destroyer 444, pbr_destroyer
402, pbr_fighter 276 -- i.e. markers rotated to heading, the single
largest use of the field on the disc. And GP_TITLE entry 7's Japanese
wordmark pieces settle from ALTERNATING tilts:

  ptlogo3a  r = 0, -14, -4, -1, 0, ...
  ptlogo3b  r = 0, +14, +4, +1, 0, ...
  ptlogo3c  r = 0, -14, -4, -1, 0, ...

Same magnitudes, opposite signs, all decaying to upright. A misread field
does not produce that.
2026-08-28 23:46:54 +00:00

164 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Primary objective — answer everything the menu port needs
**Status:** active, set 2026-08-28. This replaces "work the RE backlog" as the
agent's primary objective. It does not change what the agent *does* — it is still
reverse engineering — it changes what earns attention: an item is worth doing
when the menu port is blocked on it.
## Who builds what
**You do not build the port.** A separate agent will build it, from what you
produce. Your deliverable is decoded, verified, written-down answers plus the
reference data that proves them.
| | container agent (you) | port agent |
|---|---|---|
| decodes the disc | ✅ | ❌ — consumes your answers |
| measures the running game | ✅ | ❌ — no emulator |
| writes `docs/re/` and `docs/port/HANDOFF.md` | ✅ | reads them |
| Godot project, asset pipeline, transcoding | ❌ | ✅ |
If you find yourself designing an export schema or writing GDScript, you have
crossed the line. Stop and go back to the question you were answering.
`crates/sylpheed-viewer` is also **not yours to change** for this objective. The
Explorer is the human's tool for exploring and verifying the RE work, it keeps its
static-data-only rule, and the port does not depend on it.
## The target
Someone else has to build this, from your answers alone:
```
developer logo splash → intro video → title / PRESS Ⓐ → main menu → submenus
```
No gameplay, no 3D, no HUD, no missions. If an answer is not needed to put those
five screens on a display and let a person move through them with a d-pad and Ⓐ,
it is not in this objective.
## What is already answered
Do not re-derive these. They are in `docs/re/` and the
[disc atlas](../re/disc-atlas.html):
* **The screen archive.** `GP_TITLE.pak` holds the whole title-side tree — build 4
the title with animating wordmarks, build 5 the five-button main menu, builds
6/8/9 submenus, and the developer splash as the `palogo` bundle in the same pak.
* **Buttons are identifiable as data.** Element kind `0x3002` is a button, `0x0`
decoration, `0x10` a primitive; buttons sort top-to-bottom by resting Y; each
pairs with an `f`-suffixed highlighted variant.
* **The screen vocabulary.** The GamePart id table, 29 entries at `.rdata
0x820A1630`, confirmed by the executable's own factory-registration strings.
* **The resting pose rule** — the hold, not the longest dwell — and that a
keyframe is the *start of a ramp*.
* **Screen composition**, pixel-accurate for the tutorial pause menu and the title
main menu, via `sylpheed-cli screen render`.
* **The logo splash is not a video.** `logo1`–`logo4` are manifest-bound with no
`.wmv` on the disc; the splash is the RATC screen, which already renders.
## The open questions — these are the objective
Ordered by what blocks the port earliest. Each is done when its **gate** exists:
a written `docs/re/` result with the evidence, and reference data committed
alongside it.
| | Question | Gate |
|---|---|---|
| **Q1** | **What is a keyframe time?** Values run 16…269. 60 Hz frames would make the title intro ~4.5 s — plausible and untested. Also: is the ramp linear, or eased? | A measured answer against the running game, not an inference. Everything animated downstream depends on this number |
| **Q2** | **Which build is which screen state?** Confirm build↔state for splash, title/PRESS Ⓐ, main menu and each submenu | A table, each row confirmed against a capture of the real screen |
| **Q3** | **Paint order for these six screens.** Solved at runtime, unsolved from the file — the declaration table is provably not it | Either a rule derived from the bundle, or six measured orders and a clear statement that no file-side rule was found |
| **Q4** | **What does each button do?** Labels are baked into the sprites; no decoded field says which GamePart a button opens | Button → GamePart id, from code or from driving the game. Say which |
| **Q5** | **Navigation semantics.** Initial focus, wrap-around at the ends, whether left/right does anything, what B does on each screen | Observed behaviour, per screen |
| **Q6** | **The boot sequence, and what drives it.** Order is observable; the *data or code* that sequences it is not decoded. Include the attract loop and what returns to the title | The sequence, plus whatever the game reads to decide it |
| **Q7** | **Transitions.** What happens visually between screens — the `pteff00.prm` quads, a fade, a cut — and its timing | Described and timed against a capture |
| **Q8** | **Menu audio.** Which BGM per screen; which cue on move / confirm / back / error. The cue table is complete; the event binding is not | Cue names bound to events, with how you established each |
| **Q9** | **Video binding.** Which movie is the boot intro vs the new-game intro; whether playback is skippable and what ends it | Named movies plus the playback rules |
| **Q10** | **What are a music bank's sub-waves?** `BGM_001.slb` is three sub-waves — 10 KB, 4.47 MB, 4.67 MB — and we currently **concatenate them blindly** into one 347 s track. Two near-equal halves could be intro + loop, or two variations, or two halves of one piece. A menu that loops its music needs to know which | The role of each sub-wave, established for at least the menu BGM. "Concatenate" is a decision, not a default — right now it is a default nobody chose |
| **S1** | ~~**Ready Room probe.**~~ **DONE 2026-08-28 — [no-go](../re/ready-room-probe.md).** It is 2D and enumerates fine, but the pak is briefing/tactical-map content, not the Ready Room menu | ✅ go/no-go written |
## 🔴 Blocked in this container — a Japanese-locale capture
Recorded rather than worked around, per "do not improvise around a blocker".
Two questions have converged on needing **one capture we cannot take**: a running
capture of `GP_TITLE` **build 7**, the Japanese title screen.
* Q1's keyframe-time association. The shifted reading is favoured 26× by a
calibration-free measurement, and the only render it changes on the whole disc
is build 7 ([`ui-keyframe-time-unit.md`](../re/ui-keyframe-time-unit.md)).
* What `rest()` should return for a plateau-less element. The one element that
discriminates, `ptlogo_eff3.t32`, is also in build 7
([`structures/ui-resting-pose.md`](../re/structures/ui-resting-pose.md)).
**Why the container cannot do it:** the console language is not settable. In this
canary tree `user_language` appears only as `DECLARE_int32` — four call sites,
no `DEFINE` — and it is absent from the registered cvars in
`xenia-canary.config.toml`. There is no flag to pass, and passing an unknown one
is specifically dangerous here: `run-canary`'s own header records that xenia
calls `ShowSimpleMessageBox` from `ParseLaunchArguments` *before* logging starts,
so a bad flag blocks forever on an SDL dialog with an empty log.
Rebuilding canary to add the cvar would be improvising around this, so it has not
been done. **It needs a human decision**: either add the cvar and rebuild, or
accept that both questions stay 🟡 and the port authors those values by hand.
⚠️ Neither question blocks the five menu screens. Q1's *interpolation law* is
settled and only multi-keyframe absolute timing is open; `rest()` differs from
its alternative on **one** element across all five screens, and the current
answer there is the defensible one.
## Known unknowns — say so, do not fill them in
Some of these may turn out to be undecodable. That is a valid, useful answer, and
it is better than a guess, because the port agent will otherwise have to author
the mapping by hand and needs to know it is authoring rather than transcribing.
For each question, the answer is one of:
* **decoded** — here is the field, here is the disc-wide check;
* **measured** — not on the disc in any form we found, but here is what the
running game does, and here is the capture;
* **undecodable, with reach** — we looked here, here and here, and this is why it
is not there.
Never a fourth thing. In particular: if Q4 ends as "read the labels off the sprite
images by eye", say exactly that — it is then an authored mapping on the port
side, not a disc fact, and mislabelling it would put a guess into the port wearing
the badge of a measurement.
## The Ready Room probe (S1) — one iteration, then stop
`GP_READY_ROOM.pak` is the largest UI archive on the disc, 1 106 entries, and only
**6 of its names resolve**. It is also ISL-scripted. That is either a week or a
quarter, and one cheap test tells you which.
Our screen catalog enumerates bundles by **content**, not by name — `is_build` /
`is_composable` read the bytes — so unrecoverable *paths* do not necessarily mean
unrenderable *screens*.
```bash
sylpheed-cli screen list "$SYLPHEED_DISC/dat/GP_READY_ROOM.pak"
sylpheed-cli screen render --build <n> "$SYLPHEED_DISC/dat/GP_READY_ROOM.pak" /tmp/rr.png
```
Report how many builds it finds, whether any composite looks like a Ready Room,
and **whether the room is 2D at all** or 3D with a UI overlay — if it is 3D the
answer is no-go by definition, not "try harder".
**Then stop and write the go/no-go.** Do not start Ready Room work on your own
authority.
## Handing it over
[`HANDOFF.md`](HANDOFF.md) is the single page the port agent reads. Keep it
current as you answer questions: it is a summary with links into `docs/re/`, not a
second copy of the findings. An answer that is not reachable from HANDOFF.md has
not been delivered.
## Out of scope
3D, gameplay, HUD, missions, save/load, localisation beyond English, the Godot
project itself, any asset pipeline, and any archive outside `GP_TITLE`,
`tables.pak`, `sound.pak` and `dat/movie/` — except for the S1 probe.