From 55e1fe3783cb8ed4d2661c61cd137c9e61cd2e03 Mon Sep 17 00:00:00 2001 From: "Claude (auto-RE)" Date: Wed, 12 Aug 2026 03:32:58 +0000 Subject: [PATCH] re: the break-composite alarm is false -- the container stores 3-6 copies of each buffer locate_draw counts copies of a captured buffer. The f105 parts _rou_f105_break claims exist 3-6 times over (the 2336-vert one: 6 direct AND 6 mirrored), and every live LOD checked is anchored on a direct, byte-identical copy -- so the composite taking the drawn copy costs nothing. This also calibrates the oracle: 'exact' (anchored at the drawn offset) is stricter than correct, so 45/46 is a lower bound. Open: a resource landing on a MIRRORED copy would be a real defect invisible to every count-based metric. Co-Authored-By: Claude Opus 5 (1M context) --- .../sylpheed-formats/examples/locate_draw.rs | 53 +++++++++++++++++++ docs/re/structures/xbg7-mesh.md | 39 +++++++++++--- 2 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 crates/sylpheed-formats/examples/locate_draw.rs diff --git a/crates/sylpheed-formats/examples/locate_draw.rs b/crates/sylpheed-formats/examples/locate_draw.rs new file mode 100644 index 0000000..0d6f1ca --- /dev/null +++ b/crates/sylpheed-formats/examples/locate_draw.rs @@ -0,0 +1,53 @@ +//! How many copies of a captured buffer does a container hold? +//! +//! The twins showed that two resources decoding to one buffer can mean the +//! container really holds two (mirrored) copies and our scan found only one. +//! This asks that question for any draw: give it a `vbase`, and it reports every +//! offset whose leading vertices match the draw's dumped positions — directly, and +//! X-mirrored. +//! +//! Usage: locate_draw ... +use sylpheed_formats::ship_capture::{parse_capture, parse_drawlog}; + +fn main() { + let a: Vec = std::env::args().collect(); + let bytes = std::fs::read(&a[1]).expect("container"); + let text = std::fs::read_to_string(&a[2]).expect("log"); + let mut draws = parse_capture(&text); + if draws.is_empty() { + draws = parse_drawlog(&text); + } + let be = |at: usize| f32::from_be_bytes(bytes[at..at + 4].try_into().unwrap()); + + for want in &a[3..] { + let vb = u32::from_str_radix(want.trim_start_matches("0x"), 16).expect("hex vbase"); + let Some(d) = draws.iter().find(|d| d.vbase == vb) else { + println!("vbase 0x{vb:08X}: not in this log"); + continue; + }; + let n = d.pos.len().min(8); + let mut direct = Vec::new(); + let mut mirror = Vec::new(); + for o in (0..bytes.len().saturating_sub(12 + 64 * 24)).step_by(4) { + for (flip, out) in [(1.0f32, &mut direct), (-1.0f32, &mut mirror)] { + let hit = (0..n).all(|k| { + let at = o + k * 24; + (be(at) - flip * d.pos[k][0]).abs() <= 1e-4 + && (be(at + 4) - d.pos[k][1]).abs() <= 1e-4 + && (be(at + 8) - d.pos[k][2]).abs() <= 1e-4 + }); + if hit { + out.push(o); + } + } + } + println!( + "vbase 0x{vb:08X} vcount={}: {} direct copy/copies {:x?}, {} mirrored {:x?}", + d.vcount, + direct.len(), + &direct[..], + mirror.len(), + &mirror[..] + ); + } +} diff --git a/docs/re/structures/xbg7-mesh.md b/docs/re/structures/xbg7-mesh.md index d904499..ae2bd71 100644 --- a/docs/re/structures/xbg7-mesh.md +++ b/docs/re/structures/xbg7-mesh.md @@ -898,14 +898,37 @@ systematic mis-anchor is invisible to it because it is consistent. Where the two disagree, the capture wins. Full suite green including the disc- and ISO-gated ship tests. -❔ **Still open — grouped composites.** `_rou_f105_break` (the f105 destruction -model) claims **twelve consecutive** drawn buffers, each matching one of its -sub-mesh vertex counts exactly, while `f105_bdy_01_m`, `f105_bdy_03_m`, -`f105_eng_01_m` — resources of exactly those sizes — are anchored elsewhere. -Distinct assignment does not touch this: the grouped-pool path is excluded. The -question is the twins' question again — does the container hold two copies of -each of those buffers, or one that both names should share? The same -mirror/duplicate test would answer it. +✅ **Closed — the grouped composite is a false alarm.** `_rou_f105_break` (the +f105 destruction model) claims **twelve consecutive** drawn buffers while +`f105_bdy_01_m`, `f105_bdy_03_m` and `f105_eng_01_m` sit elsewhere, which looked +like the twins' bug in the grouped-pool path. It is not. +`examples/locate_draw.rs` counts how many copies of a captured buffer a container +holds, directly and X-mirrored: + +| drawn buffer | vcount | direct copies | mirrored copies | +|---|---|---|---| +| `0x1bf596c` | 2446 | **3** | 0 | +| `0x1c0fe2c` | 2336 | **6** | **6** | +| `0x1c211cc` | 1402 | **4** | 0 | +| `0x1bf40f4` | 261 | 1 | 0 | + +The container stores these parts several times over, and every live LOD checked +(`f105_bdy_01_m` at `0x1ecb4c0`, `f105_bdy_03_m` at `0x1f902a4`, `f105_eng_01_m` +at `0x1ffb884`) is anchored on a **direct** copy — byte-identical geometry to the +one the engine drew. So the composite taking "the drawn" copy costs nothing: the +decode is the same vertices either way. (The draws use the ordinary ship shader +`0xEEA84C59D7F95371`, the same one as the validated e106 hull draws, so these are +intact-ship draws, not debris.) + +⚠️ **This also calibrates the oracle metric.** "Exact" in the tables above means +*anchored at the offset the engine drew from*, which is stricter than correct: a +resource anchored on an identical copy is equally right. The 45/46 figure stands +as a lower bound, and an "unclaimed" row is not automatically a defect. + +❔ What the copy counts *do* leave open: with six direct and six mirrored copies +of one buffer, a resource landing on a **mirrored** copy would be a real defect +and would look identical to a correct decode in every count-based metric. Only a +capture (or the twin-pair invariant) can catch it. Not settled: `e106_brg_01_b_02` ≡ `e106_brg_01_l` (51 verts). A second 51-vertex `vbase` exists in the logs but is **not** from this container, and the container