re: verify the sweep leaves' full extent -- port's table confirmed, plus a new fact

Attempted to refute sylpheed-port's leaf table by measuring it against the disc.
It SURVIVES to the digit: ptloop01 -> pteff03, cycle span 600, x track
-639..1521, scale (100, 600); ptloop02 -> pteff03a, span 720, x -839..1721,
scale (100, 800).

The existing ptloop_leaf_sweep_at.rs samples only t=340..540 -- a window chosen
to compare two competing fits -- so it could never have shown the extent. That
gap is what let my "ptloop01/02 do not free-run" claim stand: measured over the
parent's 200x90 pivot rect, which a leaf travelling -639..1521 is almost never
inside. ptloop_leaf_extent.rs sweeps the whole cycle instead.

New fact neither of us had: the leaves are IDENTICAL on entries 4, 5 AND 7 --
the title, the main menu and the JP title. Same leaf names, spans, x tracks,
scales and parent rest position. So the menu declares exactly the same sweep as
the title, and the still-open menu question is about the game's behaviour rather
than a different declaration.

The quad is 400 px wide at scale_x 100 % -- not widened -- and scale_y 600/800 %
makes it 1080/1440 px tall, taller than the screen. A full-height strip crossing
the frame and going off both sides, which is why a phase-to-phase diff covers the
union of two positions and looks frame-wide.

And my own "centre running x~921->1041" was a 30-unit window of a 600-unit cycle
whose centre spans -439..1721. A sub-range is not an extent -- the same caution
as a pivot not being a bounding box, one level up, and I made both errors within
a day.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
This commit is contained in:
sylph-decoder
2026-08-30 16:01:13 +00:00
parent cce20b83ca
commit 2145691586
3 changed files with 122 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
//! The FULL extent of the two title sweep leaves, across their whole cycle.
//!
//! `ptloop_leaf_sweep_at.rs` samples t=340..540 — a window chosen to compare two
//! competing fits — so it never showed how far the leaves travel. That gap let a
//! claim stand that `ptloop01/02` "do not free-run", measured over the PARENT's
//! 200x90 rect, which is a pivot anchor the leaf spends almost no time inside.
//! `sylpheed-port` reports x tracks of -639..1521 and -839..1721 from their
//! export; this checks that against the disc.
//!
//! cargo run -p sylpheed-formats --example ptloop_leaf_extent
use sylpheed_formats::{pak::PakArchive, ui_layout};
use std::path::PathBuf;
fn main() {
let root = PathBuf::from(std::env::var("SYLPHEED_DISC").expect("SYLPHEED_DISC"));
let ar = PakArchive::open(root.join("dat/GP_TITLE.pak")).expect("GP_TITLE.pak");
for entry in [4usize, 5, 7] {
let Ok(by) = ar.read(&ar.entries()[entry]) else { continue };
let Some(b) = ui_layout::parse_build(&by) else { continue };
println!("\n######## GP_TITLE entry {entry} ########");
for parent in ["ptloop01", "ptloop02"] {
let Some(el) = b.elements.iter().find(|e| e.name.starts_with(parent)) else {
println!(" {parent}: not present in this build"); continue };
let Some(&(off, size)) = b.records.get(&el.name) else {
println!(" {}: no nested record", el.name); continue };
let span = u32::from_be_bytes(by[off + 8..off + 12].try_into().unwrap());
let Some(lb) = ui_layout::parse_build(&by[off..off + size]) else {
println!(" {}: leaf will not parse", el.name); continue };
println!(" {} parent rest ({},{}) nested cycle span {span}",
el.name, el.keyframes.last().map(|k| k.x).unwrap_or(0),
el.keyframes.last().map(|k| k.y).unwrap_or(0));
for le in &lb.elements {
let (mut lo, mut hi) = (i64::MAX, i64::MIN);
let (mut sxs, mut sys) = (Vec::new(), Vec::new());
for t in 0..=span {
if let Some(k) = le.pose_at(t) {
lo = lo.min(k.x as i64); hi = hi.max(k.x as i64);
if !sxs.contains(&k.scale_x) { sxs.push(k.scale_x) }
if !sys.contains(&k.scale_y) { sys.push(k.scale_y) }
}
}
let w = (le.pivot_x * 2) as i64;
println!(" leaf {:<12} pivot {}x{} quad w={w} x track {lo} .. {hi} \
(centre {} .. {}) scale_x {:?} scale_y {:?}",
le.name, le.pivot_x, le.pivot_y,
lo + le.pivot_x as i64, hi + le.pivot_x as i64, sxs, sys);
}
}
}
println!("--- END ---");
}

View File

@@ -0,0 +1,47 @@
# The two title sweep leaves, across their WHOLE cycle. 2026-08-30.
# instrument: examples/ptloop_leaf_extent.rs
#
# Why this exists: ptloop_leaf_sweep_at.rs samples t=340..540, a window chosen to
# compare two competing fits, so it never showed how far the leaves travel. That
# gap let a claim stand that ptloop01/02 "do not free-run", measured over the
# PARENT's 200x90 rect -- a pivot anchor the leaf is almost never inside.
#
# sylpheed-port reported x tracks of -639..1521 and -839..1721 from their export.
# Checked against the disc, independently:
######## GP_TITLE entry 4 ########
ptloop01.rat parent rest (441,270) nested cycle span 600
leaf pteff03.t32 pivot 200x90 quad w=400 x track -639 .. 1521 (centre -439 .. 1721) scale_x [100] scale_y [600]
ptloop02.rat parent rest (441,270) nested cycle span 720
leaf pteff03a.t32 pivot 200x90 quad w=400 x track -839 .. 1721 (centre -639 .. 1921) scale_x [100] scale_y [800]
######## GP_TITLE entry 5 ########
ptloop01.rat parent rest (441,270) nested cycle span 600
leaf pteff03.t32 pivot 200x90 quad w=400 x track -639 .. 1521 (centre -439 .. 1721) scale_x [100] scale_y [600]
ptloop02.rat parent rest (441,270) nested cycle span 720
leaf pteff03a.t32 pivot 200x90 quad w=400 x track -839 .. 1721 (centre -639 .. 1921) scale_x [100] scale_y [800]
######## GP_TITLE entry 7 ########
ptloop01.rat parent rest (441,270) nested cycle span 600
leaf pteff03.t32 pivot 200x90 quad w=400 x track -639 .. 1521 (centre -439 .. 1721) scale_x [100] scale_y [600]
ptloop02.rat parent rest (441,270) nested cycle span 720
leaf pteff03a.t32 pivot 200x90 quad w=400 x track -839 .. 1721 (centre -639 .. 1921) scale_x [100] scale_y [800]
--- END ---
# CONFIRMED to the digit: ptloop01 -> pteff03, span 600, x -639..1521,
# scale (100, 600); ptloop02 -> pteff03a, span 720, x -839..1721, scale (100,800).
#
# 📌 AND A FACT NEITHER OF US HAD: the leaves are IDENTICAL on entries 4, 5 and 7
# -- the title, the MAIN MENU and the JP title. Same leaf names, same spans, same
# x tracks, same scales, same parent rest position. So the menu carries exactly
# the same sweep as the title, at the declaration level.
#
# The quad is 400 px wide at scale_x 100 % -- not widened -- and scale_y 600/800 %
# makes it 1080 / 1440 px tall, taller than the 720-px screen. A full-height strip
# whose left edge travels -639..1521, i.e. right across the frame and off both
# sides. Two phases of that are hundreds of pixels apart, which is why a
# phase-to-phase diff covers the union of both positions and looks frame-wide.
#
# ⚠️ My own earlier figure, "centre running x~921->1041", is a 30-UNIT WINDOW of a
# 600-unit cycle whose centre spans -439..1721. A sub-range is not an extent --
# the same caution as a pivot not being a bounding box, one level up.

View File

@@ -154,6 +154,30 @@ parent is static while the **leaf record animates**, and the two nested records
cycle at *different* lengths, **600 and 720**. My "single static keyframe" was a
statement about the parent only.
**Their full table also survives an independent check against the disc**
([`data/ptloop-leaf-extent.txt`](../data/ptloop-leaf-extent.txt)), to the digit:
| | `ptloop01` | `ptloop02` |
|---|---|---|
| leaf | `pteff03` | `pteff03a` |
| cycle span | 600 | 720 |
| x track (left edge) | **639 … 1521** | **839 … 1721** |
| scale | (100 %, **600 %**) | (100 %, **800 %**) |
The quad is 400 px wide and **not** widened; `scale_y` makes it 1080 / 1440 px
tall — a full-height strip taller than the screen, whose left edge travels right
across the frame and off both sides.
📌 **And a fact neither of us had: these leaves are IDENTICAL on entries 4, 5 and
7** — the title, the **main menu**, and the JP title. Same leaf names, spans, x
tracks, scales and parent rest position. So the menu declares exactly the same
sweep as the title; the open menu question is about the game's *behaviour*, not
about a different declaration.
⚠️ **My own "centre running x≈921→1041" was a 30-unit window of a 600-unit cycle**
whose centre spans 439…1721. A sub-range is not an extent — the same caution as a
pivot not being a bounding box, one level up, and I made both errors in one day.
⚠️ The era adjudication is unaffected: its box is x 389..776, and the overlap with
the sweep band (x 721..776) shows no between-session differences — the 645 in-box
differing pixels all sit at y 99..128.