diff --git a/Cargo.lock b/Cargo.lock index d70adbe..77c0ee2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,150 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] +name = "colored" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" +dependencies = [ + "is-terminal", + "lazy_static", + "windows-sys", +] + [[package]] name = "emulator" version = "0.1.0" +dependencies = [ + "colored", +] + +[[package]] +name = "errno" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi", + "rustix", + "windows-sys", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "linux-raw-sys" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" + +[[package]] +name = "rustix" +version = "0.38.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ad981d6c340a49cdc40a1028d9c6084ec7e9fa33fcb839cab656a267071e234" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/Cargo.toml b/Cargo.toml index d3cd672..641a45a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,3 +2,7 @@ name = "emulator" version = "0.1.0" edition = "2021" + +# Stuff used for the examples +[dev-dependencies] +colored = "2.0.4" diff --git a/examples/debugger.rs b/examples/debugger.rs new file mode 100644 index 0000000..fc311e5 --- /dev/null +++ b/examples/debugger.rs @@ -0,0 +1,133 @@ +use colored::{ColoredString, Colorize}; +use std::{ + fmt::LowerHex, + io::{self, stdin, stdout, Write}, + process::exit, +}; + +use emulator::GameBoy; + +fn ask_input(text: &str) -> String { + let mut input = String::new(); + + print!("{}", text); + let _ = stdout().flush(); + stdin() + .read_line(&mut input) + .expect("Could not read string"); + + input +} + +// Output functions +fn hex_to_string(hex: T) -> ColoredString { + format!("{:x}", hex).bold().green() +} + +fn bool_to_symbol(boolean: bool) -> ColoredString { + match boolean { + true => String::from("✔️ ").green(), + false => String::from("❌").red(), + } + .bold() +} + +fn pretty_print_gameboy(gameboy: &GameBoy) -> Result<(), io::Error> { + let stdout = std::io::stdout(); + let mut lock = stdout.lock(); + + writeln!(lock, "{}", "Registers".bold().red())?; + writeln!( + lock, + " A: {}, B: {}, C: {}, D: {}, E: {}, H: {}, L: {}, SP: {}, PC: {}", + hex_to_string(gameboy.registers.a), + hex_to_string(gameboy.registers.b), + hex_to_string(gameboy.registers.c), + hex_to_string(gameboy.registers.d), + hex_to_string(gameboy.registers.e), + hex_to_string(gameboy.registers.h), + hex_to_string(gameboy.registers.l), + hex_to_string(gameboy.registers.sp), + format!("{:x}", gameboy.registers.pc).bold().blue(), + )?; + + writeln!(lock, "{}", "Flags".bold().red())?; + writeln!( + lock, + " Zero: {}, IME: {}", + bool_to_symbol(gameboy.flags.zero), + bool_to_symbol(gameboy.flags.ime), + )?; + + if let Some(opcode) = gameboy.current_opcode { + writeln!(lock, "{}", "Others".bold().red())?; + writeln!(lock, " Current opcode: {}", hex_to_string(opcode))?; + } + + writeln!(lock, "")?; + Ok(()) +} + +fn main() { + let args: Vec = std::env::args().collect(); + + if args.len() != 2 { + println!("You need to specify the rom file"); + std::process::exit(1); + } + + let rom_path = args.last().unwrap(); + let mut gameboy = GameBoy::new(&rom_path).unwrap(); + + // Input + #[rustfmt::skip] + println!("Choose one of the options"); + println!("{}. Run until PC is a certain value", "1".red().bold()); + println!( + "{}. Run until a specific opcode is executed", + "2".red().bold() + ); + println!("Input anything else to just run"); + + let input = ask_input("Enter setting: "); + let mut additional_input: u16 = 0; + + let input = input.as_str().trim(); + + // Some options will require additional input + match input { + "1" | "2" => { + additional_input = + // We need to convert the input to hexadecimal + u16::from_str_radix(ask_input("Enter additional input: ").trim(), 16).unwrap() + } + + _ => {} + } + + // Actually running the emulator + loop { + let _ = pretty_print_gameboy(&gameboy); + + // Stopping the emulator + match input { + "1" => { + if gameboy.registers.pc == additional_input { + exit(0); + } + } + + "2" => { + if let Some(opcode) = gameboy.current_opcode { + if opcode == additional_input as u8 { + exit(0); + } + } + } + + _ => {} + } + + gameboy.step(); + } +} diff --git a/examples/terminal.rs b/examples/terminal.rs deleted file mode 100644 index a09394c..0000000 --- a/examples/terminal.rs +++ /dev/null @@ -1,27 +0,0 @@ -use emulator::GameBoy; - -fn main() { - let args: Vec = std::env::args().collect(); - - if args.len() != 2 { - println!("You need to specify the rom file"); - std::process::exit(1); - } - - let rom_path = args.last().unwrap(); - - let mut gameboy = GameBoy::new(&rom_path).unwrap(); - - loop { - print!("{:?}", gameboy.registers); - - gameboy.step(); - - // if gameboy.current_opcode.unwrap() == 0x00 || gameboy.current_opcode.unwrap() == 0xC8 { - // let _ = io::stdin().read_line(&mut String::new()); - // } - - println!("OPCODE: {:x}", gameboy.current_opcode.unwrap()); - println!(""); - } -} diff --git a/src/registers.rs b/src/registers.rs index d2468dd..bad9d3e 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -35,18 +35,6 @@ impl Default for Registers { } } -impl Debug for Registers { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - writeln!( - f, - "A: {:x} B: {:x} C: {:x} D: {:x}\n\ - E: {:x} H: {:x} L: {:x}\n\ - SP: {:x} PC: {:x}", - self.a, self.b, self.c, self.d, self.e, self.h, self.l, self.sp, self.pc - ) - } -} - pub(crate) enum OneByteRegister { A, B,