summaryrefslogtreecommitdiff
path: root/src/debug.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug.rs')
-rw-r--r--src/debug.rs79
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
+ }
+ }
}