`main_menu` -- the milestone's gate -- agrees with the reference renderer to within 3/255 on every channel of every pixel, RMSE 0.38 %, no pixel above 4 %. Nine of the twelve screens are at or under that; two are byte-identical. Three exceed it, and each gets a cause rather than a wider tolerance: * `title` (max 6): every disagreement is INSIDE A TIE -- the derived order and the CLI's measured-off-the-game order differ only among elements with identical layer keys. That is exactly the residual HANDOFF Q3 documents and the export already declares in `unresolved: paint_order_ties`. Cost: 904 px at 4-6/255 in one glow band. The port keeps the stable sort; fitting it to one screen's capture would be tuning. * `title_jp` (max 154): `ptlogo_eff2` at 125 % is the only drawn element in the whole export at a scale that is not a whole multiple of 100 %, and `title_jp` is the only screen over 6/255. Same fact twice. `ui_layout::blit` samples the source at the destination pixel's top-left corner; a GPU samples at its centre, and at 125 % those disagree on one column in five. I think the CLI is the one that is wrong -- corner-sampled nearest is a half-pixel bias toward the top-left that no rasteriser produces. But that is a reading, not a measurement: it needs a framebuffer capture of the Japanese title screen, so it is filed in BLOCKED.md as a question. The port is NOT changing to match, because matching would mean reproducing a half-pixel offset on purpose to make a number smaller. * `extras` (max 4): two pixels. Also reconciled: the pivot question predicted a P1 diff could not distinguish the declared pivot from half the texture, because both renderers use the declared one. That held. Recorded so the agreement is not later mistaken for evidence -- and P2 will not settle it either. BLOCKED.md's `/reborn` HEAD updated to bc6354d, with a note that the mount is read-only by design and `git -C /reborn pull` fails rather than being skipped.
69 lines
2.7 KiB
Markdown
69 lines
2.7 KiB
Markdown
# 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`][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.
|
|
|
|
[formats]: https://git.mc02.dev/fabi/Syplheed-Reborn
|
|
|
|
## 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.
|