diff --git a/enemize/src/asar.rs b/enemize/src/asar.rs index 6324302..f405e9d 100644 --- a/enemize/src/asar.rs +++ b/enemize/src/asar.rs @@ -1,33 +1,44 @@ use std::collections::HashMap; use std::fs::File; -use std::io::{BufReader, Read}; +use std::io::{BufReader, BufRead}; use std::path::Path; -pub type Symbols = HashMap; +pub type Symbols = HashMap; -impl Symbols { - pub fn load(filename: Path) -> anyhow::Result { - let file = File::open(filename)?; - let mut reader = BufReader::new(file); +pub fn load_symbols(filename: &Path) -> anyhow::Result { + let file = File::open(filename)?; + let reader = BufReader::new(file); - reader.lines().filter_map(|l| l.ok().and_then(|line| { - let words: Vec = line.split_ascii_whitespace().collect(); - if words.len() == 2 { - Some((words[1], words[0])) - } else { - None - } - })) - .filter_map(|(symbol, mut address)| { + let symbols = reader.lines().filter_map(|l| l.ok().and_then(|line| { + let mut words = line.split_ascii_whitespace(); + match (words.next(), words.next(), words.next()) { + // Get only two-word lines. + (Some(address), Some(symbol), None) => + Some((symbol.to_owned(), address.to_owned())), + + _ => None + } + }) + .and_then(|(symbol, mut address)| { if let Some(colon_at) = address.find(':') { address.remove(colon_at); } + // Filter out the ones that don't have a hexadecimal number as the first word. let snes_address = u32::from_str_radix(&address, 16).ok()?; - let pc_address = (snes_address & 0x7FFF) + ((addr / 2) & 0xFF8000); + let pc_address = snes_to_pc_address(snes_address); Some((symbol, pc_address)) - }).collect() - } + })).collect(); + + Ok(symbols) +} + +pub fn snes_to_pc_address(snes: u32) -> usize { + ((snes & 0x7FFF) + ((snes / 2) & 0xFF8000)) as usize +} + +pub fn pc_to_snes_address(pc: usize) -> u32 { + ((pc & 0x7FFF) + ((pc & 0xFF8000) * 2)) as u32 }