#[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 } } } }