From db2c360df3a2f2cb7d4b70cbf16e659f8debcba4 Mon Sep 17 00:00:00 2001 From: Denis-Cosmin NUTIU Date: Sat, 7 Dec 2024 22:48:19 +0200 Subject: [PATCH] add unit tests --- roms/astro-dodge.ch8 | Bin 1113 -> 0 bytes src/emulator.rs | 6 +- src/instruction.rs | 282 ++++++++++++++++++++++++++++++++++++++++--- src/main.rs | 2 +- 4 files changed, 271 insertions(+), 19 deletions(-) delete mode 100644 roms/astro-dodge.ch8 diff --git a/roms/astro-dodge.ch8 b/roms/astro-dodge.ch8 deleted file mode 100644 index e41bf2cdf28ef3a080c4b1c87fd9fd7c07444996..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1113 zcma)4QA}D_82+wY@y@^|SEQ_AgiuHrG4`f3gfhZz7d5GIlPFjo+Sk*4z?k`FeF zCH<0Rr7LV)85kkVzvqL;lG2YcDa&mTw5jA zO4w9cOVX$=Bc8$hw{X3JdpkqQy(2eHhU9;oO*y6dUj6C*rhvcT01p9KIHAJ#Jl-X;gM7QN zn$<>4^1PJe$=rs}C?9@Rj6SM%Fwh1e#>hz(X9&@E&L0>{I{CG5+K{SMah8z&HC+`_ zzS4U`##8;yd5$dUxQijnsRl8mlU{N7-ME6xON^Ygo#&r#ZsXrNiU&FbodMhvhPMReuxv$T5Z=JTNi_ zr3Z)n=RA*Gc}wah83}~q1jMdd{Y9*WXCFQ|g?D}Z(RvFT2ImP3L6~Ol-kkwVzpOI<1DY$IDF6Tf diff --git a/src/emulator.rs b/src/emulator.rs index 760b679..7cabb03 100644 --- a/src/emulator.rs +++ b/src/emulator.rs @@ -362,13 +362,13 @@ where self.index_register = 0xF0 + (self.registers[vx as usize] & 0x0F) as u16; } ProcessorInstruction::BinaryCodedDecimalConversion(vx) => { - todo!("must implement") + // todo!("must implement") } ProcessorInstruction::LoadMemory(vx) => { - todo!("must implement") + // todo!("must implement") } ProcessorInstruction::StoreMemory(vx) => { - todo!("must implement") + // todo!("must implement") } _ => { warn!("Unknown instruction: {:04x}, skipping.", instruction); diff --git a/src/instruction.rs b/src/instruction.rs index 4f42a2c..1557518 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -1,6 +1,5 @@ use std::fmt; use std::fmt::{Display, Formatter, LowerHex}; -use log::info; /* Although every instruction will have a first nibble that tells you what kind of instruction it is, the rest of the nibbles will have different meanings. To differentiate these meanings, @@ -219,20 +218,10 @@ impl Instruction { ProcessorInstruction::FontCharacter(Self::grab_first_nibble(data)) } (0xF, _, 0x3, 0x3) => { - ProcessorInstruction::BinaryCodedDecimalConversion( - Self::grab_first_nibble(data) - ) - } - (0xF, _, 0x5, 0x5) => { - ProcessorInstruction::StoreMemory( - Self::grab_first_nibble(data) - ) - } - (0xF, _, 0x6, 0x5) => { - ProcessorInstruction::LoadMemory( - Self::grab_first_nibble(data) - ) + ProcessorInstruction::BinaryCodedDecimalConversion(Self::grab_first_nibble(data)) } + (0xF, _, 0x5, 0x5) => ProcessorInstruction::StoreMemory(Self::grab_first_nibble(data)), + (0xF, _, 0x6, 0x5) => ProcessorInstruction::LoadMemory(Self::grab_first_nibble(data)), // Unknown instruction _ => ProcessorInstruction::UnknownInstruction, } @@ -309,10 +298,273 @@ mod tests { assert_eq!(instruction, 0xffffu16) } + #[test] + fn test_instruction_clear_screen() { + let instruction = Instruction::new([0x00, 0xE0]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::ClearScreen + ) + } + + #[test] + fn test_instruction_call() { + let instruction = Instruction::new([0x2A, 0xBC]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::Call(0xABC) + ) + } + + #[test] + fn test_instruction_return() { + let instruction = Instruction::new([0x00, 0xEE]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::Return + ) + } + + #[test] + fn test_instruction_skip_equal_vx_data() { + let instruction = Instruction::new([0x3A, 0xBC]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::SkipEqualVXData(0xA, 0xBC) + ) + } + + #[test] + fn test_instruction_skip_not_equal_vx_data() { + let instruction = Instruction::new([0x4A, 0xBC]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::SkipNotEqualVXData(0xA, 0xBC) + ) + } + + #[test] + fn test_instruction_skip_equal_vx_vy() { + let instruction = Instruction::new([0x5A, 0xB0]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::SkipEqualVXVY(0xA, 0xB) + ) + } + + #[test] + fn test_instruction_skip_not_equal_vx_vy() { + let instruction = Instruction::new([0x9A, 0xB0]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::SkipNotEqualVXVY(0xA, 0xB) + ) + } + + #[test] + fn test_instruction_set_register() { + let instruction = Instruction::new([0x61, 0x40]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::SetRegister(0x1, 0x40) + ) + } + + #[test] + fn test_instruction_add_to_register() { + let instruction = Instruction::new([0x71, 0x40]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::AddValueToRegister(0x1, 0x40) + ) + } + + #[test] + fn test_instruction_set() { + let instruction = Instruction::new([0x81, 0x40]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::Set(1, 4) + ) + } + + #[test] + fn test_instruction_binary_or() { + let instruction = Instruction::new([0x81, 0xF1]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::BinaryOr(1, 0xF) + ) + } + + #[test] + fn test_instruction_binary_and() { + let instruction = Instruction::new([0x81, 0xF2]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::BinaryAnd(1, 0xF) + ) + } + + #[test] + fn test_instruction_logical_xor() { + let instruction = Instruction::new([0x81, 0xF3]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::BinaryXor(1, 0xF) + ) + } + + #[test] + fn test_instruction_logical_add() { + let instruction = Instruction::new([0x81, 0xF4]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::Add(1, 0xF) + ) + } + + #[test] + fn test_instruction_logical_subtract_vx() { + let instruction = Instruction::new([0x8E, 0xF5]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::SubtractVX(0xE, 0xF) + ) + } + + #[test] + fn test_instruction_logical_subtract_vy() { + let instruction = Instruction::new([0x8E, 0xF7]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::SubtractVY(0xE, 0xF) + ) + } + #[test] fn test_instruction_shift_left() { let instruction = Instruction::new([0x81, 0x1E]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::ShiftLeft(1, 1) + ) + } - assert_eq!(instruction.processor_instruction, ProcessorInstruction::ShiftLeft(1, 1)) + #[test] + fn test_instruction_shift_right() { + let instruction = Instruction::new([0x81, 0x26]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::ShiftRight(1, 2) + ) + } + + #[test] + fn test_instruction_set_index_register() { + let instruction = Instruction::new([0xAA, 0xBC]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::SetIndexRegister(0xABC) + ) + } + + #[test] + fn test_instruction_jump_with_offset() { + let instruction = Instruction::new([0xBA, 0xBC]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::JumpWithOffset(0xABC) + ) + } + + #[test] + fn test_instruction_random() { + let instruction = Instruction::new([0xCA, 0xBC]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::GenerateRandomNumber(0xA, 0xBC) + ) + } + + #[test] + fn test_instruction_display() { + let instruction = Instruction::new([0xDA, 0xBC]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::Draw(0xA, 0xB, 0xC) + ) + } + + #[test] + fn test_instruction_set_vx_timer() { + let instruction = Instruction::new([0xFA, 0x07]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::SetVXToDelayTimer(0xA) + ) + } + + #[test] + fn test_instruction_set_delay_timer() { + let instruction = Instruction::new([0xFA, 0x15]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::SetDelayTimer(0xA) + ) + } + + #[test] + fn test_instruction_set_sound_timer() { + let instruction = Instruction::new([0xFA, 0x18]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::SetSoundTimer(0xA) + ) + } + + #[test] + fn test_instruction_add_to_index() { + let instruction = Instruction::new([0xFA, 0x1E]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::AddToIndex(0xA) + ) + } + + #[test] + fn test_instruction_font_character() { + let instruction = Instruction::new([0xFA, 0x29]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::FontCharacter(0xA) + ) + } + + #[test] + fn test_instruction_binary_coded_decimal() { + let instruction = Instruction::new([0xFA, 0x33]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::BinaryCodedDecimalConversion(0xA) + ) + } + + #[test] + fn test_instruction_load_memory() { + let instruction = Instruction::new([0xFA, 0x55]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::StoreMemory(0xA) + ) + } + + #[test] + fn test_instruction_store_memory() { + let instruction = Instruction::new([0xFA, 0x65]); + assert_eq!( + instruction.processor_instruction, + ProcessorInstruction::LoadMemory(0xA) + ) } } diff --git a/src/main.rs b/src/main.rs index 25672e8..b1ead3f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ fn main() -> Result<(), anyhow::Error> { let mut emulator = Emulator::new(RatatuiDisplay::new()); - emulator.emulate(String::from("./roms/3-corax+.ch8"))?; + emulator.emulate(String::from("./roms/1-chip8-logo.ch8"))?; Ok(()) }