Understand better how SNES addressing works.
This commit is contained in:
		
							parent
							
								
									a161d9090e
								
							
						
					
					
						commit
						7a6689efd1
					
				
					 1 changed files with 29 additions and 18 deletions
				
			
		| 
						 | 
				
			
			@ -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<String, u32>;
 | 
			
		||||
pub type Symbols = HashMap<String, usize>;
 | 
			
		||||
 | 
			
		||||
impl Symbols {
 | 
			
		||||
    pub fn load(filename: Path) -> anyhow::Result<Symbols> {
 | 
			
		||||
        let file = File::open(filename)?;
 | 
			
		||||
        let mut reader = BufReader::new(file);
 | 
			
		||||
pub fn load_symbols(filename: &Path) -> anyhow::Result<Symbols> {
 | 
			
		||||
    let file = File::open(filename)?;
 | 
			
		||||
    let reader = BufReader::new(file);
 | 
			
		||||
 | 
			
		||||
        reader.lines().filter_map(|l| l.ok().and_then(|line| {
 | 
			
		||||
            let words: Vec<String> = 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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue