why describing code we do not have
H7 closed: the Decoder withdrew the per-GamePart rate the same day (1e7343e --
"it was the emulator's frame rate") and struck the section carrying it. The port
never moved, so nothing has to be undone. The refutation is kept because its
shape is reusable: a duration measured in emulator frames is the emulator's rate,
not the game's, and the tell was that it made a part outlast its whole.
That leaves the splashes with the rate at 60 unchallenged, the keyframes
vindicated against the vertex stream (worst error one alpha level in 255, no
renderer in the chain) and verify-capture at 0.01 % on both. So the one thing
nobody had checked was the REAL-TIME boot path -- our own timing end to end,
rather than a frozen pose or a model.
Pre-registered: at 60 units/s, publisher holds 255 + 9 = 264 units = 4.400 s and
developer 210 + 9 = 219 units = 3.650 s, the figures authored/timing.json states
the port emits. Accept +/-0.10 s. Three boots, no film competing with the
renderer:
publisher 4.28 / 4.26 / 4.27 mean 4.270 s declared 4.250 residual +1.2 u
developer 3.50 / 3.57 / 3.51 mean 3.527 s declared 3.500 residual +1.6 u
THE PREDICTION FAILED BY 0.13 s ON BOTH, AND THE PORT WAS RIGHT.
authored/timing.json sets black_hold_units = 0, deliberately, with its own
argument attached: a uniform black hold is positively EXCLUDED -- the same origin
gives different values to different destinations -- so only an ordered-pair key
survives and nothing may be authored until one is measured. There is therefore no
9-unit hold to add, and the port has never added one.
Two places said it did:
authored/timing.json dwell_why -- "The port emits 4.400 s and 3.650 s -- each
declared value plus the 9-unit black hold, exactly. So the pacing was right
all along and nothing changes in the code."
port/scripts/boot.gd, the _advance block -- the same sentence.
The `why` asserted a behaviour the SAME FILE refuses three keys below it, and the
code comment repeated it. Both corrected in place, with the measurement. No
behaviour changed: the claim was wrong, not the code, and the port has been
shipping 4.270 / 3.527 since P3.
⚠️ It does NOT show a hold does not belong there. Against the corpus means (4.42
and 3.46) neither figure dominates -- the port is 3.4 % short on the publisher
and 2.0 % long on the developer, where the claim would be 0.5 % short and 5.5 %
long. black_hold_why's ordered-pair ask is untouched.
⚠️ And it is a PATTERN, not an incident: this is the third `why` in this corpus
describing behaviour the code does not have, after exit_ramp_units and the dwell
slot that "was read NOWHERE for eight milestones". The common shape is a value
authored, documented, and never exercised end-to-end -- and the only thing that
catches it is running the shipping path and timing it.
Refutation attempts: the hit is against my own files again, found by predicting
my own behaviour and being wrong. The Decoder's keyframe vindication survived --
it is what makes 60 the only remaining variable on the splashes, and 60 now has
three cold boots plus three of my own runs agreeing with the declared groups.
Not settled: whether a black hold belongs between screens at all (needs an
ordered-pair measurement); H6's +0x04 exposure; H1 (key repeat).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AHUQvXGyNcKonSEWsgWcX
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-cliand 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
-- and RUNNING.md, which is how you actually start it
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
docs/re/INDEX.md— what is decodeddocs/re/REFUTED.md— what has been tested and dieddocs/re/METHOD.md— traps this project has already paid fordocs/game/navigation.md— how the game is navigateddocs/port/MODDING.md— why the asset tree looks the way it does
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.