Fix mask bit lookup to match its documented encoding
visible() documented its argument as `byte << 8 | 1 << bit` -- high byte selects the mask byte, low byte is already the shifted bit -- then shifted the low byte a second time as though it were a bit index. That is wrong twice over. It inverts the meaning of every bit argument, and for any low byte above 8 it panics in debug, because `1u8 << 32` is an overflow. Real data reaches it: the folded bits for the upper bytes of a mask are exactly the values that trip it. Treat the low byte as the bit mask, which is what the doc says and what the renderer needs. Added an assertion for a mask index that does not exist, since that was the case that exposed the mismatch.
This commit is contained in:
@@ -68,11 +68,15 @@ impl Occlusion {
|
||||
|
||||
/// Is an object with these occlusion bits visible from this mask?
|
||||
///
|
||||
/// The bits are `byte << 8 | 1 << bit`, folded at level load. The test is
|
||||
/// the game's: `mask[byte] & bit == 0` means skip.
|
||||
/// The bits are `byte << 8 | 1 << bit`, folded at level load: the high
|
||||
/// byte selects the mask byte and the low byte is *already* the shifted
|
||||
/// bit, not an index. Shifting the low byte again is both wrong and a
|
||||
/// panic, since any byte above 8 overflows a `u8` shift.
|
||||
///
|
||||
/// The test is the game's: `mask[byte] & bit == 0` means skip.
|
||||
pub fn visible(&self, mask_index: u16, bits: u16) -> bool {
|
||||
let byte = (bits >> 8) as usize;
|
||||
let bit = 1u8 << (bits & 0xff);
|
||||
let bit = (bits & 0xff) as u8;
|
||||
self.masks
|
||||
.get(mask_index as usize)
|
||||
.is_some_and(|m| byte < MASK_BYTES && m[byte] & bit != 0)
|
||||
|
||||
Reference in New Issue
Block a user