//! A PREDICTION, written before the capture that tests it. //! //! `blend_vs_t8ad_bit` finds that `T8aD +0x04` bit `0x02` separates additive from //! alpha-over on all 35 elements whose blend has been measured off the GPU, and //! that no other bit of the 48-byte header does. That is a fit to three screens. //! //! The developer splash (`GP_TITLE` entries 10 and 13) has **never been captured** //! and is one of the five screens the port ships. This prints what the bit says //! its elements should be, so the capture can falsify it rather than confirm it. //! //! Takes an archive and a build list, so the prediction can be written for any //! screen -- including one in a DIFFERENT pak, which is the sharper test: the //! splash predicts alpha-over for both its elements and so can only fail, never //! discriminate, while a screen with a predicted MIX can do both. //! //! cargo run -p sylpheed-formats --example blend_prediction_splash //! cargo run -p sylpheed-formats --example blend_prediction_splash -- GP_OPTIONS 0 1 2 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 args: Vec = std::env::args().skip(1).collect(); let pak = args .iter() .find(|a| a.parse::().is_err()) .cloned() .unwrap_or_else(|| "GP_TITLE".to_string()); let ar = PakArchive::open(root.join(format!("dat/{pak}.pak"))).expect("pak"); let builds: Vec = args.iter().filter_map(|a| a.parse().ok()).collect(); let builds = if builds.is_empty() { (0..ar.entries().len()).collect() } else { builds }; for e in builds { let Ok(by) = ar.read(&ar.entries()[e]) else { continue; }; let Some(b) = ui_layout::parse_build(&by) else { continue; }; println!("=== {pak} entry {e} ==="); 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() < 8 || &s[0..4] != b"T8aD" { continue; } let w = u32::from_be_bytes([s[4], s[5], s[6], s[7]]); println!( "{n:<26} +0x04 = {w:08X} bit 0x02 {} PREDICT {}", if w & 2 != 0 { "SET " } else { "clear" }, if w & 2 != 0 { "ADDITIVE" } else { "alpha-over" } ); } println!(); } }