Files
Sylpheed/crates/sylpheed-formats/examples/splash_blend_check.rs
MechaCat02 62376dd4a1 style: rustfmt sweep — 107 files the lint gate never saw
This branch predates CI on `main`. `cargo fmt --all` only; no behaviour.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 16:34:40 +02:00

98 lines
3.9 KiB
Rust

//! Out-of-sample test of the `T8aD +0x04` blend bit on the **boot splashes**.
//!
//! `ui-blend-mode-decoded.md` established the field on 35 elements over three
//! screens (GP_TITLE entries 2, 4, 5, 6). The two splashes -- entries 10 and 11 --
//! were NOT in that sample, and they are the screens the 2026-09-01 play-test
//! says are wrong.
//!
//! The oracle for these two screens is `data/splash-draw-pass-census.txt`: over
//! **1048 draws of frames 4..226**, covering both splashes end to end, the only
//! blend states submitted are `0x00010001` (the clear) and `0x07010701`
//! (source-over). Additive, `0x01010101`, appears **zero** times.
//!
//! PRE-REGISTERED PREDICTION, written before reading the disc: if the bit is the
//! blend selector and it generalises off its training screens, then every sprite
//! in entries 10 and 11 must report `additive = false`. Any `true` is a
//! discrepancy the field has to answer for.
//!
//! cargo run --release -p sylpheed-formats --example splash_blend_check
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 additive = 0usize;
let mut alpha_over = 0usize;
let mut no_header = 0usize;
for entry in [10usize, 11] {
let by = ar.read(&ar.entries()[entry]).expect("entry");
let Some(b) = ui_layout::parse_build(&by) else {
println!("entry {entry}: not a build");
continue;
};
println!(
"\n## GP_TITLE entry {entry} -- {} elements, {} sprites",
b.elements.len(),
b.sprites.len()
);
// Every sprite the bundle carries, not only those a top-level element
// names: a focused variant is reached through `focus_link` and would
// otherwise be invisible to this check.
let mut names: Vec<&String> = b.sprites.keys().collect();
names.sort();
for n in names {
match ui_layout::blend_additive_by_name(&b, &by, n) {
Some(true) => {
additive += 1;
println!(
" {n:<26} word04=0x{:08X} ADDITIVE",
ui_layout::header_word_04_by_name(&b, &by, n).unwrap()
);
}
Some(false) => {
alpha_over += 1;
println!(
" {n:<26} word04=0x{:08X} alpha-over",
ui_layout::header_word_04_by_name(&b, &by, n).unwrap()
);
}
None => {
no_header += 1;
println!(" {n:<26} (no T8aD header)");
}
}
}
}
println!("\nadditive={additive} alpha-over={alpha_over} no-header={no_header}");
println!("oracle (splash-draw-pass-census.txt, 1048 draws): additive draws = 0");
if additive == 0 {
println!("PREDICTION HELD -- the bit agrees with the capture on both splashes");
} else {
println!(
"PREDICTION FAILED -- {additive} sprite(s) claim additive, \
the capture submits none"
);
}
// Control: this harness must be able to REPORT additive, or "additive=0"
// is a property of the harness and not of the splashes. Entry 6 is a screen
// the oracle measures as mixed.
let by6 = ar.read(&ar.entries()[6]).expect("entry 6");
let b6 = ui_layout::parse_build(&by6).expect("build 6");
let c_add = b6
.sprites
.keys()
.filter(|n| ui_layout::blend_additive_by_name(&b6, &by6, n) == Some(true))
.count();
println!(
"control -- entry 6 through the SAME code path reports additive={c_add} \
(must be > 0): {}",
if c_add > 0 { "PASS" } else { "FAIL" }
);
}