re: name the elements under the port's hot residual tiles -- a frame, a button and an effect

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
This commit is contained in:
sylph-decoder
2026-08-31 05:02:19 +00:00
parent 36b81da9d9
commit fdc4cc9a62
2 changed files with 84 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
//! 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 384704, y 64256, 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));
}
}

View File

@@ -0,0 +1,38 @@
# What sits under the port's hot residual tiles on the main menu? 2026-08-31.
#
# 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. Their result:
# hot tiles cluster at x 384..704, y 64..256, hottest (512,128) at 3.66x the median
# tile, and NO tile in the hot region has moved (every |dx|,|dy| < 0.1 px against a
# control reading a true 1 px at +0.949).
#
# ⚠️ COORDINATE FRAME. Their tiles are in the frame they compare in; the disc is
# design space, and the two differ by the capture offset
# (capture_y = 64.82 + 0.9919 * design_y). So both readings were tested rather than
# one assumed -- and the answer does not depend on it: three elements are hot under
# BOTH.
#
# ✅ ELEMENTS WHOSE REST POSITION FALLS IN THE HOT BAND (GP_TITLE entry 5):
#
# ptframe1.t32 (440, 108) pivot (124,140) HOT under both readings
# ptbtn01.rat (542, 162) pivot ( 42, 22) HOT under both -- the NEW GAME button
# pteff12.t32 (467, 180) pivot (174,180) HOT under both -- an effect element
# ptbtn02.rat (542, 242) pivot ( 58, 22) hot in DESIGN space only
#
# 📌 THE HOT REGION IS NOT ONE ELEMENT. It is where a FRAME, a BUTTON and an
# EFFECT overlap -- three elements of different kinds stacked in the same band.
# That is consistent with their null result: they went looking for two families of
# tile (edge-only versus hot-everywhere) and found one continuous population, so
# the region has no character of its own.
#
# ⚠️ WHAT THIS DOES NOT SAY. It names what is THERE, not what is wrong. Their map
# already excludes local displacement in these tiles, so this is not a misplaced
# element; the inventory is offered as the next reader's starting point, not as a
# diagnosis. The residual's cause remains open.
#
# 📌 AND A CONTROL LIMIT OF THEIRS THAT CHANGES HOW ANY SLOPE READS: a known +2 px
# displacement localises perfectly but reads back +0.839, because the slope is a
# linearisation (residual ~ dx * gradient) that saturates once dx approaches the
# width of an edge. So their +1 px control gives localisation AND magnitude, the
# +2 px control gives localisation and SIGN only, and **any slope they report is a
# FLOOR on the displacement, never a ceiling**.