Read the shrub header floats, including a denormal the PS2 flushes
Extended the shrub header past the two self-identifying words. The first four words are floats -- finite on all 358 spans -- though they do not behave like a min/max bounding box, which orders correctly on only 146 of 358, so they are recorded as bounds rather than named. The word at +0x10 is positive everywhere, 3.0 to 20.0, exactly 5.0 on 281 of them. The word at +0x14 is the interesting one. It is zero on 342 spans and the bit pattern 04000000 on the other 16, which is a denormal of about 2.8e-45. The Emotion Engine has no denormals, so hardware reads all 358 as zero. That is only the second reading. My probe reported the field as 0.000 everywhere because it printed to three decimals, and the test caught it: level 7 class 7 fails a strict zero check. The lesson is that "exact" in a measurement means exact in the measured precision -- rounding in the output made a real distinction invisible. It also matches AGENTS.md on modelling the FPU rather than correcting it: this field looks like noise on disc and is a constant to the machine that reads it, and the parser accepts either rather than picking one. The shrub body past +0x2c is still not decoded.
This commit is contained in:
@@ -1644,6 +1644,8 @@ fn shrub_headers_name_their_own_class_on_every_level() {
|
||||
let mut levels = 0usize;
|
||||
let mut spans = 0usize;
|
||||
let mut absent = 0usize;
|
||||
let (mut min_size, mut max_size) = (f32::MAX, 0.0f32);
|
||||
let mut denormals = 0usize;
|
||||
|
||||
for n in 0..27 {
|
||||
let dir = data.join(format!("level{n}"));
|
||||
@@ -1667,6 +1669,27 @@ fn shrub_headers_name_their_own_class_on_every_level() {
|
||||
"level{n} class {i}"
|
||||
);
|
||||
assert!(!s.data.is_empty(), "level{n} class {i}: empty shrub data");
|
||||
assert!(
|
||||
s.header.bounds.iter().all(|v| v.is_finite()),
|
||||
"level{n} class {i}: non-finite shrub bounds"
|
||||
);
|
||||
assert!(
|
||||
s.header.size.is_finite() && s.header.size > 0.0,
|
||||
"level{n} class {i}: shrub size {}",
|
||||
s.header.size
|
||||
);
|
||||
// The PS2 has no denormals, so a denormal here and a zero
|
||||
// are the same value to the hardware. Both occur on disc.
|
||||
if s.header.reserved != 0.0 {
|
||||
assert!(
|
||||
s.header.reserved.is_subnormal(),
|
||||
"level{n} class {i}: reserved {} is neither zero nor denormal",
|
||||
s.header.reserved
|
||||
);
|
||||
denormals += 1;
|
||||
}
|
||||
min_size = min_size.min(s.header.size);
|
||||
max_size = max_size.max(s.header.size);
|
||||
spans += 1;
|
||||
}
|
||||
Ok(None) => absent += 1,
|
||||
@@ -1684,5 +1707,8 @@ fn shrub_headers_name_their_own_class_on_every_level() {
|
||||
spans + absent
|
||||
);
|
||||
assert!(spans > 340, "only {spans} shrub spans with geometry");
|
||||
eprintln!("shrub: {spans} headers naming their own class, {absent} without geometry");
|
||||
eprintln!(
|
||||
"shrub: {spans} headers naming their own class, {absent} without geometry; \
|
||||
size field {min_size}..{max_size}; {denormals} denormal reserved words"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user