//! Where is the `DIFFICULTY` screen? Search by NAME, not by structure. //! //! A previous pass searched every pak for a build with exactly 8 `btn`-named //! records, on the assumption that DIFFICULTY's four items (EASY / NORMAL / HARD //! / BACK) pair with `f` focus variants the way GP_TITLE's screens do. Nothing //! plausible turned up, and the assumption was mine — recorded as a negative //! narrower than "not found" (data/gp-title-holds-three-button-screens.txt). //! //! This drops the structural assumption and looks for the words instead, across //! every sprite AND record name in every build on the disc. //! //! CONTROL: the same scan must find `ptbtn11` in GP_TITLE — a name whose home is //! independently known — when asked for it. A name scan that finds nothing //! proves nothing unless it can find something. //! //! cargo run -p sylpheed-formats --example find_difficulty_names use std::path::PathBuf; use sylpheed_formats::{pak::PakArchive, ui_layout}; const WANTED: &[&str] = &["easy", "normal", "hard", "diff", "level", "rank"]; fn main() { let root = PathBuf::from(std::env::var("SYLPHEED_DISC").expect("SYLPHEED_DISC")); let mut paks: Vec<_> = std::fs::read_dir(root.join("dat")) .expect("dat") .filter_map(|e| e.ok().map(|e| e.path())) .filter(|p| p.extension().map(|x| x == "pak").unwrap_or(false)) .collect(); paks.sort(); let mut control = false; let mut hits = 0usize; for p in &paks { let Ok(ar) = PakArchive::open(p) else { continue; }; let pname = p.file_name().unwrap().to_string_lossy().to_string(); for (i, e) in ar.entries().iter().enumerate() { let Ok(by) = ar.read(e) else { continue }; let Some(b) = ui_layout::parse_build(&by) else { continue; }; let all: Vec = b.sprites.keys().chain(b.records.keys()).cloned().collect(); if pname == "GP_TITLE.pak" && all.iter().any(|n| n.contains("ptbtn11")) { control = true; } let m: Vec<&String> = all .iter() .filter(|n| { let l = n.to_lowercase(); WANTED.iter().any(|w| l.contains(w)) }) .collect(); if !m.is_empty() { hits += 1; let mut s: Vec = m.iter().map(|x| (*x).clone()).collect(); s.sort(); s.dedup(); println!(" {pname:28} entry {i:3} {:?}", &s[..s.len().min(6)]); } } } println!( "\ncontrol (found ptbtn11 in GP_TITLE): {}", if control { "PASSED" } else { "FAILED" } ); println!("{hits} build(s) carried a difficulty-ish name"); }