//! 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" }); }