diff --git a/.gitignore b/.gitignore index ea8c4bf..2c96eb1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -/target +target/ +Cargo.lock diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index ae03c9f..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,32 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "carter-emu" -version = "0.1.0" -dependencies = [ - "itertools", - "pretty-hex", -] - -[[package]] -name = "either" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" - -[[package]] -name = "itertools" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8bf247779e67a9082a4790b45e71ac7cfd1321331a5c856a74a9faebdab78d0" -dependencies = [ - "either", -] - -[[package]] -name = "pretty-hex" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa0831dd7cc608c38a5e323422a0077678fa5744aa2be4ad91c4ece8eec8d5" diff --git a/Cargo.toml b/Cargo.toml index 87be82b..797c6f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,8 +3,13 @@ name = "carter-emu" version = "0.1.0" edition = "2021" +[[bin]] +name = "ce" +path = "src/main.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -itertools = "*" -pretty-hex = "*" +itertools = "0.10.*" +pretty-hex = "0.3.*" +clap = {version = "3.2.*", features=["derive"]} diff --git a/src/main.rs b/src/main.rs index 6e1df33..89dac0c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,18 +1,30 @@ +use clap::Parser; use itertools::Itertools; use pretty_hex::*; -use std::env; use std::fs; +use std::io::{stdin, Read}; + +#[derive(Parser)] +#[clap(version, about)] +struct Args { + /// Path to file to execute + #[clap(value_parser)] + path: String, + + /// Set debug level + /// -d for stepping + /// -dd for debug info at step + #[clap(short, action = clap::ArgAction::Count)] + debug: u8, +} fn main() -> Result<(), std::io::Error> { println!("carter-emu v{}", env!("CARGO_PKG_VERSION")); // load program from file into memory - let args: Vec = env::args().collect(); - if args.len() < 2 { - panic!("usage: ce "); - } + let args = Args::parse(); - let mut in_bytes: Vec = fs::read(&args[1])?; + let mut in_bytes: Vec = fs::read(&args.path)?; in_bytes.pop(); // remove trailing newline let instructions = Instruction::from_chars(in_bytes.into_iter()); @@ -28,14 +40,14 @@ fn main() -> Result<(), std::io::Error> { } mem.resize(256, 0); - execute(&mut mem); + execute(&mut mem, args.debug); println!("{}", pretty_hex(&mem)); Ok(()) } -fn execute(mem: &mut Vec) { +fn execute(mem: &mut Vec, step: u8) { // prep registers let mut dp = 0; // data pointer let mut ipl = 0; // instruction pointer low @@ -43,6 +55,8 @@ fn execute(mem: &mut Vec) { let mut rpl = 0; // return pointer low let mut rph = 0; // return pointer high + let mut stdin = stdin(); + loop { if ipl == 256 { return; @@ -51,6 +65,15 @@ fn execute(mem: &mut Vec) { loop { let inst = ins[iph]; + + if step > 1 { + print_state(ipl, iph, dp, mem, rpl, rph); + } + if step > 0 { + println!(">>> {inst}"); + let _ = stdin.read(&mut [0u8]).unwrap(); + } + match inst { Instruction::LoopOpen => { rpl = ipl; @@ -85,6 +108,24 @@ fn execute(mem: &mut Vec) { } } +fn print_state(ipl: usize, iph: usize, dp: usize, mem: &Vec, rpl: usize, rph: usize) { + println!( + "ipl: {:2X} = {} +iph: {:2X} + dp: {:2X} = {:2X} +rpl: {:2X} = {} +rph: {:2X}", + ipl, + Instruction::display_byte(mem[ipl]), + iph, + dp, + mem[dp], + rpl, + Instruction::display_byte(mem[rpl]), + rph, + ); +} + #[derive(Copy, Clone)] enum Instruction { LoopOpen, @@ -110,7 +151,6 @@ impl fmt::Display for Instruction { } impl Instruction { - #[allow(dead_code)] fn from_byte(byte: u8) -> Vec { // split into 2-bit pairs before mapping [ @@ -156,4 +196,9 @@ impl Instruction { | Instruction::to_pair(is.get(2)) << 2 | Instruction::to_pair(is.get(3)) } + + fn display_byte(byte: u8) -> String { + let is = Instruction::from_byte(byte); + format!("{} {} {} {}", is[0], is[1], is[2], is[3]) + } }