refactor printing + args

This commit is contained in:
Alex Janka 2023-01-22 12:13:02 +11:00
parent 744f769728
commit 13bd9f0a1c
3 changed files with 113 additions and 46 deletions

View file

@ -2,16 +2,36 @@
mod processor;
use clap::Parser;
use clap::{ArgGroup, Parser};
use processor::CPU;
use std::{
fs,
io::{self, stdout, Write},
sync::RwLock,
};
#[macro_export]
macro_rules! verbose_println {
($($tts:tt)*) => {
if crate::is_verbose() {
println!($($tts)*);
}
};
}
#[macro_export]
macro_rules! verbose_print {
($($tts:tt)*) => {
if crate::is_verbose() {
print!($($tts)*);
}
};
}
/// Simple program to greet a person
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
#[command(group(ArgGroup::new("prints").args(["verbose","cycle_count"])))]
struct Args {
/// ROM path
#[arg(short, long)]
@ -25,6 +45,14 @@ struct Args {
#[arg(long)]
run_bootrom: bool,
/// Verbose print
#[arg(short, long)]
verbose: bool,
/// Show cycle count
#[arg(short, long)]
cycle_count: bool,
/// Step emulation by...
#[arg(long)]
step_by: Option<usize>,
@ -130,7 +158,8 @@ impl Memory {
}
fn set(&mut self, address: Address, data: u8) {
println!("write addr: {:#X}, data: {:#X}", address, data);
verbose_println!("write addr: {:#X}, data: {:#X}", address, data);
match address {
0x0..0x100 => {
if !self.bootrom_enabled {
@ -162,7 +191,7 @@ impl Memory {
// println!("empty space write: {:#X} to addr {:#X}", data, address);
}
0xFF00..0xFF4C => {
print!("writing to addr {:#X}\r", address);
verbose_print!("writing to addr {:#X}\r", address);
stdout().flush().unwrap();
if address == 0xFF02 && data == 0x81 {
@ -178,8 +207,8 @@ impl Memory {
self.cpu_ram[(address - 0xFF80) as usize] = data;
}
0xFFFF => {
println!("interrupts set to {:#b}", data);
println!(" / {:#X}", data);
verbose_println!("interrupts set to {:#b}", data);
verbose_println!(" / {:#X}", data);
self.interrupts = data;
}
}
@ -247,9 +276,15 @@ fn swap_rom_endian(rom: &ROM) -> ROM {
static mut PAUSE_ENABLED: bool = false;
static mut PAUSE_QUEUED: bool = false;
// static mut VERBOSE: bool = false;
static VERBOSE: RwLock<bool> = RwLock::new(false);
fn main() {
let args = Args::parse();
{
let mut v = VERBOSE.write().unwrap();
*v = args.verbose;
}
let rom: ROM = fs::read(args.rom).expect("Could not load ROM");
let bootrom: ROM = fs::read(args.bootrom).expect("Could not load BootROM");
@ -269,15 +304,19 @@ fn main() {
let mut cycle_num = 0;
let mut instructions_seen = vec![];
let mut last_state = cpu.state.clone();
let mut next_state: State;
let mut next_state = last_state;
match args.step_by {
Some(step_size) => loop {
for _ in 0..step_size {
cycle_num += 1;
cpu.exec_next();
println!(
"exec {:#4X} from {:#4X}",
cpu.last_instruction, cpu.last_instruction_addr
if args.cycle_count {
print_cycles(&cycle_num);
}
run_cycle(
&mut cpu,
&mut next_state,
&mut last_state,
&mut instructions_seen,
);
}
print!(
@ -285,39 +324,55 @@ fn main() {
cycle_num
);
stdout().flush().unwrap();
pause();
pause_once();
},
None => loop {
let will_pause;
unsafe {
will_pause = PAUSE_QUEUED.clone();
}
cycle_num += 1;
// print_cycles(&cycle_num);
cpu.exec_next();
unsafe {
next_state = cpu.state;
if !PAUSE_ENABLED {
if next_state.pc.as_u16 >= 0x100 {
PAUSE_ENABLED = true;
}
}
last_state = next_state;
if will_pause {
pause();
}
}
match instructions_seen.contains(&cpu.last_instruction) {
true => {}
false => {
// println!("new instruction enountered: {:#X}", cpu.last_instruction);
instructions_seen.push(cpu.last_instruction);
}
if args.cycle_count {
print_cycles(&cycle_num);
}
run_cycle(
&mut cpu,
&mut next_state,
&mut last_state,
&mut instructions_seen,
);
},
}
}
fn run_cycle(
cpu: &mut CPU,
next_state: &mut State,
last_state: &mut State,
instructions_seen: &mut Vec<u8>,
) {
let will_pause;
unsafe {
will_pause = PAUSE_QUEUED.clone();
}
cpu.exec_next();
unsafe {
*next_state = cpu.state;
if !PAUSE_ENABLED {
if next_state.pc.as_u16 >= 0x100 {
PAUSE_ENABLED = true;
}
}
*last_state = *next_state;
if will_pause {
pause();
}
}
match instructions_seen.contains(&cpu.last_instruction) {
true => {}
false => {
// println!("new instruction enountered: {:#X}", cpu.last_instruction);
instructions_seen.push(cpu.last_instruction);
}
}
}
#[allow(dead_code)]
fn pause() {
unsafe {
@ -328,6 +383,10 @@ fn pause() {
}
}
}
#[allow(dead_code)]
fn pause_once() {
io::stdin().read_line(&mut String::new()).unwrap();
}
#[allow(dead_code)]
fn print_cycles(cycles: &i32) {
@ -342,3 +401,10 @@ fn print_cycles(cycles: &i32) {
);
stdout().flush().unwrap();
}
fn is_verbose() -> bool {
match VERBOSE.read() {
Ok(v) => *v,
Err(_) => false,
}
}

View file

@ -3,7 +3,7 @@ use std::{
ops::{BitAnd, BitOr, BitXor},
};
use crate::{Inner, Memory, Register, State};
use crate::{verbose_println, Inner, Memory, Register, State};
mod opcodes;
@ -33,9 +33,10 @@ impl CPU {
unsafe { self.last_instruction_addr = self.state.pc.as_u16 };
let opcode = self.next_opcode();
self.last_instruction = opcode;
println!(
verbose_println!(
"exec {:#4X} from pc: {:#X}",
opcode, self.last_instruction_addr
opcode,
self.last_instruction_addr
);
self.run_opcode(opcode);
}
@ -177,15 +178,15 @@ impl CPU {
fn set_flag(&mut self, flag: FLAGS) {
if flag == FLAGS::Z {
println!("setting z flag");
verbose_println!("setting z flag");
}
unsafe {
println!(
verbose_println!(
"setting flag: currently {0:#b} / {0:#X}",
self.state.af.as_u8s.right
);
self.state.af.as_u8s.right = self.state.af.as_u8s.right.bitor(1 << flag as u8);
println!(
verbose_println!(
" now {0:#b} / {0:#X}",
self.state.af.as_u8s.right
);

View file

@ -1,4 +1,4 @@
use crate::{Inner, Register};
use crate::{verbose_println, Inner, Register};
use std::ops::{BitAnd, BitOr, BitXor};
use super::{as_signed, res, set, swap_nibbles, CPU, FLAGS};
@ -84,7 +84,7 @@ impl CPU {
0x20 => {
let jump_size = self.ld_immediate_byte();
if self.get_flag(FLAGS::Z) == 0 {
println!("z flag is 0... so doing jump...");
verbose_println!("z flag is 0... so doing jump...");
unsafe {
self.state.pc.as_u16 = self
.state
@ -94,7 +94,7 @@ impl CPU {
}
} else {
unsafe {
println!(
verbose_println!(
"not jumping! z flag is {0:#b}, flags are {1:#b} / {1:#X}",
self.get_flag(FLAGS::Z),
self.state.af.as_u8s.right
@ -117,7 +117,7 @@ impl CPU {
},
0x26 => self.state.hl.as_u8s.left = self.ld_immediate_byte(),
0x27 => unsafe {
println!("Running DAA instruction (0x27) that I'm not too sure about...");
verbose_println!("Running DAA instruction (0x27) that I'm not too sure about...");
if self.get_flag(FLAGS::N) == 0 {
if self.get_flag(FLAGS::C) == 1 || self.state.af.as_u8s.left > 0x99 {
self.state.af.as_u8s.left += 0x60;
@ -133,7 +133,7 @@ impl CPU {
self.state.af.as_u8s.left -= 0x6;
}
}
println!(
verbose_println!(
" ...this set register a to {:#X}...",
self.state.af.as_u8s.left
);