use crate::{Result, error::Error};
pub const CHT_FILE_SIZE: usize = 256;
pub const CHT_SLOT_COUNT: usize = 64;
pub const CHT_CHEAT_COUNT: usize = 13;
pub const CHEAT_NAMES: [&str; CHT_CHEAT_COUNT] = [
"oracle",
"nodemarker",
"moonraker",
"task",
"animation",
"magiccarpet",
"savecheats",
"drevil",
"drno",
"goldfinger",
"neversaydie",
"oddjob",
"yeahbaby",
];
#[derive(Debug, Clone)]
pub struct CheatEntry {
pub index: usize,
pub name: Option<&'static str>,
pub value: u32,
}
impl CheatEntry {
#[must_use]
pub const fn is_on(&self) -> bool {
self.value != 0
}
}
#[derive(Debug, Clone)]
pub struct ChtFile {
pub entries: Vec<CheatEntry>,
}
impl ChtFile {
#[must_use]
pub fn named_cheats(&self) -> &[CheatEntry] {
&self.entries[..CHT_CHEAT_COUNT]
}
#[must_use]
pub fn nonzero_unnamed(&self) -> Vec<&CheatEntry> {
self.entries[CHT_CHEAT_COUNT..]
.iter()
.filter(|e| e.value != 0)
.collect()
}
}
pub fn parse_cht_file(data: &[u8]) -> Result<ChtFile> {
if data.len() != CHT_FILE_SIZE {
return Err(Error::Parse(format!(
"CHT file must be exactly {} bytes, got {}",
CHT_FILE_SIZE,
data.len()
)));
}
let entries = (0..CHT_SLOT_COUNT)
.map(|i| {
let offset = i * 4;
let value = u32::from_le_bytes([
data[offset],
data[offset + 1],
data[offset + 2],
data[offset + 3],
]);
CheatEntry {
index: i,
name: CHEAT_NAMES.get(i).copied(),
value,
}
})
.collect();
Ok(ChtFile { entries })
}