From d6ef37daf9357f0e84a6dfed79a23883a2291a31 Mon Sep 17 00:00:00 2001 From: Denis Nutiu Date: Sat, 7 Dec 2024 12:37:01 +0200 Subject: [PATCH] implement skip conditional instructions set --- src/emulator.rs | 30 ++++++++++++++++++++++++++++-- src/instruction.rs | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/emulator.rs b/src/emulator.rs index 6d270bc..9a6f8a3 100644 --- a/src/emulator.rs +++ b/src/emulator.rs @@ -3,11 +3,11 @@ use crate::instruction::{Instruction, ProcessorInstruction}; use crate::stack::Stack; use anyhow::anyhow; use log::{debug, info, trace, warn}; +use rand::Rng; use std::fs::File; use std::io::Read; use std::path::Path; use std::{thread, time}; -use rand::Rng; /// Represents the display's width in pixels. const DISPLAY_WIDTH: usize = 64; @@ -279,7 +279,33 @@ where ProcessorInstruction::GenerateRandomNumber(register, data) => { self.registers[register as usize] = rand::thread_rng().gen_range(0x00..0xFF) & data } - ProcessorInstruction::UnknownInstruction => { + ProcessorInstruction::SkipEqualVXData(vx, data) => { + let vx_data = self.registers[vx as usize]; + if vx_data == data { + self.program_counter += 2 + } + } + ProcessorInstruction::SkipNotEqualVXData(vx, data) => { + let vx_data = self.registers[vx as usize]; + if vx_data != data { + self.program_counter += 2 + } + } + ProcessorInstruction::SkipEqualVXVY(vx, vy) => { + let vx_data = self.registers[vx as usize]; + let vy_data = self.registers[vy as usize]; + if vx_data == vy_data { + self.program_counter += 2 + } + } + ProcessorInstruction::SkipNotEqualVXVY(vx, vy) => { + let vx_data = self.registers[vx as usize]; + let vy_data = self.registers[vy as usize]; + if vx_data != vy_data { + self.program_counter += 2 + } + } + _ => { warn!("Unknown instruction: {:04x}, skipping.", instruction); } } diff --git a/src/instruction.rs b/src/instruction.rs index 51d289c..66988fd 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -54,6 +54,14 @@ pub enum ProcessorInstruction { JumpWithOffset(u16), /// Generates a random number ANDed with the data and stores it in VX. GenerateRandomNumber(u8, u8), + /// Skips the next instruction if VX is equal to data. + SkipEqualVXData(u8, u8), + /// Skip the next instruction if VX is not equal to data. + SkipNotEqualVXData(u8, u8), + /// Skips the next instruction if VX is equal to VY. + SkipEqualVXVY(u8, u8), + /// Skip the next instruction if VX is not equal to VY. + SkipNotEqualVXVY(u8, u8), /// Unknown instruction UnknownInstruction, } @@ -172,15 +180,27 @@ impl Instruction { Self::grab_first_nibble(data), Self::grab_middle_nibble(data), ), - (0xB, _, _, _) => { - ProcessorInstruction::JumpWithOffset(Self::grab_inner_data(data)) - } - (0xC, _, _, _) => { - ProcessorInstruction::GenerateRandomNumber( - Self::grab_first_nibble(data), - Self::grab_last_byte(data), - ) - } + (0xB, _, _, _) => ProcessorInstruction::JumpWithOffset(Self::grab_inner_data(data)), + (0xC, _, _, _) => ProcessorInstruction::GenerateRandomNumber( + Self::grab_first_nibble(data), + Self::grab_last_byte(data), + ), + (0x3, _, _, _) => ProcessorInstruction::SkipEqualVXData( + Self::grab_first_nibble(data), + Self::grab_last_byte(data), + ), + (0x4, _, _, _) => ProcessorInstruction::SkipNotEqualVXData( + Self::grab_first_nibble(data), + Self::grab_last_byte(data), + ), + (0x5, _, _, 0x0) => ProcessorInstruction::SkipEqualVXVY( + Self::grab_first_nibble(data), + Self::grab_middle_nibble(data), + ), + (0x9, _, _, 0x0) => ProcessorInstruction::SkipNotEqualVXVY( + Self::grab_first_nibble(data), + Self::grab_middle_nibble(data), + ), // Unknown instruction _ => ProcessorInstruction::UnknownInstruction, }