const BASE: [u8; 19] = [
0xCB, 0xE1, 0xEE, 0xFA, 0xE5, 0xEE, 0xAD, 0xEE, 0xE9, 0xD2, 0xE9, 0xEB, 0xE1, 0xE9, 0xF3, 0xE8,
0xE9, 0xF4, 0xE1,
];
const MASK_START: usize = 0x12;
pub fn toggle_mask(section: &mut [u8]) {
if section.len() < MASK_START + 2 {
return;
}
let len_entries = u16::from_be_bytes([section[0x10], section[0x11]]);
for (i, b) in section[MASK_START..].iter_mut().enumerate() {
*b ^= BASE[i % 19].wrapping_add(len_entries as u8);
}
}
pub fn is_plain(section: &[u8]) -> bool {
section.len() >= 0x20 && matches!(u16::from_be_bytes([section[0x12], section[0x13]]), 1..=3)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn mask_is_involution_and_flips_plainness() {
let mut s = vec![0u8; 0x40];
s[..4].copy_from_slice(b"PSSI");
s[0x10..0x12].copy_from_slice(&16u16.to_be_bytes());
s[0x12..0x14].copy_from_slice(&2u16.to_be_bytes());
let orig = s.clone();
assert!(is_plain(&s));
toggle_mask(&mut s);
assert!(!is_plain(&s));
assert_ne!(s, orig);
toggle_mask(&mut s);
assert_eq!(s, orig);
}
}