diff options
Diffstat (limited to 'src/debug.rs')
-rw-r--r-- | src/debug.rs | 79 |
1 files changed, 72 insertions, 7 deletions
diff --git a/src/debug.rs b/src/debug.rs index d19dbec..1593d9d 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -1,23 +1,28 @@ use bedrock_core::*; +use std::path::Path; use std::time::Instant; -macro_rules! yellow { () => { eprint!("\x1b[33m") };} -macro_rules! normal { () => { eprint!("\x1b[0m" ) };} + +const NORMAL: &str = "\x1b[0m"; +const YELLOW: &str = "\x1b[33m"; +const BLUE: &str = "\x1b[34m"; pub struct DebugState { pub enabled: bool, last_cycle: usize, last_mark: Instant, + symbols: DebugSymbols, } impl DebugState { - pub fn new(enabled: bool) -> Self { + pub fn new<P: AsRef<Path>>(enabled: bool, symbols_path: Option<P>) -> Self { Self { enabled, last_cycle: 0, last_mark: Instant::now(), + symbols: DebugSymbols::from_path_opt(symbols_path), } } @@ -37,7 +42,12 @@ impl DebugState { debug_stack(&core.wst, 0x10); eprint!("RST: "); debug_stack(&core.rst, 0x10); - + // Print information about the current symbol. + if let Some(symbol) = self.symbols.for_address(core.mem.pc) { + eprint!("SYM: {BLUE}@{}{NORMAL}", symbol.name); + if let Some(location) = &symbol.location { eprint!(" {location}"); } + eprintln!(); + } self.last_cycle = core.cycle; self.last_mark = Instant::now(); } @@ -46,9 +56,64 @@ impl DebugState { fn debug_stack(stack: &Stack, len: usize) { for i in 0..len { - if i == stack.sp as usize { yellow!(); } + if i == stack.sp as usize { eprint!("{YELLOW}"); } eprint!("{:02x} ", stack.mem[i]); } - normal!(); - eprintln!(); + eprintln!("{NORMAL}"); +} + + +struct DebugSymbols { + symbols: Vec<DebugSymbol> +} + +impl DebugSymbols { + /// Load debug symbols from a symbols file. + pub fn from_path_opt<P: AsRef<Path>>(path: Option<P>) -> Self { + let mut symbols = Vec::new(); + if let Some(path) = path { + if let Ok(string) = std::fs::read_to_string(path) { + for line in string.lines() { + if let Some(symbol) = DebugSymbol::from_line(line) { + symbols.push(symbol); + } + } + } + } + symbols.sort_by_key(|s| s.address); + Self { symbols } + } + + pub fn for_address(&self, address: u16) -> Option<&DebugSymbol> { + if self.symbols.is_empty() { return None; } + let symbol = match self.symbols.binary_search_by_key(&address, |s| s.address) { + Ok(index) => self.symbols.get(index)?, + Err(index) => self.symbols.get(index.checked_sub(1)?)?, + }; + Some(&symbol) + } +} + +struct DebugSymbol { + address: u16, + name: String, + location: Option<String>, +} + +impl DebugSymbol { + pub fn from_line(line: &str) -> Option<Self> { + if let Some((address, line)) = line.split_once(' ') { + let address = u16::from_str_radix(address, 16).ok()?; + if let Some((name, location)) = line.split_once(' ') { + let name = name.to_string(); + let location = Some(location.to_string()); + Some( DebugSymbol { address, name, location } ) + } else { + let name = line.to_string(); + Some( DebugSymbol { address, name, location: None } ) + } + } else { + None + } + } } |