core: Add error handling to cartridge header parsing
Former-commit-id: 4e65ccd597bc082f259788f0870287254e852a2f Former-commit-id: ebb62516936dc0f27dc9761aeb6bb6faa8ec58b5
This commit is contained in:
parent
1b1b855702
commit
4050dcdf2f
|
@ -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]
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue