t8ad: a surface is a list of sub-rectangles, not a 256 grid -- disc decode 96% -> 100%
The "~15% deferred variants" were not variants. Auditing every T8aD on the disc gave 19216 surfaces, 18442 decoding (96.0%) and 774 failing in two clusters: GP_DIALOG strips declaring 524x63 with a "tile count" of 1 or 2 instead of 3, and small textures in the six *2D language paks whose pixels ran past the end of the file. Both fall out of the per-tile header, which is not opaque flags: it is four BE u32 -- dst X, dst Y, width, height. A 15x18 icon stores a 13x18 rectangle at (1,0); pdmes010 stores (59,6,256,54) and (315,6,149,54), the second beginning exactly 16 + 256*54*4 bytes after the first. So 0x1c is a RECTANGLE COUNT and the 256-grid reading was an accident of most surfaces being stored as full-width bands. Parser rewritten to that model, still refusing to guess: a rectangle must fit the declared surface and its pixels must fit the file, else None. Disc decode is now 19216/19216 = 100.00%. Two test fixtures were built to the old model and are corrected rather than worked around. lsta's t8ad_frame wrote NO offset-table entry, so the decoder read "pixels" from inside the header -- the test passed only because it checked dimensions alone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -48,12 +48,21 @@ pub fn parse(bytes: &[u8]) -> Option<Vec<T8adImage>> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// A faithful one-rectangle T8aD frame: base header, a 1-entry offset table,
|
||||
/// then the rectangle header (dst 0,0, size w×h) and its pixels. (Before
|
||||
/// 2026-08-11 this fixture wrote no offset-table entry at all and the decoder
|
||||
/// read "pixels" from inside the header — the test only ever checked the
|
||||
/// dimensions, so it passed anyway.)
|
||||
fn t8ad_frame(w: u32, h: u32) -> Vec<u8> {
|
||||
let mut b = vec![0u8; 64];
|
||||
let mut b = vec![0u8; 0x2c];
|
||||
b[0..4].copy_from_slice(&T8AD_MAGIC);
|
||||
b[0x14..0x18].copy_from_slice(&w.to_be_bytes());
|
||||
b[0x18..0x1c].copy_from_slice(&h.to_be_bytes());
|
||||
b[0x1c..0x20].copy_from_slice(&1u32.to_be_bytes());
|
||||
b.extend_from_slice(&0x30u32.to_be_bytes()); // offset table → rect at 0x30
|
||||
for v in [0u32, 0, w, h] {
|
||||
b.extend_from_slice(&v.to_be_bytes()); // dst X, dst Y, width, height
|
||||
}
|
||||
b.extend_from_slice(&vec![0x80u8; (w * h * 4) as usize]);
|
||||
b
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user