boy-debug: misc improvements

This commit is contained in:
John 2024-07-09 01:39:57 -05:00
parent 6cee907f1c
commit f0733cde37

View File

@ -163,9 +163,7 @@ pub mod cli {
impl<T: Iterator<Item = char>> Lexible for T { impl<T: Iterator<Item = char>> Lexible for T {
fn lex(self) -> Lexer<Self> { fn lex(self) -> Lexer<Self> {
Lexer { Lexer { text: self.peekable() }
text: self.peekable(),
}
} }
} }
@ -175,6 +173,7 @@ pub mod cli {
} }
impl<I: Iterator<Item = char>> Lexer<I> { impl<I: Iterator<Item = char>> Lexer<I> {
/// Advances to the next non-whitespace character
fn sync(&mut self) -> &mut Self { fn sync(&mut self) -> &mut Self {
while self.peek().map(|c| c.is_whitespace()).unwrap_or(false) { while self.peek().map(|c| c.is_whitespace()).unwrap_or(false) {
self.take(); self.take();
@ -333,10 +332,9 @@ pub mod cli {
impl<T: Iterator<Item = Token>> Parser<T> { impl<T: Iterator<Item = Token>> Parser<T> {
pub fn new(t: T) -> Self { pub fn new(t: T) -> Self {
Self { Self { lexer: t.peekable() }
lexer: t.peekable(),
}
} }
#[must_use] #[must_use]
fn peek(&mut self) -> Option<&Token> { fn peek(&mut self) -> Option<&Token> {
self.lexer.peek() self.lexer.peek()
@ -374,10 +372,9 @@ pub mod cli {
pub fn parse<I: Iterator<Item = Token>>(lexer: &mut Parser<I>) -> Option<Stmt> { pub fn parse<I: Iterator<Item = Token>>(lexer: &mut Parser<I>) -> Option<Stmt> {
let verb = Verb::parse(lexer)?; let verb = Verb::parse(lexer)?;
let [dst, src] = match verb { let [dst, src] = match verb {
Verb::Set => [ Verb::Set => {
Expr::parse(lexer, 0)?, [Expr::parse(lexer, 0)?, Expr::parse(lexer.then(Token::Op(Op::Eq))?, 0)?]
Expr::parse(lexer.then(Token::Op(Op::Comma))?, 0)?, }
],
Verb::Load Verb::Load
| Verb::Get | Verb::Get
| Verb::Run | Verb::Run
@ -440,7 +437,8 @@ pub mod cli {
} }
Token::Op(Op::BrackOpen) => { Token::Op(Op::BrackOpen) => {
let mut exprs = vec![]; let mut exprs = vec![];
while p.then(Token::Op(Op::BrackClose)).is_none() { while Some(&Token::Op(Op::BrackClose)) != p.peek() {
// while p.then(Token::Op(Op::BrackClose)).is_none() {
exprs.push(Expr::parse(p, 0)?); exprs.push(Expr::parse(p, 0)?);
if p.then(Token::Op(Op::Comma)).is_none() { if p.then(Token::Op(Op::Comma)).is_none() {
break; break;
@ -510,8 +508,8 @@ pub mod cli {
Range, Range,
Array, Array,
Bit, Bit,
Factor,
Shift, Shift,
Factor,
Term, Term,
Sign, Sign,
} }
@ -861,11 +859,6 @@ pub mod message {
} }
pub mod gameboy { pub mod gameboy {
use std::io::Write;
use boy::cpu::CPU;
use boy::memory::io::*;
use boy_utils::*;
use crate::{ use crate::{
ast::{Expr, Reg, Stmt, Verb}, ast::{Expr, Reg, Stmt, Verb},
@ -873,6 +866,9 @@ pub mod gameboy {
disassembler::Disassemble, disassembler::Disassemble,
message::{Request, Response}, message::{Request, Response},
}; };
use boy::{cpu::CPU, error::Error, memory::io::*};
use boy_utils::*;
use std::io::Write;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Gameboy<T: BusIO> { pub struct Gameboy<T: BusIO> {
@ -883,11 +879,7 @@ pub mod gameboy {
impl<T: BusIO> Gameboy<T> { impl<T: BusIO> Gameboy<T> {
pub fn new(bus: T) -> Self { pub fn new(bus: T) -> Self {
Self { Self { trace: false, cpu: CPU::new(), bus }
trace: false,
cpu: CPU::new(),
bus,
}
} }
pub fn process(&mut self, message: Request) -> Response { pub fn process(&mut self, message: Request) -> Response {
match message { match message {
@ -928,7 +920,7 @@ pub mod gameboy {
(Verb::Load, Expr::String(file), ..) => { (Verb::Load, Expr::String(file), ..) => {
if let Err(e) = self.bus.read_file(file) { if let Err(e) = self.bus.read_file(file) {
eprintln!("{e}"); eprintln!("{e}");
return Response::Failure return Response::Failure;
} }
} }
(Verb::Set, Expr::Int(addr), Expr::Int(data)) => { (Verb::Set, Expr::Int(addr), Expr::Int(data)) => {
@ -1060,6 +1052,7 @@ pub mod gameboy {
} }
fn step(&mut self, steps: usize) -> Response { fn step(&mut self, steps: usize) -> Response {
use boy::error::ErrorKind as Eek;
let Self { trace, cpu, bus } = self; let Self { trace, cpu, bus } = self;
for step in 1..=steps { for step in 1..=steps {
let (loc, insn) = (cpu.pc(), cpu.ir()); let (loc, insn) = (cpu.pc(), cpu.ir());
@ -1073,7 +1066,7 @@ pub mod gameboy {
} }
if steps < 100 { if steps < 100 {
print!( print!(
"{loc:04x}: [{insn:?}]\x1b[23GTook {cycles} cycle{}\x1b[50G", "{step:04x}: Took {cycles} cycle{}\x1b[38G",
if cycles == 1 { "" } else { "s" } if cycles == 1 { "" } else { "s" }
); );
} }
@ -1085,16 +1078,38 @@ pub mod gameboy {
let _ = std::io::stdout().flush(); let _ = std::io::stdout().flush();
} }
} }
Err(e) => { Err(Error { kind: Eek::HitBreak(addr, cycles) }) => {
println!( print!(
"\n{loc:04x}: [{insn:?}]\x1b[23G{insn}\x1b[50G\x1b[31mStep {step:x}: {e}\x1b[0m" "\x1b[31m{addr:04x}\x1b[0m: Took {cycles} cycle{}\x1b[38G",
if cycles == 1 { "" } else { "s" }
); );
bus.read_iter_from(loc.wrapping_sub(1) as usize)
.disassemble()
.map(|(_, s)| println!("{:04x}: {s}", loc.wrapping_sub(1)))
.next();
let _ = std::io::stdout().flush();
break;
}
Err(Error { kind: Eek::UnimplementedInsn(_) }) => {
print!("{step:04x}: \x1b[91mNot yet implemented:\x1b[0m\x1b[38G");
bus.read_iter_from(loc.wrapping_sub(1) as usize)
.disassemble()
.map(|(_, s)| println!("{:04x}: {s}", loc.wrapping_sub(1)))
.next();
let _ = std::io::stdout().flush();
}
Err(e) => {
print!("{step:04x}: {e}\x1b[38G{insn}");
bus.read_iter_from(loc.wrapping_sub(1) as usize)
.disassemble()
.map(|(_, s)| println!("{:04x}: {s}", loc.wrapping_sub(1)))
.next();
let _ = std::io::stdout().flush();
return Response::Failure; return Response::Failure;
} }
} }
} }
println!();
bus.diag(0);
Response::Success Response::Success
} }
} }