[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. # A PATH dependency now that the decoders and the exporter live in one # repository. This deletes a whole class of failure that the two-repo split # created: no pinned revision to go stale, no tag to keep alive, no commit that # a squash-merge can orphan, and no way for the exporter to be built against a # decoder it was never tested with. A decoder change and the exporter change it # requires now land in the same commit or not at all. # ✅ UNPINNED 2026-09-20. The pin above was deliberate and carried its own exit # condition -- "revert to the path dependency the day the tag is an ancestor of # `main`" -- because while it held, `sylpheed-cli` built from the WORKSPACE crate # and the exporter from the tag, so `tools/port/verify-screen` compared two eras # instead of detecting drift. `formats-pin-2026-09-01` is now an ancestor of # `main` (measured), so the two read one decoder again. # # 🔴 AND THE PIN HAD A COST NOBODY PRICED IN: it made this repository depend on # its OWN history by tag. The issue-#49 history rewrite replaced every commit, # the locked rev vanished, and the build broke for every clean checkout while # still working on the machine that did the rewrite, because its `~/.cargo/git` # still held the old object (PR #60). A path dependency cannot fail that way. sylpheed-formats = { path = "../sylpheed-formats" } 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"] }