boy: Initial public commit
- SM83 implementation kinda works - Live disassembly, memory write tracing - Pretty snazzy debugger with custom memory editor - hexadecimal calculator with novel operator precedence rules
This commit is contained in:
9
boy-utils/Cargo.toml
Normal file
9
boy-utils/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "boy-utils"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
boy = { path = ".." }
|
||||
69
boy-utils/src/lib.rs
Normal file
69
boy-utils/src/lib.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
/// Utilities and common behavior for the [boy] emulator
|
||||
use std::io::Write;
|
||||
use std::ops::Range;
|
||||
|
||||
use boy::memory::io::*;
|
||||
|
||||
/// Formats the data over a given range as a traditional hexdump
|
||||
pub fn slice_hexdump(data: &[u8], range: Range<usize>) -> std::io::Result<()> {
|
||||
const WIDTH: usize = 16;
|
||||
const HEX: usize = 6;
|
||||
const ASCII: usize = 3 * (WIDTH + 1) + HEX;
|
||||
|
||||
let base = range.start;
|
||||
let mut out = std::io::stdout().lock();
|
||||
|
||||
let Some(data) = data.get(range) else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
for (chunkno, chunk) in data.chunks(WIDTH).enumerate() {
|
||||
write!(out, "{:04x}\x1b[{HEX}G", base + chunkno * WIDTH)?;
|
||||
for (byteno, byte) in chunk.iter().enumerate() {
|
||||
write!(out, "{}{byte:02x}", if byteno == 8 { " " } else { " " })?
|
||||
}
|
||||
write!(out, "\x1b[{ASCII}G|")?;
|
||||
for byte in chunk.iter() {
|
||||
match char::from_u32(*byte as u32) {
|
||||
Some(c) if c.is_ascii_graphic() => write!(out, "{c}")?,
|
||||
Some(_) | None => write!(out, "∙")?,
|
||||
}
|
||||
}
|
||||
writeln!(out, "|")?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn bus_hexdump(bus: &impl BusIO, range: Range<usize>) -> std::io::Result<()> {
|
||||
use boy::memory::io::BusAux;
|
||||
const WIDTH: usize = 16;
|
||||
|
||||
let mut out = std::io::stdout();
|
||||
|
||||
let upper = range.end;
|
||||
for lower in range.clone().step_by(WIDTH) {
|
||||
let upper = (lower + WIDTH).min(upper);
|
||||
// write!(out, "{:04x}\x1b[{HEX}G", lower)?;
|
||||
let _data: [u8; WIDTH] = bus.read_arr(lower).unwrap_or_else(|e| e);
|
||||
write!(out, "{:04x} ", lower)?;
|
||||
// write hexadecimal repr
|
||||
for (idx, addr) in (lower..upper).enumerate() {
|
||||
let space = if idx == WIDTH / 2 { " " } else { " " };
|
||||
match bus.read(addr) {
|
||||
Some(data) => write!(out, "{space}{data:02x}"),
|
||||
None => write!(out, "{space}__"),
|
||||
}?;
|
||||
}
|
||||
let padding = WIDTH - (upper - lower);
|
||||
let padding = padding * 3 + if padding >= (WIDTH / 2) { 1 } else { 0 };
|
||||
write!(out, "{:padding$} |", "")?;
|
||||
for data in (lower..upper).flat_map(|addr| bus.read(addr)) {
|
||||
match char::from_u32(data as u32) {
|
||||
Some(c) if !c.is_control() => write!(out, "{c}"),
|
||||
_ => write!(out, "."),
|
||||
}?;
|
||||
}
|
||||
writeln!(out, "|")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user