rest -- except on six elements, where the game
agrees with the timeline P2's gate is the buttons sliding in, and `tools/screen-strip` renders the strip that shows it. But the useful result came out of checking where the animation settles. On 8 of 12 screens the settled timeline is BYTE-IDENTICAL to the declared `rest` pose -- the port walks the keyframes with an authored time unit and arrives, to the pixel, where the pinned decoders independently say the screen rests. On `main_menu` the two differ in exactly one region, 400x470 at (440,108): the bounding box of `ptframe1` and `ptframe2` and nothing else. `rest` puts both at their first keyframe, off-position and transparent. The capture of the running game shows them -- the bright circuit bracket around the menu. Cropping the same region from the capture and from both renders puts the ring and its elbow trace in the timeline render pixel-aligned with the game's, and absent from the rest render. Geometry, so it does not depend on the capture's gamma or on its having been taken with NEW GAME focused. `ui_layout::rest_plateau` excludes a trailing run of identical keyframes because it is normally the exit. On an element with NO exit animation the trailing run IS the hold. The condition that identifies these exactly, with no false positives here, is "the final untimed keyframe has the same pose as the last timed one" -- six elements, and `rest()` misses all six. Filed in BLOCKED.md for the RE agent: the decoders are pinned and are not this port's to fix, and `sylpheed-cli screen render` is missing the bracket too. Worth saying plainly what this does to P1: the port and the reference agreed on `main_menu` to 3/255 and BOTH were missing two elements the game draws. Two renderers reading one field through one decoder agreeing is not evidence the field is right. BLOCKED.md had already said that about the pivot; here it bit. The title is NOT settled and P2 does not claim it. `rest` and the timeline disagree there by 142-247/255, the only live title capture composites the PRESS A plate over build 4 so it cannot be diffed against the title alone, and both of the port's modes draw a cyan glow slab the game does not have -- a third problem, P3's. Recorded as an open question rather than resolved by tuning. Also reconciled against the RE agent's new work: Q8 is answered -- the SE waves are located in `Static.slb` (move/confirm/back), which unblocks P6's audio; and the title's transitions are a lookup by NAME, giving P3/P5 the game's own screen vocabulary as candidate `goto` targets, marked as the name match it is.
Sylpheed Godot
A clean-room Godot 4 port of Project Sylpheed: Arc of Deception, starting with the menu shell: developer splash → intro video → title → main menu → submenus.
You need your own copy of the game. Nothing in this repository is game content. An offline exporter reads the disc you supply and writes an open, moddable asset tree; the Godot project reads only that tree and never touches a disc format.
your disc ──▶ crates/sylpheed-export ──▶ export/ ──▶ port/ (Godot 4)
(Rust; decoders come from JSON + PNG reads ONLY
sylpheed-formats) + OGG + OGV open formats
Why the wall
Two reasons, and the second is the interesting one:
- Godot cannot read IPFB archives, RATC bundles, T8aD textures, XMA banks or WMV video, and it should not learn to.
- Modding is a goal of this port. If the runtime reads the original formats, modding means reverse engineering. If it reads JSON and PNG, modding means opening a file.
Where the knowledge comes from
The decoders live in sylpheed-formats, pinned by revision — a
separate project, where the reverse engineering happens. Its
docs/port/HANDOFF.md is the contract: what has been decoded, what was measured
off the running game, and what is known to be undecodable. Read it before
assuming a value is on the disc.
Layout
crates/sylpheed-export/ |
disc → open formats. Regenerates export/ wholesale |
port/ |
the Godot 4 project |
authored/ |
decisions that are not on the disc, each with its reason |
export/ |
generated, gitignored, never hand-edited |
tools/ |
verification harnesses that hold the port to the reference renderer |
docs/ |
the mission, the format spec, the agent's loop prompt |
Verifying
sylpheed-cli screen render -- built from the same sylpheed-formats revision
the exporter is pinned to -- is the reference renderer. tools/verify-screen
draws every exported screen both ways and reports the largest per-channel
difference in the frame:
tools/verify-screen # every screen in the manifest
tools/verify-screen main_menu # one of them
Where the two disagree, one of them is wrong; docs/DECISIONS.md says which and
why, rather than tuning the port until the number goes down.
Status
P1. The exporter writes GP_TITLE's twelve screen builds and their sprites,
and the Godot project draws any of them statically at 1280x720 from that tree
alone. main_menu matches the reference renderer to within 3/255 on every
channel of every pixel. Next: P2, keyframe animation.