Answers the port's ask about ptframe1/ptframe2, whose residual is uniquely higher on flat pixels than edges and signed one direction -- a body-intensity difference. Prior work covers .prm primitives and a refuted T8aD +0x04 bit; neither covers a .t32 element. All 15 words of the 60-byte declaration entry are read: 3 are the name, 8 constant, the rest kind, focus index, position and pivot. The frames are kind 0, identical to every other plain sprite. One candidate found and refuted by myself: T8aD +0x08 is the only word where both frames agree uniquely on that screen, at 0x8050 -- but 38 sprites carry it disc-wide, only 8 named frame, and the high byte tracks the archive. It is an atlas/format word, not a mode. Also records a false positive of my own test: +0x00 and +0x08 first read as 'separating the frames' because those words are the name string. So any blend the port picks is authored. Reach: not looked at the executable's draw path, where a mode selected in code rather than data would live. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
49 lines
2.4 KiB
Rust
49 lines
2.4 KiB
Rust
//! Does a textured element's declaration carry anything that distinguishes the
|
|
//! two FRAME elements from every other element on the main menu?
|
|
//!
|
|
//! `sylpheed-port` asks for the blend/alpha mode of `ptframe1`/`ptframe2`. Prior
|
|
//! work is on `.prm` PRIMITIVES (`ui-prm-blend-mode.md`, undecodable with reach —
|
|
//! no field, the declaration words are constant) and on a refuted `T8aD +0x04`
|
|
//! bit. Neither covers a `.t32` element's own declaration entry, which is 60
|
|
//! bytes and mostly unread.
|
|
//!
|
|
//! This dumps every declaration entry on the menu and reports, per 4-byte word,
|
|
//! whether the two frames share a value that no other element has. A word that
|
|
//! separates exactly those two is a candidate; one that does not, is not.
|
|
//!
|
|
//! cargo run -p sylpheed-formats --example decl_entry_diff
|
|
use sylpheed_formats::{pak::PakArchive, ui_layout};
|
|
use std::path::PathBuf;
|
|
|
|
const AT: usize = 0x20;
|
|
const N: usize = 60;
|
|
|
|
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");
|
|
let names: Vec<String> = b.elements.iter().map(|e| e.name.clone()).collect();
|
|
let frames: Vec<usize> = names.iter().enumerate()
|
|
.filter(|(_, n)| n.starts_with("ptframe")).map(|(i, _)| i).collect();
|
|
println!("{} elements; frames at indices {:?}", names.len(), frames);
|
|
|
|
let word = |i: usize, w: usize| -> u32 {
|
|
let o = AT + i * N + w * 4;
|
|
u32::from_be_bytes([by[o], by[o + 1], by[o + 2], by[o + 3]])
|
|
};
|
|
println!("\nper-word: does a value separate EXACTLY the two frames?");
|
|
for w in 0..N / 4 {
|
|
let fv: Vec<u32> = frames.iter().map(|&i| word(i, w)).collect();
|
|
let same_in_frames = fv.windows(2).all(|p| p[0] == p[1]);
|
|
let others: Vec<u32> = (0..names.len()).filter(|i| !frames.contains(i))
|
|
.map(|i| word(i, w)).collect();
|
|
let unique = same_in_frames && !others.contains(&fv[0]);
|
|
let distinct = { let mut v: Vec<u32> = (0..names.len()).map(|i| word(i, w)).collect();
|
|
v.sort_unstable(); v.dedup(); v.len() };
|
|
println!(" +0x{:02X} frames {:?} distinct values {distinct:2}{}",
|
|
w * 4, fv.iter().map(|v| format!("{v:08X}")).collect::<Vec<_>>(),
|
|
if unique { " <- SEPARATES THE FRAMES" } else { "" });
|
|
}
|
|
}
|