core: Add error handling to cartridge header parsing

Former-commit-id: 4e65ccd597bc082f259788f0870287254e852a2f
Former-commit-id: ebb62516936dc0f27dc9761aeb6bb6faa8ec58b5
This commit is contained in:
Tibor Nagy 2020-05-30 13:09:42 +02:00 committed by MishMish
parent 1b1b855702
commit 4050dcdf2f
4 changed files with 39 additions and 10 deletions

View file

@ -6,7 +6,7 @@ use rustboyadvance_core::cartridge;
fn parse_rom_header(env: &JNIEnv, barr: jbyteArray) -> cartridge::header::CartridgeHeader { fn parse_rom_header(env: &JNIEnv, barr: jbyteArray) -> cartridge::header::CartridgeHeader {
let rom_data = env.convert_byte_array(barr).unwrap(); let rom_data = env.convert_byte_array(barr).unwrap();
cartridge::header::parse(&rom_data) cartridge::header::parse(&rom_data).unwrap()
} }
#[no_mangle] #[no_mangle]

View file

@ -120,7 +120,7 @@ impl GamepakBuilder {
)) ))
}?; }?;
let header = header::parse(&bytes); let header = header::parse(&bytes)?;
info!("Loaded ROM: {:?}", header); info!("Loaded ROM: {:?}", header);
if !self.create_backup_file { if !self.create_backup_file {

View file

@ -1,6 +1,8 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::str::from_utf8; use std::str::from_utf8;
use super::super::{GBAError, GBAResult};
/// From GBATEK /// From GBATEK
/// ///
/// The first 192 bytes at 8000000h-80000BFh in ROM are used as cartridge header. The same header is also used for Multiboot images at 2000000h-20000BFh (plus some additional multiboot entries at 20000C0h and up). /// The first 192 bytes at 8000000h-80000BFh in ROM are used as cartridge header. The same header is also used for Multiboot images at 2000000h-20000BFh (plus some additional multiboot entries at 20000C0h and up).
@ -38,22 +40,49 @@ pub struct CartridgeHeader {
// joybus_entry_point: Addr, // joybus_entry_point: Addr,
} }
pub fn parse(bytes: &[u8]) -> CartridgeHeader { fn calculate_checksum(bytes: &[u8]) -> u8 {
bytes
.iter()
.cloned()
.fold(0u8, u8::wrapping_sub)
.wrapping_sub(0x19)
}
pub fn parse(bytes: &[u8]) -> GBAResult<CartridgeHeader> {
if bytes.len() < 0xc0 {
return Err(GBAError::CartridgeLoadError(
"incomplete cartridge header".to_string(),
));
}
let checksum = bytes[0xbd];
if calculate_checksum(&bytes[0xa0..=0xbc]) != checksum {
return Err(GBAError::CartridgeLoadError(
"invalid header checksum".to_string(),
));
}
let game_title = from_utf8(&bytes[0xa0..0xac])
.map_err(|_| GBAError::CartridgeLoadError("invalid game title".to_string()))?;
let game_code = from_utf8(&bytes[0xac..0xb0])
.map_err(|_| GBAError::CartridgeLoadError("invalid game code".to_string()))?;
let maker_code = from_utf8(&bytes[0xb0..0xb2])
.map_err(|_| GBAError::CartridgeLoadError("invalid marker code".to_string()))?;
// let (_, rom_entry_point) = le_u32(bytes).unwrap(); // let (_, rom_entry_point) = le_u32(bytes).unwrap();
let game_title = from_utf8(&bytes[0xa0..0xac]).unwrap();
let game_code = from_utf8(&bytes[0xac..0xb0]).unwrap();
let maker_code = from_utf8(&bytes[0xb0..0xb2]).unwrap();
// let (_, ram_entry_point) = le_u32(&bytes[0xc0..]).unwrap(); // let (_, ram_entry_point) = le_u32(&bytes[0xc0..]).unwrap();
// let (_, joybus_entry_point) = le_u32(&bytes[0xc0..]).unwrap(); // let (_, joybus_entry_point) = le_u32(&bytes[0xc0..]).unwrap();
CartridgeHeader { Ok(CartridgeHeader {
// rom_entry_point: rom_entry_point, // rom_entry_point: rom_entry_point,
game_title: String::from(game_title), game_title: String::from(game_title),
game_code: String::from(game_code), game_code: String::from(game_code),
maker_code: String::from(maker_code), maker_code: String::from(maker_code),
software_version: bytes[0xbc], software_version: bytes[0xbc],
checksum: bytes[0xbd], checksum: checksum,
// ram_entry_point: ram_entry_point, // ram_entry_point: ram_entry_point,
// joybus_entry_point: joybus_entry_point, // joybus_entry_point: joybus_entry_point,
} })
} }

View file

@ -55,5 +55,5 @@ impl From<cartridge::header::CartridgeHeader> for RomInfo {
#[wasm_bindgen] #[wasm_bindgen]
pub fn parse_rom_header(rom_bin: &[u8]) -> RomInfo { pub fn parse_rom_header(rom_bin: &[u8]) -> RomInfo {
cartridge::header::parse(rom_bin).into() cartridge::header::parse(rom_bin).unwrap().into()
} }