Bound the last region by core_data's constant trailer
Comparing all 27 levels byte-for-byte from the end: the last 231,952 bytes (0x38A10) of every level's core_data are identical. Level-specific content therefore ends at len - 0x38A10, which is a real bound for the final region and is not core_data.len(). This closes shrub. Across the 24 levels that have a shrub region the bound gives 24,442,928 bytes total, and the disc test asserts on every level that the region ends strictly inside the lump rather than at its end. What the trailer is remains unestablished -- fixed data, or padding from a fixed-size decompression buffer -- but it is constant, which is all a bound needs. The data between the last shrub class and the trailer is high entropy: 183 to 256 distinct byte values per 4 KB block, mean 254, where texture data sits under 200. It is real content of unknown type and is the most likely home for moby_anim, now that the range between collision and moby has been ruled out as texture. A lump shorter than the trailer now yields end: None rather than a backwards bound, covered by a test.
This commit is contained in:
@@ -1737,6 +1737,8 @@ fn core_regions_chain_on_every_level() {
|
||||
use gc_formats::regions::core_layout;
|
||||
let mut levels = 0usize;
|
||||
let mut unresolved_shrub = 0usize;
|
||||
let mut bounded = 0usize;
|
||||
let mut shrub_bytes = 0usize;
|
||||
let (mut first, mut last) = (usize::MAX, 0usize);
|
||||
|
||||
for n in 0..27 {
|
||||
@@ -1748,7 +1750,7 @@ fn core_regions_chain_on_every_level() {
|
||||
.map(|m| m.len() as usize)
|
||||
.unwrap_or(0);
|
||||
let h = LevelCoreHeader::parse(&index).expect("core header");
|
||||
let regions = core_layout(&index, &h);
|
||||
let regions = core_layout(&index, &h, core_len);
|
||||
|
||||
// Regions appear in order, never overlap, and never run past the lump.
|
||||
for pair in regions.windows(2) {
|
||||
@@ -1804,8 +1806,15 @@ fn core_regions_chain_on_every_level() {
|
||||
"level{n}: regions out of order: {names:?}"
|
||||
);
|
||||
if let Some(s) = regions.iter().find(|r| r.name == "shrub") {
|
||||
if s.end.is_none() {
|
||||
unresolved_shrub += 1;
|
||||
// The constant trailer bounds it; assert it is actually inside
|
||||
// the lump rather than at its end.
|
||||
match s.end {
|
||||
Some(e) => {
|
||||
assert!(e < core_len, "level{n}: shrub ends at the lump's end");
|
||||
shrub_bytes += s.len().unwrap_or(0);
|
||||
bounded += 1;
|
||||
}
|
||||
None => unresolved_shrub += 1,
|
||||
}
|
||||
first = first.min(s.start);
|
||||
last = last.max(s.start);
|
||||
@@ -1816,11 +1825,13 @@ fn core_regions_chain_on_every_level() {
|
||||
assert_eq!(levels, 27, "expected all 27 levels, got {levels}");
|
||||
// Known gap, not a bug: the offset ending the shrub region is not in the
|
||||
// core index and textures sit before moby, so they cannot bound it.
|
||||
assert!(
|
||||
unresolved_shrub > 20,
|
||||
"shrub end should still be unresolved, saw {unresolved_shrub}"
|
||||
assert_eq!(
|
||||
unresolved_shrub, 0,
|
||||
"every level with shrub should bound it"
|
||||
);
|
||||
assert_eq!(bounded, 24, "expected 24 levels with a shrub region");
|
||||
eprintln!(
|
||||
"regions: shrub starts {first}..{last}, end unresolved on {unresolved_shrub}/27 levels"
|
||||
"regions: shrub starts {first}..{last}; {shrub_bytes} bytes total, \
|
||||
bounded by the constant trailer on all {bounded} levels"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user