lsta: the count was never unreliable -- it counts sprites AND PRMD primitives
The module said "a few entries disagree with the actual frame count, so we walk by the T8aD magic instead". They do not disagree. An LSTA is a display list of inline elements that are either T8aD sprites or PRMD primitives (the flat coloured quad the UI bundles use to dim a scene), and the count at 0x04 counts both: across all 64 lists on the disc, count == T8aD + PRMD, with no exceptions. The six lists that looked wrong (GP_DEBRIEFING_PILOTLOG, GP_MISSION_SELECT, two language builds each) each hold exactly one primitive, which is the whole of the off-by-one. Also measured after the T8aD rectangle-list fix: all 1281 sprite frames decode, 100%. parse() still returns sprites and skips primitives -- that is the useful behaviour -- but the docs now say so instead of blaming the header. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,18 @@
|
||||
//! `LSTA` — a sprite list: a header followed by N inline [`T8aD`](crate::t8ad)
|
||||
//! frames concatenated back-to-back.
|
||||
//! `LSTA` — a display list: a header followed by N inline elements concatenated
|
||||
//! back-to-back, each either a [`T8aD`](crate::t8ad) sprite or a `PRMD`
|
||||
//! primitive (a flat coloured quad — the same primitive the UI bundles use to
|
||||
//! dim a scene).
|
||||
//!
|
||||
//! A `count` lives at `@0x04`, but a few entries disagree with the actual frame
|
||||
//! count, so we walk by the `T8aD` magic instead (robust) and decode each frame
|
||||
//! from its slice up to the next frame (or end).
|
||||
//! The `count` at `@0x04` is **exact, and counts both kinds**: across all 64
|
||||
//! lists on the disc, `count == T8aD frames + PRMD primitives` with no
|
||||
//! exceptions (measured 2026-08-11). An earlier note here said "a few entries
|
||||
//! disagree with the actual frame count" — they do not; that comparison was
|
||||
//! counting sprites against a total that includes primitives.
|
||||
//!
|
||||
//! [`parse`] walks by magic and returns the **sprites**, deliberately skipping
|
||||
//! `PRMD` entries, so its result length is `count` only for lists that hold no
|
||||
//! primitives. Six lists do (in `GP_DEBRIEFING_PILOTLOG`, `GP_MISSION_SELECT`),
|
||||
//! each with exactly one.
|
||||
|
||||
use crate::t8ad::{self, T8adImage, T8AD_MAGIC};
|
||||
|
||||
@@ -15,8 +24,9 @@ pub fn is_lsta(bytes: &[u8]) -> bool {
|
||||
bytes.len() >= 4 && bytes[0..4] == LSTA_MAGIC
|
||||
}
|
||||
|
||||
/// Decode all inline T8aD frames. Frames that don't decode (unsupported T8aD
|
||||
/// variant) are skipped. Returns `None` only for non-LSTA input.
|
||||
/// Decode the inline T8aD sprites, skipping `PRMD` primitives. Returns `None`
|
||||
/// only for non-LSTA input. Every one of the 1 281 sprite frames on the disc
|
||||
/// decodes (measured 2026-08-11, after the T8aD rectangle-list fix).
|
||||
pub fn parse(bytes: &[u8]) -> Option<Vec<T8adImage>> {
|
||||
if !is_lsta(bytes) {
|
||||
return None;
|
||||
|
||||
Reference in New Issue
Block a user