Sylpheed port agent 0db45b4c66 port: play the keyframe timeline, with the time unit authored in one place
P2. A keyframe is the start of a linear ramp toward the next; `ScreenView` walks
them at `time_units` and `boot.gd` advances that in real time, or freezes it with
`--time=<seconds>`.

`authored/timing.json` holds the ONE constant this needs. HANDOFF Q1 is answered
-- linear, 2 units per rendered frame, 1 unit = 1/60 s -- but that conversion was
MEASURED off the running game, not read from a file, so it is authored rather
than exported and it says so at length. Expressed as units-per-second, because
60 is exact and 0.01666... is a decimal a reader has to recognise.

The timeline stops at the last TIMED keyframe and never plays the exit. Every
group's final keyframe carries no `t` -- across this export it is a fade-out for
116 of 134 elements, a scale-and-slide exit for 12, and identical for 6 -- so
playing into it would mean inventing how long the ramp takes. That duration is
the screen transition, it is measured at ~0.4 s, and it is P3's to author with
its own evidence. `exit_ramp_seconds` is therefore null on purpose, not missing.

`--pose=rest` keeps the P1 behaviour available: since the port's default is now
the timeline and the two DISAGREE, renderer-vs-renderer diffing has to be able to
ask for the same assumption the reference renderer makes.

The interpolation is checked by where it lands: on 8 of the 12 screens the
settled timeline is byte-identical to the rest render.
2026-08-28 19:51:57 +00:00

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:

  1. Godot cannot read IPFB archives, RATC bundles, T8aD textures, XMA banks or WMV video, and it should not learn to.
  2. 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.

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%