pool_window.rs shows the Destroyer's raw tokens: "200.0" "Size_X" "Size_Y" "2000.0" "Size_Z" -- Size_Y is a bare key, so the 13 runtime values recovered earlier are real defaults, not a reader artefact. The filler reads each size field through sub_822FC5A8, which loads f31 from 0x8209fd28 = 0.0 at entry and returns it on a pool miss, then stores to +52. Nothing else in the 15876-byte filler writes +52, so the definition leaves a defaulted Size_Y at 0.0 and the runtime 200 is written later. Two corrections: the +48/+52/+56 comparison block builds a size-class bitmask against 1000.0 (constant 0x8209fd20), not a has-value mask; and both earlier Size_Y derivation candidates are refuted (one is a conditional pick, the other multiplies into a different struct). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
30 lines
1.2 KiB
Rust
30 lines
1.2 KiB
Rust
//! Raw token sequence around a key, for one record — the ground truth for
|
|
//! "is this field actually defaulted, or is our reader missing it?"
|
|
//! Run: pool_window <disc-root> <ID substring> <key>
|
|
use sylpheed_formats::idxd::IdxdObject;
|
|
use sylpheed_formats::pak::PakArchive;
|
|
fn main() {
|
|
let disc = std::env::args().nth(1).unwrap();
|
|
let want = std::env::args().nth(2).unwrap();
|
|
let key = std::env::args().nth(3).unwrap();
|
|
let pak = PakArchive::open(format!("{disc}/dat/GP_MAIN_GAME_E.pak")).unwrap();
|
|
for e in pak.entries() {
|
|
let Ok(b) = pak.read(e) else { continue };
|
|
let Ok(o) = IdxdObject::parse(&b) else { continue };
|
|
let Some(id) = o.get_raw("ID") else { continue };
|
|
if !id.contains(&want) { continue; }
|
|
let t = o.tokens();
|
|
println!("=== {id} get_f32({key}) = {:?}", o.get_f32(&key));
|
|
for (i, tok) in t.iter().enumerate() {
|
|
if tok == &key {
|
|
let lo = i.saturating_sub(6);
|
|
let hi = (i + 7).min(t.len());
|
|
for j in lo..hi {
|
|
println!(" [{j}]{} {:?}", if j == i { " <-- key" } else { " " }, t[j]);
|
|
}
|
|
println!();
|
|
}
|
|
}
|
|
}
|
|
}
|