re(xbg7): a capture names a never-decoding family, and the cause is mixed strides in one pool
capture_ib_truth now proposes an identity for each drawn buffer our decoder cannot place, by matching (vertex, index) counts against declared-but-not-decoded resources. That identified n201_01/_02/_03 in Stage_S02.xpr — three of the 63 resources that decode in no container — and the capture pins all four sub-meshes: #0 vb 0x32BA71C ib 0x32B39FC 4464 idx 777 v stride 24 #1 vb 0x32BEFF4 ib 0x32B5CDC 4464 idx 869 v stride 24 #2 vb 0x32C416C ib 0x32B7FBC 576 idx 192 v stride 24 #3 vb 0x32C536C ib 0x32B843C 4464 idx 869 v stride 28 <- different The layout matches our assumptions exactly (tight index packing, last buffer flush against vb0 so pad 0, span 27936 == align4-summed markers, contiguous vertex buffers, max index == verts-1 everywhere). The defect is that sub-mesh #3 has a different stride AND its own vertex shader: anchor_grouped_meshes parses one declaration per resource and applies its stride to every sub-mesh, so it reads #3 out of phase (372 non-finite position components of 2607), and since the pivot is the largest index count with ties going to the last marker, the pivot IS that sub-mesh — so the whole resource is declined. Also adds examples/miss_targets.rs (which container to aim a capture at): 63 resources decode nowhere, 58 of them in exactly one container, clustering as Stage_S16 21 (e901_wing_05_*), ptc_pack 12, Base 6, then per-stage n2xx groups. Flying stage 16 did not draw the e901 wings — the container is resident but the unit must also be on screen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NptfmpjdpNCKEez6d2xvA9
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
//!
|
||||
//! Usage:
|
||||
//! cargo run --release --example capture_ib_truth -- <Stage_SNN.xpr> <capture.log>...
|
||||
use sylpheed_formats::mesh::Xbg7Model;
|
||||
use sylpheed_formats::mesh::{debug_resource_params, xbg7_resource_names, Xbg7Model};
|
||||
use sylpheed_formats::ship_capture::{parse_capture, CapturedDraw};
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -113,6 +113,25 @@ fn main() {
|
||||
}
|
||||
println!("decoded {} resources, {} distinct vertex offsets\n", models.len(), by_off.len());
|
||||
|
||||
// Declared-but-not-decoded resources, indexed by their first marker's
|
||||
// (vertex, index) counts. A drawn buffer our decoder cannot name is the one
|
||||
// thing a capture can give the residual misses: ground truth for where the
|
||||
// block actually is. Matching on counts is enough to propose an identity —
|
||||
// then `debug_try_anchor` at that offset says which gate rejects it.
|
||||
let decoded_names: std::collections::HashSet<String> =
|
||||
models.iter().map(|m| m.name.clone()).collect();
|
||||
let mut undecoded_by_counts: HashMap<(usize, usize), Vec<String>> = HashMap::new();
|
||||
for n in xbg7_resource_names(&bytes) {
|
||||
if decoded_names.contains(&n) {
|
||||
continue;
|
||||
}
|
||||
if let Some((markers, _)) = debug_resource_params(&bytes, &n) {
|
||||
if let Some(&(v, i)) = markers.first() {
|
||||
undecoded_by_counts.entry((v, i)).or_default().push(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── The report: one row per drawn BUFFER, aggregating its index batches.
|
||||
let mut per_buf: HashMap<u32, (usize, Vec<sylpheed_formats::ship_capture::CapturedIndexBuffer>, u32)> =
|
||||
HashMap::new();
|
||||
@@ -177,7 +196,14 @@ fn main() {
|
||||
.map(|(n, p, i)| format!("{n}(v{p},i{i})"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" "))
|
||||
.unwrap_or_else(|| "-".into())
|
||||
.unwrap_or_else(|| {
|
||||
// Nothing of ours sits here — is it a resource that never
|
||||
// decodes? Propose it by (vertex, index) counts.
|
||||
undecoded_by_counts
|
||||
.get(&(*vcount as usize, total as usize))
|
||||
.map(|v| format!("MISSED? {}", v.join(" ")))
|
||||
.unwrap_or_else(|| "-".into())
|
||||
})
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user