//! Is `GP_DIALOG` entry 2 the `DLG_SELECT_DIFFICULTY` screen? //! //! The image lists `DLG_SELECT_DIFFICULTY` among the `DLG_*` names at //! `0x820A41BB`, so DIFFICULTY is a DIALOG, not a GamePart screen with its own //! pak — which is why a search for an 8-record `btn` build in a difficulty-named //! archive found nothing. `GP_DIALOG` entry 2 carries `pcbtn00`..`03`: four //! buttons, matching EASY / NORMAL / HARD / BACK. //! //! CONTROL: `GP_TITLE` entry 5's five buttons must come back at the rows the disc //! is independently known to place them (162/242/322/401/482, spacing 80). //! //! cargo run -p sylpheed-formats --example dialog_button_rows use std::path::PathBuf; use sylpheed_formats::{pak::PakArchive, ui_layout}; fn rows(ar: &PakArchive, entry: usize, what: &str) { let Ok(by) = ar.read(&ar.entries()[entry]) else { return; }; let Some(b) = ui_layout::parse_build(&by) else { return; }; let mut v: Vec<(i32, String)> = b .elements .iter() .filter(|e| { let n = &e.name; (n.starts_with("pcbtn") || n.starts_with("ptbtn")) && !n.contains('f') }) .map(|e| { ( e.rest().map(|k| k.y).unwrap_or(e.pivot_y as i32), e.name.clone(), ) }) .collect(); v.sort_by_key(|r| r.0); println!("\n{what} (entry {entry}):"); for (y, n) in &v { println!(" y {y:5} {n}"); } if v.len() > 1 { let sp: Vec = v.windows(2).map(|w| w[1].0 - w[0].0).collect(); println!(" spacing {sp:?}"); } } fn main() { let root = PathBuf::from(std::env::var("SYLPHEED_DISC").expect("SYLPHEED_DISC")); let t = PakArchive::open(root.join("dat/GP_TITLE.pak")).expect("GP_TITLE"); rows( &t, 5, "CONTROL: GP_TITLE main menu (must be 162/242/322/401/482)", ); let d = PakArchive::open(root.join("dat/GP_DIALOG.pak")).expect("GP_DIALOG"); rows(&d, 2, "GP_DIALOG candidate for DLG_SELECT_DIFFICULTY"); rows(&d, 3, "GP_DIALOG entry 3 (the pair)"); }