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) <noreply@anthropic.com>
This commit is contained in:
53
crates/sylpheed-formats/examples/locate_draw.rs
Normal file
53
crates/sylpheed-formats/examples/locate_draw.rs
Normal file
@@ -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 <container.xpr> <capture.log> <vbase-hex>...
|
||||
use sylpheed_formats::ship_capture::{parse_capture, parse_drawlog};
|
||||
|
||||
fn main() {
|
||||
let a: Vec<String> = 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[..]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user