use log::error;
use crate::backup::Backup;
#[derive(Default, Clone)]
pub struct Rom {
pub data: Vec<u8>,
pub title: Vec<u8>,
pub game_code: [u8; 4],
pub maker_code: [u8; 2],
pub main_unit_code: u8,
pub device_type: u8,
pub rom_version: u8,
}
#[derive(thiserror::Error, Debug)]
pub enum RomError {
#[error("Invalid magic number: 0x{0:02X}, expected: 0x96")]
InvalidMagic(u8),
}
impl Rom {
pub fn from_bytes(data: &[u8]) -> Result<Self, RomError> {
let header = &data[0xA0..0xC0];
let title = header[..0xC].to_vec();
let game_code = header[0xC..0x10].try_into().unwrap();
let maker_code = header[0x10..0x12].try_into().unwrap();
let magic = header[0x12];
if magic != 0x96 {
Err(RomError::InvalidMagic(magic))?
}
let main_unit_code = header[0x13];
let device_type = header[0x14];
let rom_version = header[0x1C];
let complement_check = header[0x1D];
for i in (0x15..=0x1B).chain(0x1E..=0x1F) {
if header[i] != 0 {
error!("Non-zero value in reserved area: {:02X}", header[i]);
}
}
let sum = header[..=0x1C]
.iter()
.fold(0_u8, |a, b| a.wrapping_add(*b))
.wrapping_add(0x19);
if sum.wrapping_add(complement_check) != 0 {
error!("Invalid complement check: {sum:02X} + {complement_check:02X} != 0");
}
let ret = Rom {
data: data.to_vec(),
title,
game_code,
maker_code,
main_unit_code,
device_type,
rom_version,
};
Ok(ret)
}
pub fn backup_type(&self) -> &'static str {
Backup::detect_backup(&self.data, None).backup_type()
}
}