From 6e76f96467c90924ceb1df54cb97fe0d3ecca0e6 Mon Sep 17 00:00:00 2001 From: Denis Nutiu Date: Fri, 22 Nov 2024 23:14:52 +0200 Subject: [PATCH] add tests --- Cargo.lock | 23 ++++++++++++++ Cargo.toml | 5 ++- src/emulator.rs | 84 ++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 92 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a489814..210e82f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,6 +9,7 @@ dependencies = [ "anyhow", "env_logger", "log", + "pretty_assertions", ] [[package]] @@ -81,6 +82,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "env_filter" version = "0.1.2" @@ -128,6 +135,16 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + [[package]] name = "regex" version = "1.11.1" @@ -235,3 +252,9 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" diff --git a/Cargo.toml b/Cargo.toml index 3c6a3a6..0fa5b53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,7 @@ edition = "2021" [dependencies] log = "0.4.22" env_logger = "0.11.5" -anyhow = "1.0.93" \ No newline at end of file +anyhow = "1.0.93" + +[dev-dependencies] +pretty_assertions = "1.4.1" \ No newline at end of file diff --git a/src/emulator.rs b/src/emulator.rs index ec0ec3f..17d771a 100644 --- a/src/emulator.rs +++ b/src/emulator.rs @@ -6,12 +6,42 @@ use std::path::Path; const MEMORY_SIZE: usize = 4096; const NUMBER_OF_REGISTERS: usize = 16; +const FONT_SPRITES: [u8; 80] = [ + 0xF0, 0x90, 0x90, 0x90, 0xF0, // 0 + 0x20, 0x60, 0x20, 0x20, 0x70, // 1 + 0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2 + 0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3 + 0x90, 0x90, 0xF0, 0x10, 0x10, // 4 + 0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5 + 0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6 + 0xF0, 0x10, 0x20, 0x40, 0x40, // 7 + 0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8 + 0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9 + 0xF0, 0x90, 0xF0, 0x90, 0x90, // A + 0xE0, 0x90, 0xE0, 0x90, 0xE0, // B + 0xF0, 0x80, 0x80, 0x80, 0xF0, // C + 0xE0, 0x90, 0x90, 0x90, 0xE0, // D + 0xF0, 0x80, 0xF0, 0x80, 0xF0, // E + 0xF0, 0x80, 0xF0, 0x80, 0x80, // F +]; /// Emulator emulates the Chip8 CPU. pub struct Emulator { + /// Memory represents the emulator's memory. memory: [u8; MEMORY_SIZE], - registers: [u16; NUMBER_OF_REGISTERS], + /// Registers holds the general purpose registers. + registers: [u8; NUMBER_OF_REGISTERS], + /// The index register store memory addresses. + index_register: u16, + /// The program counter register tracks the currently executing instruction. program_counter: u16, + /// The delay timer register. It is decremented at a rate of 60 Hz until it reaches 0. + delay_timer: u8, + /// The sound timer register. It is decremented at a rate of 60 Hz until it reaches 0. + /// It plays a beeping sound when it's value is different from 0. + sound_timer: u8, + /// The stack pointer register. + stack_pointer: u8, } impl Emulator { @@ -21,7 +51,11 @@ impl Emulator { let mut emulator = Emulator { memory: [0; 4096], registers: [0; 16], + index_register: 0, program_counter: 0, + delay_timer: 0, + sound_timer: 0, + stack_pointer: 0, }; emulator.load_font_data(); @@ -31,24 +65,6 @@ impl Emulator { fn load_font_data(&mut self) { info!("Loading font data..."); - const FONT_SPRITES: [u8; 80] = [ - 0xF0, 0x90, 0x90, 0x90, 0xF0, // 0 - 0x20, 0x60, 0x20, 0x20, 0x70, // 1 - 0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2 - 0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3 - 0x90, 0x90, 0xF0, 0x10, 0x10, // 4 - 0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5 - 0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6 - 0xF0, 0x10, 0x20, 0x40, 0x40, // 7 - 0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8 - 0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9 - 0xF0, 0x90, 0xF0, 0x90, 0x90, // A - 0xE0, 0x90, 0xE0, 0x90, 0xE0, // B - 0xF0, 0x80, 0x80, 0x80, 0xF0, // C - 0xE0, 0x90, 0x90, 0x90, 0xE0, // D - 0xF0, 0x80, 0xF0, 0x80, 0xF0, // E - 0xF0, 0x80, 0xF0, 0x80, 0x80, // F - ]; FONT_SPRITES .iter() .enumerate() @@ -89,3 +105,33 @@ impl Emulator { Ok(()) } } + +#[cfg(test)] +mod tests { + use super::*; + use pretty_assertions::assert_eq; + + #[test] + fn test_load_font_data() { + let emulator = Emulator::new(); + assert_eq!(emulator.memory[0xf0..0xf0 + 80], FONT_SPRITES) + } + + #[test] + fn test_load_rom_ibm_logo() { + // Setup + let mut file = File::open("roms/ibm-logo.ch8").expect("Failed to test open ROM"); + let mut rom_file_data: [u8; 132] = [0; 132]; + file.read(&mut rom_file_data) + .expect("Failed to read test ROM"); + + // Test + let mut emulator = Emulator::new(); + emulator + .load_rom("roms/ibm-logo.ch8") + .expect("failed to load ROM"); + + // Assert + assert_eq!(emulator.memory[0x200..0x200 + 132], rom_file_data) + } +}