re: partial field map inside the live definition object, and why the automation failed

Anchoring on a unit whose disc record sets a field locates it in the live object:
Size_X/Y/Z (+0x30/34/38) and HP (+0x54) confirmed across five capital ships and
the player fighter; +0x74 (0.8) and +0x84 (0.97) are probable ThrusterRatio and
ResistanceParalyze but rest on a single anchoring unit; +0x40 varies per unit and
is unidentified.

live_offsets.rs automates the correlation and currently produces one hit which is
false -- YawDragFactor 2.0 collided with the integer 2 at +0x0c stored as a
denormal. Causes recorded: get_f32 is unreliable on default-heavy IDXD records
because the value-before-key pairing shifts, and 96 words only reaches +0x180
while RadarRange/FCSRange sit beyond it. Next run dumps 512 words.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-12 20:36:57 +00:00
parent 3322202732
commit 892f1e3979
3 changed files with 151 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
//! Every key/value a named unit record actually sets on disc.
//!
//! The live definition object in guest RAM has no field names; to find where a
//! field like `HQRatio` sits inside it, anchor on a unit whose disc record DOES
//! set that field and look for the value. This prints those anchors.
//! Run: unit_fields <disc-root> <substring of ID>...
use sylpheed_formats::idxd::IdxdObject;
use sylpheed_formats::pak::PakArchive;
fn main() {
let disc = std::env::args().nth(1).expect("disc root");
let want: Vec<String> = std::env::args().skip(2).collect();
let pak = PakArchive::open(format!("{disc}/dat/GP_MAIN_GAME_E.pak")).expect("pak");
for entry in pak.entries() {
let Ok(bytes) = pak.read(entry) else { continue };
let Ok(obj) = IdxdObject::parse(&bytes) else { continue };
let Some(id) = obj.get_raw("ID") else { continue };
if !want.iter().any(|w| id.contains(w.as_str())) {
continue;
}
println!("=== {id} (schema {:08x})", obj.schema_hash);
// The pool interleaves VALUE before KEY (see the module docs), so the
// pairs read (t[i] = value, t[i+1] = key).
let t = obj.tokens();
let mut i = 0;
while i + 1 < t.len() {
println!(" {:<30} {}", t[i + 1], t[i]);
i += 2;
}
}
}