Closes a negative of mine whose failed assumption I had named: I searched for an 8-record btn-named build in an archive of its own, assuming DIFFICULTY's four items pair with f variants the way GP_TITLE's screens do. It has its own prefix and is not a GamePart screen at all. Three independent routes agree. The image lists DLG_SELECT_DIFFICULTY among the DLG_* dialog names at 0x820A41BB, and GP_DIFFICULTY appears zero times. GP_DIALOG entries 2/3 are the only builds there with pcbtn00..03 -- four buttons at design rows 259/329/399/469, spacing 70, an EN/JP pair. And my capture of the running screen puts its four rows within 4 px of those, with spacing 70.5/69.5/70.0 against the disc's 70/70/70. Reach stated: the entries are identified by button count and geometry, not by a binding from the DLG_ name to a pak entry. No such binding was found. Also notes the consequence for Q6's count-match: NEW GAME opens a DIALOG from an external archive, which still matches the count but is not the same category as OPTIONS or TUTORIAL opening a GamePart. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
67 lines
2.8 KiB
Rust
67 lines
2.8 KiB
Rust
//! 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 sylpheed_formats::{pak::PakArchive, ui_layout};
|
|
use std::path::PathBuf;
|
|
|
|
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<String> = 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<String> = 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");
|
|
}
|