Refutes a DECISIONS claim and decodes the element the port withheld on my say-so. The claim that title_jp s ptlogo_eff2 at 125 percent is the single drawn element in the whole export at a scale that is not a whole multiple of 100 percent rested on a census of PARENTS only. Opening the 45 leaves as well finds thirteen distinct non-whole-multiple scales -- 75, 96, 99, 101, 103, 112, 125, 150, 204x208, 210x220, 250, and the 75x100 / 96x100 / 99x100 pairs -- with 125 among the rarest at two occurrences. ptlogo1 and ptlogo2 carry 101/103/112 on the ENGLISH title too, so it is not a Japanese-build peculiarity. The claim s real content was "the only one the port draws", which is about the export s element set rather than the disc. And ptlogo_eff2 is decoded. The 125 percent lasts 57 units, about 0.95 s -- a scale-0 to 125 to scale-0 flash between t=50 and t=107, a transient rather than a steady state, which is why it looked anomalous in a census of resting poses. The leaf draws at 100 percent as two superimposed copies of the same sprite at alpha 160 and 80, each rotating a full 360 degrees over 960 units: a slow double-layered spin, 16 s per revolution. This is exactly the case the ptloop rule could not separate. There the parent had expired so leaf-wins and parent-ignored were indistinguishable; here the parent carries real geometry including a scale that reaches zero twice. If parent scale gates the leaf the spin is a 0.95 s flash; if the leaf runs on its own timeline it spins for 16 s. Nothing on the disc chooses between them, and title_jp has no oracle capture, so it is undecodable in this container -- the port is right to withhold it, and the Japanese-locale capture MISSION has parked would settle it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
49 lines
2.1 KiB
Rust
49 lines
2.1 KiB
Rust
//! Every scale value on the disc's UI, parents AND nested leaves.
|
|
//!
|
|
//! `DECISIONS.md` records `ptlogo_eff2` at 125 % as "the single drawn element in
|
|
//! the whole export at a scale that is not a whole multiple of 100 %". That
|
|
//! census was over parents only -- leaves were never opened. This opens them.
|
|
use sylpheed_formats::{pak, ui_layout};
|
|
use std::collections::BTreeMap;
|
|
|
|
fn main() {
|
|
let path = std::env::args().nth(1).expect("pak");
|
|
let ar = pak::PakArchive::open(&path).expect("open");
|
|
let mut hist: BTreeMap<(u32, u32), Vec<String>> = BTreeMap::new();
|
|
let mut leaves_opened = 0usize;
|
|
for (i, e) in ar.entries().to_vec().iter().enumerate() {
|
|
let Ok(bytes) = ar.read(e) else { continue };
|
|
let Some(b) = ui_layout::parse_build(&bytes) else { continue };
|
|
for el in &b.elements {
|
|
for k in &el.keyframes {
|
|
hist.entry((k.scale_x, k.scale_y))
|
|
.or_default()
|
|
.push(format!("e{i}/{}", el.name));
|
|
}
|
|
if let Some(&(off, size)) = b.records.get(&el.name) {
|
|
if let Some(lb) = ui_layout::parse_build(&bytes[off..off + size]) {
|
|
leaves_opened += 1;
|
|
for le in &lb.elements {
|
|
for k in &le.keyframes {
|
|
hist.entry((k.scale_x, k.scale_y))
|
|
.or_default()
|
|
.push(format!("e{i}/{}->LEAF/{}", el.name, le.name));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
println!("{leaves_opened} leaves opened\n");
|
|
println!("{:>12} {:>7} examples", "scale", "count");
|
|
for (k, v) in &hist {
|
|
let mut ex: Vec<&String> = v.iter().collect();
|
|
ex.sort(); ex.dedup();
|
|
let odd = k.0 % 100 != 0 || k.1 % 100 != 0;
|
|
println!("{}{:>5},{:<5} {:>7} {}", if odd { "* " } else { " " },
|
|
k.0, k.1, v.len(),
|
|
ex.iter().take(3).map(|s| s.as_str()).collect::<Vec<_>>().join(", "));
|
|
}
|
|
println!("\n* = not a whole multiple of 100%");
|
|
}
|