diff --git a/Cargo.lock b/Cargo.lock index 1b005cf..a489814 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,6 +6,7 @@ version = 3 name = "Chip8Emulator" version = "0.1.0" dependencies = [ + "anyhow", "env_logger", "log", ] @@ -68,6 +69,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "anyhow" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" + [[package]] name = "colorchoice" version = "1.0.3" diff --git a/Cargo.toml b/Cargo.toml index 7335134..3c6a3a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" [dependencies] log = "0.4.22" env_logger = "0.11.5" +anyhow = "1.0.93" \ No newline at end of file diff --git a/roms/ibm-logo.ch8 b/roms/ibm-logo.ch8 new file mode 100644 index 0000000..677f227 Binary files /dev/null and b/roms/ibm-logo.ch8 differ diff --git a/src/emulator.rs b/src/emulator.rs index 1552a36..ec0ec3f 100644 --- a/src/emulator.rs +++ b/src/emulator.rs @@ -1,17 +1,31 @@ +use anyhow::anyhow; use log::{debug, info}; +use std::fs::File; +use std::io::Read; +use std::path::Path; +const MEMORY_SIZE: usize = 4096; +const NUMBER_OF_REGISTERS: usize = 16; + +/// Emulator emulates the Chip8 CPU. pub struct Emulator { - memory: [u8; 4096] + memory: [u8; MEMORY_SIZE], + registers: [u16; NUMBER_OF_REGISTERS], + program_counter: u16, } impl Emulator { + /// Creates a new `Emulator` instance. + /// pub fn new() -> Emulator { let mut emulator = Emulator { memory: [0; 4096], + registers: [0; 16], + program_counter: 0, }; - + emulator.load_font_data(); - + emulator } @@ -33,12 +47,45 @@ impl Emulator { 0xF0, 0x80, 0x80, 0x80, 0xF0, // C 0xE0, 0x90, 0x90, 0x90, 0xE0, // D 0xF0, 0x80, 0xF0, 0x80, 0xF0, // E - 0xF0, 0x80, 0xF0, 0x80, 0x80 // F + 0xF0, 0x80, 0xF0, 0x80, 0x80, // F ]; - FONT_SPRITES.iter().enumerate().for_each(|i| { - self.memory[0xf0 + i.0] = *i.1 - }); + FONT_SPRITES + .iter() + .enumerate() + .for_each(|i| self.memory[0xf0 + i.0] = *i.1); info!("Loaded font data..."); debug!("Memory:\n{}\n", format!("{:?}", self.memory)) } -} \ No newline at end of file + + /// Emulates the ROM specified at `path`. + pub fn emulate(&mut self, path: T) -> Result<(), anyhow::Error> + where + T: AsRef + std::fmt::Display, + { + self.load_rom(path)?; + + Ok(()) + } + + /// Loads the ROM found at the rom path in the emulator's RAM memory. + fn load_rom(&mut self, rom_file: T) -> Result<(), anyhow::Error> + where + T: AsRef + std::fmt::Display, + { + let mut file = File::open(&rom_file)?; + + // Check ROM length if it overflows max RAM size. + let rom_size = file.metadata()?.len(); + debug!("Open ROM {} of size {} bytes.", &rom_file, rom_size); + if rom_size > MEMORY_SIZE as u64 - 0x200 { + return Err(anyhow!( + "ROM at {} overflows emulator's RAM size of 4kB.", + &rom_file + )); + } + file.read(&mut self.memory[0x200..])?; + + debug!("Memory:\n{}\n", format!("{:?}", self.memory)); + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index 73ef58d..c40446e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,8 +3,12 @@ use env_logger; mod emulator; -fn main() { +fn main() -> Result<(), anyhow::Error> { env_logger::init(); - let emulator = Emulator::new(); + let mut emulator = Emulator::new(); + + emulator.emulate(String::from("./roms/ibm-logo.ch8"))?; + + Ok(()) }