sylpheed-port mapped the menu's edge residual at 64 px tiles and handed over coordinates without names, which is the division I proposed: the map is theirs, the element inventory is mine. Under the hot band at x 384..704, y 64..256 sit ptframe1.t32, ptbtn01.rat (the NEW GAME button) and pteff12.t32, an effect element -- all three hot under BOTH coordinate readings, so the answer does not depend on whether their tiles are in design or capture space. ptbtn02 is hot in design space only. So the hot region is not one element but three of different kinds overlapping, which is consistent with their null: they looked for two families of tile and found one continuous population, so the region has no character of its own. This names what is there, not what is wrong -- their map already excludes local displacement in these tiles. Also records their control limit: a +2 px displacement reads back +0.839 because the slope saturates, so any slope they report is a floor on the displacement and never a ceiling. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
47 lines
2.2 KiB
Rust
47 lines
2.2 KiB
Rust
//! What elements sit under the port's hot residual tiles on the main menu?
|
||
//!
|
||
//! `sylpheed-port` mapped the menu's edge residual at 64 px tiles and handed over
|
||
//! coordinates without names — the element inventory is this side's. Hot tiles
|
||
//! cluster at x 384–704, y 64–256, hottest at (512,128).
|
||
//!
|
||
//! ⚠️ Their tiles are in the frame they compare in; this prints DESIGN space, and
|
||
//! the two differ by the capture offset (capture_y ≈ 64.8 + 0.992·design_y). Both
|
||
//! readings are printed so the mapping is not assumed.
|
||
//!
|
||
//! cargo run -p sylpheed-formats --example main_menu_element_extents
|
||
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");
|
||
let by = ar.read(&ar.entries()[5]).expect("entry 5");
|
||
let b = ui_layout::parse_build(&by).expect("build");
|
||
println!("{:<26} {:>6} {:>6} {:>7} {:>7} {}", "element", "x", "y", "pivot_x", "pivot_y", "sprite");
|
||
let mut rows: Vec<(i32, i32, String, String)> = b
|
||
.elements
|
||
.iter()
|
||
.map(|e| {
|
||
let k = e.rest();
|
||
(k.map(|k| k.x).unwrap_or(0), k.map(|k| k.y).unwrap_or(0),
|
||
e.name.clone(), e.sprite.clone().unwrap_or_default())
|
||
})
|
||
.collect();
|
||
rows.sort_by_key(|r| (r.1, r.0));
|
||
for (x, y, n, s) in &rows {
|
||
// flag anything whose rest position lands in the hot band, read both ways
|
||
let cap_y = 64.82 + 0.9919 * (*y as f64);
|
||
let hot_design = (384..=704).contains(x) && (64..=256).contains(y);
|
||
let hot_capture = (384..=704).contains(x) && (64.0..=256.0).contains(&cap_y);
|
||
let mark = match (hot_design, hot_capture) {
|
||
(true, true) => " <- HOT both readings",
|
||
(true, false) => " <- hot in DESIGN space",
|
||
(false, true) => " <- hot in CAPTURE space",
|
||
_ => "",
|
||
};
|
||
println!("{n:<26} {x:>6} {y:>6} {:>7} {:>7} {s}{mark}",
|
||
b.elements.iter().find(|e| &e.name == n).map(|e| e.pivot_x).unwrap_or(0),
|
||
b.elements.iter().find(|e| &e.name == n).map(|e| e.pivot_y).unwrap_or(0));
|
||
}
|
||
}
|