Sylpheed port agent 7a6a027fc8 port: P7 -- the new-game intro plays, and the two screens it skips are named out loud
S00A has been exported since P4; what P7 needed was something to play it and a
defined place to land. Both are here, and the interesting part is the gap.

The real chain is NEW GAME -> DIFFICULTY -> SELECT DATA -> (A) on a save slot ->
~4.5 s -> S00A. DIFFICULTY and SELECT DATA are MEASURED destinations that are not
GP_TITLE builds, so no screen file exists to go to. The port jumps from NEW GAME
to the one thing in that chain it has -- and the whole design is about not
letting that read as a sequence:

  * MenuFlow.accept returns a new kind, `video`, rather than folding this into
    `blocked`, because the caller has to announce the skip and a distinct kind is
    what forces it to;
  * the runtime prints the skipped screens by name on every run;
  * flow.json carries `skipped_chain` as DATA, so what is missing lives beside
    the decision instead of inside a GDScript string.

After the movie the port returns to the title. Authored, and it has to be: the
game goes into mission 1 and gameplay is out of scope. The ~4.5 s before the
movie is left EMPTY on purpose -- GP_TITLE does carry a loading screen and 4.5 s
is about the right shape for one, which is exactly why that belongs in BLOCKED.md
and not in flow.json.

`--script`'s 20 s per-step timeout would have killed every movie run at step 1.
Raising the constant would have been wrong the other way: a movie stuck at frame
0 would then hang the job, and a job that waits is worse than one that fails. The
test is now LIVENESS -- while get_stream_position() advances the deadline moves
with it, and a stalled movie still trips the same 20 s.

Found while looking: GP_TITLE's four unnamed builds (entries 0, 1, 12, 15) are
LOADING screens -- every element in all four is pgloading_*, and LOADING is one of
the three names the decoder read out of the title part's state function. NOT
renamed here: which member of each pair is which locale is an inference, and a
name stops being questioned once written. Handed over.

One of them is a second casualty of the rest.t problem, and a worse one:
pgloading_eff00.prm rests OPAQUE BLACK at t=38, so anything drawing that screen
at its declared rest paints a black rectangle over all of it. The title's case
only dimmed a frame.

REFUTATION, attempted and SURVIVED: HANDOFF says "exactly the six screen builds
carry the black .prm quad while the six overlays do not". Counting bundles with a
full-screen black primitive gives 8 and 4 -- build_12/15 carry one too. But
theirs runs black -> held -> clear where the transition quad runs black -> clear
-> black, so read strictly as "the quad whose group is the transition" the claim
holds. Recorded anyway: there are two kinds, and the naive census over-counts.

Gate: NEW GAME -> S00A plays 93.75 s against a declared 93.9 -> title, with
98.453 s recorded off the Master bus. What that does NOT show is that S00A's own
audio is in the mix -- bed and movie were not separated in this run, and the
write-up says so.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WM5XL4HfrHuxz8RiMWdCMC
2026-08-29 13:12:41 +00:00

Sylpheed

A clean-room reverse engineering and port project for Project Sylpheed: Arc of Deception (Xbox 360, 2007).

Three things live here, in one repository so that a change spanning them lands as one commit:

The decoders crates/sylpheed-formats — the disc's formats, read and verified disc-wide
The port port/ — a Godot 4 project, plus crates/sylpheed-export which converts a disc into the open asset tree it reads
The corpus docs/re/ — what has been reverse engineered, with its evidence, its retractions and its dead ends

You need your own copy of the game. No game content is in this repository and none ever will be. The exporter reads the disc you supply.

The oracle is the real game

sylpheed-cli and the Explorer are tools for verifying our decoding. They are hypotheses under test and they have been wrong. When something must be checked against the truth, the truth is the game running in Xenia Canary, captured — not any renderer of ours.

This is stated first because getting it backwards is the most expensive mistake this project has made.

Layout

crates/
  sylpheed-formats/   the decoders. Disc-wide verified; the corpus is its spec
  sylpheed-cli/       headless tools -- render a screen, dump a table, probe audio
  sylpheed-viewer/    the Explorer: a human's window onto the disc. STATIC data only
  sylpheed-export/    disc -> the open, moddable asset tree
port/                 the Godot 4 project. Reads open formats ONLY
authored/             decisions that are NOT on the disc, each with its reason
data/
  base/               generated by the exporter. Gitignored, never hand-edited
  mods/               drop-in overrides. Yours
docs/
  re/                 the corpus: findings, refutations, method traps
  game/               how the game is navigated -- menus, modals, flight
  port/               the port's mission, its handoff contract, modding rules
  agents/             how the agent team works together
tools/                capture harnesses, probes, the share tool
exchange/             transient inter-agent files. NOT in git
docker/               the agent containers

Where to start

Xenia Canary is a separate repository: it is a fork tracking upstream, and it carries our instrumentation.

Conventions

Confidence is per claim, never per document: CONFIRMED · 🟡 PROBABLE · HYPOTHESIS · REFUTED. A withdrawn result is kept with its reasoning rather than deleted — that is why the numbers here can be trusted.

Description
No description provided
Readme MIT 820 MiB
Languages
Rust 57.6%
Python 27.7%
Shell 10.6%
GDScript 3.5%
Dockerfile 0.4%
Other 0.1%