Pin bumped to the TAG formats-pin-2026-08-29 (7eeae30), applying the policy the previous commit wrote. What I wanted from it: `UiBuild` gained a public `records` map. Without it a leaf was unreachable through the public API -- parse_build sorted T8aD children into `sprites` and `.rat` children into a PRIVATE map -- so the focus ring, which lives inside ptbtn0Nf.rat, a record the parent bundle declares NO element for, could not be located at all. My exporter was writing 19 of build 5's 21 sprites and I could not see why. v3 carries two new things. ROTATION. `rotation_deg`, decoded at keyframe +12, and the game DRAWS it -- confirmed twice by the RE agent on different screens with different elements: the title's ptloop sweeps declare +30/-45 and a GPU capture submits them at +30.26/-45.28, and the focus ring ramps 0 -> 360 with everything else constant, caught mid-spin in a capture. Rotation is about the DECLARED PIVOT, measured. The comparison renderer does not draw it yet, so a rotation disagreement means sylpheed-cli is behind, not that the port is wrong. Sign is still an assumption. THE FOCUS RECORD. A focused button is not a sprite swap: ptbtn0Nf.rat declares the spinning ring AND the bright label, and since the parent declares no element for the record, the leaf is the only source of placement for both. v2's single focus_sprite could not carry the ring at all and drew the highlight 7 px off-centre by inheriting the base position. That -7,-7 is load-bearing: the f label is 13 px larger per axis and -7 keeps the two concentric. Checked against the game, not against the other renderer: rendering main_menu with OPTIONS focused changes the region x 504..703, y 399..448. The RE agent measured the same difference in the live capture at x 505..703, y 397..446 -- independently, from the other side. Ring, label and underline all land; the only visible residual is the ring's spin PHASE, which is exactly the one thing neither of us has resolved (its second keyframe is untimed, and the screen-level rule for that is not established to apply inside a leaf). Listed in `unresolved` rather than invented. verify-screen is unchanged at 16/16 -- rotation has no effect at rest on these screens, as predicted.
59 lines
3.4 KiB
TOML
59 lines
3.4 KiB
TOML
[package]
|
|
name = "sylpheed-export"
|
|
description = "Convert a Project Sylpheed disc into the open asset tree the Godot port reads"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
license.workspace = true
|
|
|
|
[dependencies]
|
|
# The decoders, PINNED BY REVISION. Not vendored and not reimplemented: they are
|
|
# disc-wide verified in their own repository, and floating the pin would let a
|
|
# decoder change land mid-milestone -- exactly the confusion this prevents.
|
|
#
|
|
# `sylpheed_formats::media` in particular owns the cases where one playable thing
|
|
# is not one archive entry (segment-spanning reads, multi-sub-wave banks, and the
|
|
# continuous cutscene-voice stream). Do not re-derive those here.
|
|
#
|
|
# Pin moved f817dd5 -> 7eeae30 on 2026-08-29. WHAT I WANTED FROM IT: `UiBuild`
|
|
# gained a public `records` map (record name -> the nested `.rat` leaf's byte
|
|
# range). Without it a consumer could not locate a leaf at all: `parse_build`
|
|
# sorted T8aD children into `sprites` and `.rat` children into a PRIVATE map, so
|
|
# the focus ring -- which lives inside `ptbtn0Nf.rat`, a record the parent
|
|
# bundle declares no element for -- was unreachable through the public API.
|
|
# Also brings `Keyframe::rotation_deg`, which the game does render.
|
|
#
|
|
# PINNED BY TAG, not by sha, and MISSION §2 now requires it. The reachability
|
|
# risk this comment used to warn about is closed: a sha reachable only from an
|
|
# `auto/*` branch is orphaned when that branch is deleted or -- worse --
|
|
# SQUASH-MERGED, because squash creates new commits, so `main` would look like
|
|
# it contained the work while this pin became unreachable. A tag is a permanent
|
|
# ref, it says what it is here in the file, and it fails loudly at FETCH rather
|
|
# than silently at build. `formats-pin-2026-08-29` is 7eeae30.
|
|
#
|
|
# Previous pin note, kept because the reasoning still holds:
|
|
# Pin moved 5414db3 -> f817dd5 on 2026-08-29. WHAT I WANTED FROM IT: `56cc7ac`,
|
|
# "a RATC child's name is stated, not inferred". A child was named by scanning
|
|
# backwards for the last printable run before its magic; for `pteff05.t32` the
|
|
# three trailing payload bytes are `38 41 58` = `8AX` and beat the real name, so
|
|
# the FULL-RESOLUTION BACKGROUND OF ALL FIVE MENU SCREENS registered under a
|
|
# name no element declares and resolved to no sprite. This port exported those
|
|
# screens without their background and said so in every render as "pteff05 (no
|
|
# sprite in the export)" -- which docs/DECISIONS.md then wrote up as correct.
|
|
# It was not. f817dd5 is the last commit touching `crates/` on that branch.
|
|
#
|
|
# Previous pin note, kept because the reasoning still holds:
|
|
# Pin moved 8b6dbcf -> 5414db3 on 2026-08-28. WHAT I WANTED FROM IT: the fix to
|
|
# `ui_layout::rest()`. At 8b6dbcf a trailing run of identical keyframes was
|
|
# always treated as the exit, so an element with no exit animation rested at its
|
|
# invisible pre-roll -- `ptframe1`/`ptframe2`, the main menu's circuit bracket,
|
|
# which a capture of the running game plainly shows. 5414db3 is the revision at
|
|
# which that fix carries its disc-wide check (30 of 13 991 elements move, 4
|
|
# become visible, 0 become invisible), not merely the one where it was written.
|
|
sylpheed-formats = { git = "https://git.mc02.dev/fabi/Syplheed-Reborn.git", tag = "formats-pin-2026-08-29" }
|
|
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
anyhow = "1"
|
|
clap = { version = "4", features = ["derive", "env"] }
|
|
image = { version = "0.25", default-features = false, features = ["png"] }
|