1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
use anyhow::{anyhow, Result};
use byteorder::{ByteOrder, LittleEndian, ReadBytesExt};
use std::{io::Cursor, str::from_utf8};
pub mod equipment;
pub mod stats;
pub fn validate_sram(sram: &[u8]) -> Result<()> {
let mut cur = Cursor::new(sram);
if sram.len() != 32768 {
return Err(anyhow!("Validation Error: Unexpected file size"));
}
let checksum_validity: u16 = LittleEndian::read_u16(&sram[0x3E1..0x3E3]);
if checksum_validity != 0x55AA || sram[0x4F0] != 0xFF {
return Err(anyhow!("Validation Error: Invalid file"));
}
let valid_names: [&str; 2] = ["VT", "ER"];
let rom_name = &sram[0x2000..0x2002];
if valid_names
.iter()
.any(|&x| x == from_utf8(&rom_name).unwrap())
== false
{
return Err(anyhow!("Validation Error: Invalid ROM name"));
}
let mut checksum = 0u16;
cur.set_position(0x00);
while cur.position() < 0x4FE {
let bytes = cur.read_u16::<LittleEndian>()?;
checksum = checksum.overflowing_add(bytes).0;
}
let expected_inv_checksum = 0x5A5Au16.overflowing_sub(checksum).0;
let inv_checksum: u16 = LittleEndian::read_u16(&sram[0x4FE..0x500]);
if inv_checksum != expected_inv_checksum {
return Err(anyhow!("Validation Error: Invalid checksum"));
}
return Ok(());
}
pub(crate) fn bitmask(bits: u32) -> u32 {
(1u32 << bits) - 1u32
}