re: runtime DATA SHEET reads the live weapon record (Route B, first capture)
Drove the retail game headless (Canary + lavapipe, vgamepad) to the Ready Room Arsenal and read the Gallery-Mode DATA SHEET for every weapon the 5%-progress save reveals. Two UI->field mappings are CONFIRMED against weapons whose values ARE on disc: Ammo Capacity == LoadingCount (9/9 exact matches) Max. Lock Ons == TriggerShotCount (FALCON 9AM 12 == wep_02; BUZZARD 22 == wep_04) That makes the panel an oracle for fields the disc leaves defaulted, and it is shown for undeveloped weapons too, so no points need spending. Recovered TriggerShotCount for wep_05 and wep_60 (both 4, on-disc absent), and bracketed the defaulted Power / MaximumRange via the Range/Damage letter classes. Ruled out first: the defaults are not in hidden/DefTables.pak (no WEAPON-schema objects there) nor in the localized GP_MAIN_GAME_* duplicates. Also adds the two analysis examples that produce the shopping list of defaulted fields, the screenshot harness used to drive the menus, and the evidence PNGs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
50
crates/sylpheed-formats/examples/default_owners.rs
Normal file
50
crates/sylpheed-formats/examples/default_owners.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
//! Scratch analysis: for one IDXD key, list every object that DECLARES it and
|
||||
//! whether it carries a value on disc or is left at the title-code default.
|
||||
//!
|
||||
//! Run: cargo run -p sylpheed-formats --example default_owners -- <KEY> [KEY...]
|
||||
|
||||
use sylpheed_formats::idxd::IdxdObject;
|
||||
use sylpheed_formats::pak::PakArchive;
|
||||
|
||||
fn is_number(s: &str) -> bool {
|
||||
let s = s.strip_suffix(['f', 'F']).unwrap_or(s);
|
||||
let t = s.strip_prefix(['-', '+']).unwrap_or(s);
|
||||
!t.is_empty() && t.chars().all(|c| c.is_ascii_digit() || c == '.')
|
||||
}
|
||||
fn is_key(s: &str) -> bool {
|
||||
!s.is_empty()
|
||||
&& s.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')
|
||||
&& s.chars().next().is_some_and(|c| c.is_ascii_alphabetic() || c == '_')
|
||||
&& !is_number(s)
|
||||
}
|
||||
fn is_value(s: &str) -> bool {
|
||||
is_number(s) || !is_key(s)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let root = std::env::var("SYLPHEED_DISC")
|
||||
.unwrap_or_else(|_| "/home/fabi/RE - Project Sylpheed/sylph_extract".into());
|
||||
let wanted: Vec<String> = std::env::args().skip(1).collect();
|
||||
let arc = PakArchive::open(std::path::Path::new(&root).join("dat/GP_MAIN_GAME_E.pak")).unwrap();
|
||||
|
||||
for e in arc.entries() {
|
||||
let Ok(bytes) = arc.read(e) else { continue };
|
||||
let Ok(obj) = IdxdObject::parse(&bytes) else { continue };
|
||||
let toks = obj.tokens().to_vec();
|
||||
let mut hits: Vec<String> = vec![];
|
||||
for (i, t) in toks.iter().enumerate() {
|
||||
if !wanted.iter().any(|w| w == t) {
|
||||
continue;
|
||||
}
|
||||
let valued = i > 0 && is_value(&toks[i - 1]);
|
||||
hits.push(if valued {
|
||||
format!("{t}={}", toks[i - 1])
|
||||
} else {
|
||||
format!("{t}=<DEFAULT>")
|
||||
});
|
||||
}
|
||||
if !hits.is_empty() {
|
||||
println!("0x{:08x} {:<44} {}", obj.schema_hash, obj.identity(), hits.join(" "));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user