trevors_chip8_toy/emma/src/chip8/instructions.rs
Trevor Merritt d6f7c73de3 add test chip8 file
more decoder and executor code
lots and lots more tests.  lots and lots and lots and lots more needed
2024-09-23 16:12:52 -04:00

191 lines
6.8 KiB
Rust

#[derive(Debug)]
pub enum Chip8CpuInstructions {
SysAddr(i16), // 0x0nnn Exit to System Call
CLS, // * 0x00E0 Clear Screen
RET, // 0x00EE Return from Subroutine
JpAddr(i16), // 0x1nnn Jump to Address
CallAddr(i16), // 0x2nnn Call Subroutine
SeVxByte(i16, i16), // 0x3xkk Skip next instruction if Vx = kk.
SneVxByte(i16, i16), // 0x4xkk Skip next instruction if Vx != kk
SeVxVy(u16, u16), // 0x5xy0 Skip next instruction if Vx == Vy
LdVxByte(u16, u16), // * 0x6xkk Set Vx = kk
AddVxByte(u16, u16), // 0x7xkk Set Vx = Vx + kk
LdVxVy(u16, u16), // 0x8xy0 Set value of Vy in Vx
OrVxVy(u16, u16), // 0x8xy1 Set Vx = Vx OR Vy
AndVxVy(u16, u16), // 0x8xy2 Set Vx = Vx AND Vy
XorVxVy(u16, u16), // 0x8xy3 Set Vx = Vx XOR Vy
AddVxVy(u16, u16), // 0x8xy4 Set Vx = Vx + Vy (SET VF on Carry)
SubVxVy(u16, u16), // 0x8xy5 Set Vx = Vx - Vy (Set VF NOT Borrow)
ShrVxVy(u16, u16), // 0x8xy6 Set Vx = Vx SHR 1 (Shift Rotated Right 1)
SubnVxVy(u16, u16), // 0x8xy7 Set Vx = Vy - Vx (Set VF NOT Borrow)
ShlVxVy(u16, u16), // 0x8xyE Shift Left
SneVxVy(u16, u16), // 0x9xy0 Skip next instruction if Vx != Vy
LdIAddr(u16), // * 0xAnnn VI = nnn
JpV0Addr(u16), // 0xBnnn Jump to nnn+V0
RndVxByte(u16, u16), // 0xCxkk Vx = random byte AND kk
DrawVxVyNibble(u16, u16, u16), // * 0xDxyn Display N byte sprite starting at Vx to Vy
SkpVx(u16), // 0xE09E Skip next instruction if key in Vx pressed
SnkpVx(u16), // 0xE0A1 Skip next instruction if key in Vx NOT pressed
LdVxDt(u16), // 0xFx07 Set Vx = Delay timer
LdVxK(u16), // 0xFx0A Wait for key, put in Vx
LdDtVx(u16), // 0xFx15 Set Delay Timer
LdStVx(u16), // 0xFx18 Set Sount Timer
AddIVx(u16), // 0xFx1E I = I + Vx
LdFVx(u16), // 0xFx29 Set I = Location of sprite for Digit Vx
LdBVx(u16), // 0xFx33 Store BCD of Vx in I, I+1, I+2
LdIVx(u16), // 0xFx55 Store V0 to Vx in memory starting at I
LdVxI(u16), // 0xFx65 Load V0 to Vx in memory starting at I
XXXXERRORINSTRUCTION,
}
#[derive(Clone)]
struct Chip8SystemState {
pub video_memory: [bool; 512],
pub memory: [u8; 4096],
pub registers: [u8; 16],
pub i: i16,
pub pc: i16,
pub sound_timer: i8,
pub delay_timer: i8
}
trait Chip8Instruction {
fn execute(&self, input: Chip8SystemState) -> Chip8SystemState;
}
impl Chip8Instruction for Chip8CpuInstructions {
fn execute(&self, mut input: Chip8SystemState) -> Chip8SystemState {
match self {
Chip8CpuInstructions::SysAddr(new_address) => {
let mut new_state = input.clone();
new_state.pc = *new_address;
new_state
}
Chip8CpuInstructions::CLS => {
input.video_memory = [false; 512];
input
}
Chip8CpuInstructions::RET => {
input
}
Chip8CpuInstructions::JpAddr(new_address) => {
input
}
Chip8CpuInstructions::CallAddr(_) => {
input
}
Chip8CpuInstructions::SeVxByte(_, _) => {
input
}
Chip8CpuInstructions::SneVxByte(_, _) => {
input
}
Chip8CpuInstructions::SeVxVy(_, _) => {
input
}
Chip8CpuInstructions::LdVxByte(register, byte) => {
input.registers[*register as usize] = byte.to_be_bytes()[0];
input
}
Chip8CpuInstructions::AddVxByte(_, _) => {
input
}
Chip8CpuInstructions::LdVxVy(_, _) => {
input
}
Chip8CpuInstructions::OrVxVy(_, _) => {
input
}
Chip8CpuInstructions::AndVxVy(_, _) => {
input
}
Chip8CpuInstructions::XorVxVy(_, _) => {
input
}
Chip8CpuInstructions::AddVxVy(_, _) => {
input
}
Chip8CpuInstructions::SubVxVy(_, _) => {
input
}
Chip8CpuInstructions::ShrVxVy(_, _) => {
input
}
Chip8CpuInstructions::SubnVxVy(_, _) => {
input
}
Chip8CpuInstructions::ShlVxVy(_, _) => {
input
}
Chip8CpuInstructions::SneVxVy(_, _) => {
input
}
Chip8CpuInstructions::LdIAddr(new_index) => {
input.i = *new_index as i16;
input
}
Chip8CpuInstructions::JpV0Addr(_) => {
input
}
Chip8CpuInstructions::RndVxByte(_, _) => {
input
}
Chip8CpuInstructions::DrawVxVyNibble(x, y, n) => {
// read nibble bytes from memory starting at I
let mut did_change: bool = false;
for draw_x in 0..*n {
let mut new_value = input.memory[(input.i + draw_x as i16) as usize];
for draw_y in 0..8 {
}
}
if did_change {
input.registers[0xF] = 1u8;
} else {
input.registers[0xF] = 0u8;
}
input
}
Chip8CpuInstructions::SkpVx(_) => {
input
}
Chip8CpuInstructions::SnkpVx(_) => {
input
}
Chip8CpuInstructions::LdVxDt(_) => {
input
}
Chip8CpuInstructions::LdVxK(_) => {
input
}
Chip8CpuInstructions::LdDtVx(_) => {
input
}
Chip8CpuInstructions::LdStVx(_) => {
input
}
Chip8CpuInstructions::AddIVx(_) => {
input
}
Chip8CpuInstructions::LdFVx(_) => {
input
}
Chip8CpuInstructions::LdBVx(_) => {
input
}
Chip8CpuInstructions::LdIVx(_) => {
input
}
Chip8CpuInstructions::LdVxI(_) => {
input
}
Chip8CpuInstructions::XXXXERRORINSTRUCTION => {
input
}
}
}
}