This branch predates CI on `main`. `cargo fmt --all` only; no behaviour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
70 lines
3.0 KiB
Rust
70 lines
3.0 KiB
Rust
//! Where does the `DIFFICULTY` screen live?
|
|
//!
|
|
//! `boot-config-and-gamepart-registry.md` records a count-match — "Ⓑ = event 0,
|
|
//! four menu items load an external archive, EXTRAS stays inside GP_TITLE" —
|
|
//! explicitly as an observation, not a decode. The disc can test half of it:
|
|
//! OPTIONS, LOAD GAME and TUTORIAL have their own paks, and EXTRAS' two items
|
|
//! have GP_MISSION_SELECT / GP_MOVIE_THEATER while EXTRAS itself is GP_TITLE
|
|
//! entries 6/9. NEW GAME is the fourth, and there is no GP_DIFFICULTY.pak.
|
|
//!
|
|
//! So: which archive holds a build with EASY / NORMAL / HARD buttons?
|
|
//!
|
|
//! CONTROL: the same scan must find the EXTRAS build in GP_TITLE, whose location
|
|
//! is independently known (entries 6/9, buttons ptbtn11/12/13).
|
|
//!
|
|
//! cargo run -p sylpheed-formats --example find_difficulty_build
|
|
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 dat = root.join("dat");
|
|
let mut paks: Vec<_> = std::fs::read_dir(&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 found_extras = false;
|
|
for p in &paks {
|
|
let Ok(ar) = PakArchive::open(p) else {
|
|
continue;
|
|
};
|
|
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 btns: Vec<&String> = b
|
|
.records
|
|
.keys()
|
|
.filter(|n| n.starts_with("ptbtn") || n.contains("btn"))
|
|
.collect();
|
|
if btns.len() != 8 {
|
|
continue;
|
|
}
|
|
let name = p.file_name().unwrap().to_string_lossy();
|
|
// CONTROL: the known MAIN MENU build (11 records, so this control is now vacuous) must show up.
|
|
if name == "GP_TITLE.pak" && (i == 5 || i == 8) {
|
|
found_extras = true;
|
|
println!("CONTROL {name} entry {i}: {} button records — the known MAIN MENU build (11 records, so this control is now vacuous)",
|
|
btns.len());
|
|
}
|
|
// any build outside GP_TITLE with a small button set is a candidate
|
|
if name != "GP_TITLE.pak" {
|
|
let mut names: Vec<String> = btns.iter().map(|s| (*s).clone()).collect();
|
|
names.sort();
|
|
println!(
|
|
" {name:28} entry {i:3} {} buttons {:?}",
|
|
btns.len(),
|
|
&names[..names.len().min(8)]
|
|
);
|
|
}
|
|
}
|
|
}
|
|
println!("\ncontrol {} — the known MAIN MENU build (11 records, so this control is now vacuous) was {}found",
|
|
if found_extras { "PASSED" } else { "FAILED" },
|
|
if found_extras { "" } else { "NOT " });
|
|
}
|