This branch predates CI on `main`. `cargo fmt --all` only; no behaviour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
97 lines
3.5 KiB
Rust
97 lines
3.5 KiB
Rust
//! Which T8aD header word, if any, separates the FOUR elements the port measures
|
|
//! as rendering too dark (`ptframe1`/`2` on the main menu, `ptframe3`/`4` on
|
|
//! `EXTRAS`) from the elements on the same two screens it measures as accurate?
|
|
//!
|
|
//! The control that matters: `pteff10` has max alpha 130 and no fully-opaque
|
|
//! pixel — the same "wholly semi-transparent" property the port proposed as the
|
|
//! reason the frames are special — and it renders nearly exact. So the separator
|
|
//! must put `pteff10` on the ACCURATE side.
|
|
//!
|
|
//! cargo run -p sylpheed-formats --example frame_vs_accurate_words
|
|
use std::path::PathBuf;
|
|
use sylpheed_formats::{pak::PakArchive, ui_layout};
|
|
|
|
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 mut rows: Vec<(String, usize, Vec<u32>)> = Vec::new();
|
|
for build in [5usize, 6] {
|
|
let by = ar.read(&ar.entries()[build]).expect("entry");
|
|
let b = ui_layout::parse_build(&by).expect("build");
|
|
let mut names: Vec<&String> = b.sprites.keys().collect();
|
|
names.sort();
|
|
for n in names {
|
|
let (off, size) = b.sprites[n];
|
|
let s = &by[off..(off + size).min(by.len())];
|
|
if s.len() < 48 || &s[0..4] != b"T8aD" {
|
|
continue;
|
|
}
|
|
let ws: Vec<u32> = (0..12)
|
|
.map(|k| u32::from_be_bytes([s[k * 4], s[k * 4 + 1], s[k * 4 + 2], s[k * 4 + 3]]))
|
|
.collect();
|
|
rows.push((n.clone(), build, ws));
|
|
}
|
|
}
|
|
let is_frame = |n: &str| n.starts_with("ptframe");
|
|
println!(
|
|
"{:<16} {:>5} +0x04 +0x08 +0x1C +0x2C",
|
|
"sprite", "build"
|
|
);
|
|
for (n, b, w) in &rows {
|
|
println!(
|
|
"{n:<16} {b:>5} {:08X} {:08X} {:08X} {:08X}{}",
|
|
w[1],
|
|
w[2],
|
|
w[7],
|
|
w[11],
|
|
if is_frame(n) { " <- TOO DARK" } else { "" }
|
|
);
|
|
}
|
|
println!("\nwords where every ptframe* agrees and NO other sprite takes that value:");
|
|
let frames: Vec<&(String, usize, Vec<u32>)> =
|
|
rows.iter().filter(|(n, _, _)| is_frame(n)).collect();
|
|
let mut any = false;
|
|
for k in 0..12 {
|
|
let v = frames[0].2[k];
|
|
if !frames.iter().all(|r| r.2[k] == v) {
|
|
continue;
|
|
}
|
|
if rows.iter().any(|(n, _, w)| !is_frame(n) && w[k] == v) {
|
|
continue;
|
|
}
|
|
println!(" word {k} (+0x{:02X}) = {v:08X}", k * 4);
|
|
any = true;
|
|
}
|
|
if !any {
|
|
println!(" NONE — no header word separates the four frames from the rest");
|
|
}
|
|
println!(
|
|
"\nper-bit check on +0x04 and +0x08 (a bit that is 1 on all frames, 0 on all others):"
|
|
);
|
|
let mut anyb = false;
|
|
for &k in &[1usize, 2] {
|
|
for bit in 0..32 {
|
|
let on = |v: u32| (v >> bit) & 1 == 1;
|
|
if frames.iter().all(|r| on(r.2[k]))
|
|
&& rows.iter().all(|(n, _, w)| is_frame(n) || !on(w[k]))
|
|
{
|
|
println!(" +0x{:02X} bit {bit} (0x{:X})", k * 4, 1u32 << bit);
|
|
anyb = true;
|
|
}
|
|
if frames.iter().all(|r| !on(r.2[k]))
|
|
&& rows.iter().all(|(n, _, w)| is_frame(n) || on(w[k]))
|
|
{
|
|
println!(
|
|
" +0x{:02X} bit {bit} (0x{:X}) INVERTED",
|
|
k * 4,
|
|
1u32 << bit
|
|
);
|
|
anyb = true;
|
|
}
|
|
}
|
|
}
|
|
if !anyb {
|
|
println!(" NONE");
|
|
}
|
|
}
|