add unit tests
This commit is contained in:
parent
d42a0ec2c5
commit
db2c360df3
4 changed files with 271 additions and 19 deletions
Binary file not shown.
|
@ -362,13 +362,13 @@ where
|
||||||
self.index_register = 0xF0 + (self.registers[vx as usize] & 0x0F) as u16;
|
self.index_register = 0xF0 + (self.registers[vx as usize] & 0x0F) as u16;
|
||||||
}
|
}
|
||||||
ProcessorInstruction::BinaryCodedDecimalConversion(vx) => {
|
ProcessorInstruction::BinaryCodedDecimalConversion(vx) => {
|
||||||
todo!("must implement")
|
// todo!("must implement")
|
||||||
}
|
}
|
||||||
ProcessorInstruction::LoadMemory(vx) => {
|
ProcessorInstruction::LoadMemory(vx) => {
|
||||||
todo!("must implement")
|
// todo!("must implement")
|
||||||
}
|
}
|
||||||
ProcessorInstruction::StoreMemory(vx) => {
|
ProcessorInstruction::StoreMemory(vx) => {
|
||||||
todo!("must implement")
|
// todo!("must implement")
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
warn!("Unknown instruction: {:04x}, skipping.", instruction);
|
warn!("Unknown instruction: {:04x}, skipping.", instruction);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::{Display, Formatter, LowerHex};
|
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,
|
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,
|
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))
|
ProcessorInstruction::FontCharacter(Self::grab_first_nibble(data))
|
||||||
}
|
}
|
||||||
(0xF, _, 0x3, 0x3) => {
|
(0xF, _, 0x3, 0x3) => {
|
||||||
ProcessorInstruction::BinaryCodedDecimalConversion(
|
ProcessorInstruction::BinaryCodedDecimalConversion(Self::grab_first_nibble(data))
|
||||||
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)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
(0xF, _, 0x5, 0x5) => ProcessorInstruction::StoreMemory(Self::grab_first_nibble(data)),
|
||||||
|
(0xF, _, 0x6, 0x5) => ProcessorInstruction::LoadMemory(Self::grab_first_nibble(data)),
|
||||||
// Unknown instruction
|
// Unknown instruction
|
||||||
_ => ProcessorInstruction::UnknownInstruction,
|
_ => ProcessorInstruction::UnknownInstruction,
|
||||||
}
|
}
|
||||||
|
@ -309,10 +298,273 @@ mod tests {
|
||||||
assert_eq!(instruction, 0xffffu16)
|
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]
|
#[test]
|
||||||
fn test_instruction_shift_left() {
|
fn test_instruction_shift_left() {
|
||||||
let instruction = Instruction::new([0x81, 0x1E]);
|
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)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||||
|
|
||||||
let mut emulator = Emulator::new(RatatuiDisplay::new());
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue