From b41f50f447dee06b0753d524a824f776b51034d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Albeza?= Date: Sun, 28 Jul 2024 10:02:35 +0200 Subject: [PATCH] Implement Jump Offset opcode --- chip8/src/vm.rs | 18 ++++++++++++++++++ chip8/src/vm/opcode.rs | 3 +++ 2 files changed, 21 insertions(+) diff --git a/chip8/src/vm.rs b/chip8/src/vm.rs index a68f350..2b5b5f3 100644 --- a/chip8/src/vm.rs +++ b/chip8/src/vm.rs @@ -82,6 +82,7 @@ impl Vm { Opcode::SubN(x, y) => self.exec_subn_vy_vx(x, y)?, Opcode::ShiftL(x, y) => self.exec_shift_left(x, y)?, Opcode::LoadI(addr) => self.exec_load_i(addr)?, + Opcode::JumpOffset(addr) => self.exec_jump_offset(addr)?, Opcode::Display(x, y, rows) => self.exec_display(x, y, rows)?, Opcode::NoOp => {} _ => todo!(), @@ -259,6 +260,11 @@ impl Vm { Ok(()) } + + fn exec_jump_offset(&mut self, addr: u16) -> Result<()> { + self.pc = addr + self.v_registers[0x0] as u16; + Ok(()) + } } #[cfg(test)] @@ -597,4 +603,16 @@ mod tests { assert_eq!(vm.v_registers[0x0], 0x02); assert_eq!(vm.v_registers[0xf], 0x01); } + + #[test] + fn opcode_jump_offset() { + let rom = [0xb2, 0x00]; + let mut vm = Vm::new(&rom); + vm.v_registers[0x0] = 0xab; + + let res = vm.tick(); + + assert!(res.is_ok()); + assert_eq!(vm.pc, 0x2ab); + } } diff --git a/chip8/src/vm/opcode.rs b/chip8/src/vm/opcode.rs index 73e010d..d8804d9 100644 --- a/chip8/src/vm/opcode.rs +++ b/chip8/src/vm/opcode.rs @@ -22,6 +22,7 @@ pub enum Opcode { SubN(u8, u8), ShiftL(u8, u8), LoadI(u16), + JumpOffset(u16), Display(u8, u8, u8), } @@ -58,6 +59,7 @@ impl TryFrom for Opcode { (0x8, x, y, 0x7) => Ok(Self::SubN(x, y)), (0x8, x, y, 0xe) => Ok(Self::ShiftL(x, y)), (0xa, _, _, _) => Ok(Self::LoadI(nnn)), + (0xb, _, _, _) => Ok(Self::JumpOffset(nnn)), (0xd, x, y, n) => Ok(Self::Display(x, y, n)), _ => Err(VmError::InvalidOpcode(value)), } @@ -88,6 +90,7 @@ mod tests { assert_eq!(Opcode::try_from(0x8ab7), Ok(Opcode::SubN(0xa, 0xb))); assert_eq!(Opcode::try_from(0x8abe), Ok(Opcode::ShiftL(0xa, 0xb))); assert_eq!(Opcode::try_from(0xaabc), Ok(Opcode::LoadI(0x0abc))); + assert_eq!(Opcode::try_from(0xbabc), Ok(Opcode::JumpOffset(0x0abc))); assert_eq!(Opcode::try_from(0xdabc), Ok(Opcode::Display(0xa, 0xb, 0xc))); } }