pokemon data validation

master
hheik 2023-04-01 13:49:34 +03:00
parent 0395cbc942
commit d26da8776b
1 changed files with 77 additions and 2 deletions

View File

@ -1,6 +1,81 @@
use super::inspector::Battle; use super::inspector::{Battle, PokemonInstance};
const PLAYER_PARTY_OFFSET: usize = 0x21E42C;
const ENEMY_PARTY_OFFSET: usize = 0x258874;
const POKEMON_SIZE: usize = 0xDC;
const PARTY_MAX_SIZE: usize = 6;
pub fn parse_battle_party(data: &Vec<u8>) -> Result<Battle, String> { pub fn parse_battle_party(data: &Vec<u8>) -> Result<Battle, String> {
let mut result = Battle::default(); let mut battle = Battle::default();
for i in 0..PARTY_MAX_SIZE {
if let Some(instance) = try_parse(data, PLAYER_PARTY_OFFSET + i * POKEMON_SIZE) {
battle.player_party.push(instance);
}
if let Some(instance) = try_parse(data, ENEMY_PARTY_OFFSET + i * POKEMON_SIZE) {
battle.enemy_party.push(instance);
}
}
Ok(battle)
}
fn try_parse(data: &[u8], offset: usize) -> Option<PokemonInstance> {
let encrypted = &data[offset..offset + POKEMON_SIZE];
if !contains_pokemon(encrypted) {
return None;
}
let decrypted = decrypt_pokemon(encrypted).ok()?;
let pokemon = parse_pokemon(&decrypted).ok()?;
Some(pokemon)
}
fn decrypt_pokemon(encrypted: &[u8]) -> Result<Vec<u8>, String> {
validate_size(encrypted)?;
let mut result = vec![0; POKEMON_SIZE];
// NOTIMP
Ok(result) Ok(result)
} }
fn parse_pokemon(decrypted: &[u8]) -> Result<PokemonInstance, String> {
validate_size(decrypted)?;
let mut instance = PokemonInstance::default();
// NOTIMP
Ok(instance)
}
/// Check if the raw data contains a pokemon.
/// If the header section (8 bytes) are all 0x00, then the data doens't contain a pokemon.
/// This works with both encrypted and decryped forms, as the header is never encrypted.
fn contains_pokemon(data: &[u8]) -> bool {
if let Err(_) = validate_size(data) {
return false;
}
read_long(data, 0) != 0 || read_long(data, 4) != 0
}
fn validate_size(data: &[u8]) -> Result<(), String> {
if data.len() != POKEMON_SIZE {
return Err(format!(
"Invalid data size. expected: {POKEMON_SIZE} - actual: {}",
data.len()
));
}
Ok(())
}
/// Read a 1 byte value
fn read_byte(data: &[u8], offset: usize) -> u8 {
data[offset]
}
/// Read a little-endian 2 byte value
fn read_short(data: &[u8], offset: usize) -> u16 {
data[offset] as u16 | ((data[offset + 1] as u16) << 8)
}
/// Read a little-endian 4 byte value
fn read_long(data: &[u8], offset: usize) -> u32 {
data[offset] as u32
| ((data[offset + 1] as u32) << 8)
| ((data[offset + 2] as u32) << 16)
| ((data[offset + 3] as u32) << 24)
}