Refactor several opcodes + remove opcode property

This commit is contained in:
Rekai Musuka 2020-07-13 21:39:38 -05:00
parent 05f52dd397
commit f4a8840b91
1 changed files with 37 additions and 40 deletions

View File

@ -5,7 +5,6 @@ use std::path::Path;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct Chip8 { pub struct Chip8 {
opcode: u16,
i: u16, i: u16,
pc: u16, pc: u16,
sp: u8, sp: u8,
@ -21,7 +20,6 @@ pub struct Chip8 {
impl Default for Chip8 { impl Default for Chip8 {
fn default() -> Self { fn default() -> Self {
let mut chip8 = Chip8 { let mut chip8 = Chip8 {
opcode: 0,
i: 0, i: 0,
pc: 0x200, // Progrm counter starts at 0x200 pc: 0x200, // Progrm counter starts at 0x200
sp: 0, sp: 0,
@ -60,16 +58,16 @@ impl Chip8 {
]; ];
pub fn execute_cycle(&mut self) { pub fn execute_cycle(&mut self) {
self.opcode = self.get_opcode(); let opcode = self.get_opcode();
println!("{:#x}", self.opcode); // println!("{:#x}", self.opcode);
self.execute_opcode(); self.execute_opcode(opcode);
self.delay.tick(); self.delay.tick();
self.sound.tick(); self.sound.tick();
} }
pub fn load_font_set(&mut self) { pub fn load_font_set(&mut self) {
self.memory[0..0x50].copy_from_slice(&Self::FONT_SET); self.memory[0x50..0xA0].copy_from_slice(&Self::FONT_SET);
} }
pub fn load_rom<P: AsRef<Path>>(&mut self, path: P) -> Result<(), io::Error> { pub fn load_rom<P: AsRef<Path>>(&mut self, path: P) -> Result<(), io::Error> {
@ -98,11 +96,11 @@ impl Chip8 {
) )
} }
fn execute_opcode(&mut self) { fn execute_opcode(&mut self, opcode: u16) {
let (nib_1, nib_2, nib_3, nib_4) = Self::get_nibs(self.opcode); let (nib_1, nib_2, nib_3, nib_4) = Self::get_nibs(opcode);
let nnn: u16 = self.opcode & 0x0FFF; let nnn: u16 = opcode & 0x0FFF;
let kk: u8 = (self.opcode & 0x00FF) as u8; let kk: u8 = (opcode & 0x00FF) as u8;
let x = nib_2; let x = nib_2;
let y = nib_3; let y = nib_3;
let n = nib_4; let n = nib_4;
@ -114,6 +112,8 @@ impl Chip8 {
(0x0, 0x0, 0xE, 0x0) => self.cls(), (0x0, 0x0, 0xE, 0x0) => self.cls(),
// 00EE // 00EE
(0x0, 0x0, 0xE, 0xE) => self.ret(), (0x0, 0x0, 0xE, 0xE) => self.ret(),
// 0NNN
(0x0, _, _, _) => { /* Nothing to see here */ }
// 1NNN // 1NNN
(0x1, _, _, _) => self.jmp_addr(nnn), (0x1, _, _, _) => self.jmp_addr(nnn),
// 2NNN // 2NNN
@ -179,7 +179,7 @@ impl Chip8 {
// Fx65 // Fx65
(0xF, _, 0x6, 0x5) => self.load_into_vx_from_i(x), (0xF, _, 0x6, 0x5) => self.load_into_vx_from_i(x),
// Otherwise... // Otherwise...
_ => panic!("UNIMPLEMENTED OPCODE: {:#x}", self.opcode), _ => panic!("UNIMPLEMENTED OPCODE: {:#x}", opcode),
} }
} }
@ -197,7 +197,7 @@ impl Chip8 {
fn jmp_addr(&mut self, nnn: u16) { fn jmp_addr(&mut self, nnn: u16) {
// sets the program counter to addr (nnn) // sets the program counter to addr (nnn)
self.pc = nnn; self.pc = nnn - 2; // We want to execute nnn so decrement pc by 2;
} }
fn call_addr(&mut self, nnn: u16) { fn call_addr(&mut self, nnn: u16) {
@ -205,7 +205,7 @@ impl Chip8 {
// pc is then set to addr // pc is then set to addr
self.sp += 1; self.sp += 1;
self.stack[self.sp as usize] = self.pc; self.stack[self.sp as usize] = self.pc;
self.pc = nnn; self.pc = nnn - 2; // see Chip8#jmp_addr()
} }
fn se_vx_byte(&mut self, x: u8, kk: u8) { fn se_vx_byte(&mut self, x: u8, kk: u8) {
@ -236,6 +236,7 @@ impl Chip8 {
fn add_vx_byte(&mut self, x: u8, kk: u8) { fn add_vx_byte(&mut self, x: u8, kk: u8) {
// calculate Vx + kk, then store it in Vx // calculate Vx + kk, then store it in Vx
// This does indeed overflow without setting VF
self.v[x as usize] = self.v[x as usize].wrapping_add(kk); self.v[x as usize] = self.v[x as usize].wrapping_add(kk);
} }
@ -265,22 +266,19 @@ impl Chip8 {
// only the lowest 8 bits of result are stored in Vx // only the lowest 8 bits of result are stored in Vx
let x = x as usize; let x = x as usize;
let (res, did_overflow) = self.v[x].overflowing_add(self.v[y as usize]); let (sum, did_overflow) = self.v[x].overflowing_add(self.v[y as usize]);
self.v[x] = sum;
self.v[0xF] = if did_overflow { 1 } else { 0 }; self.v[0xF] = if did_overflow { 1 } else { 0 };
self.v[x] = res;
} }
fn sub_vx_vy(&mut self, x: u8, y: u8) { fn sub_vx_vy(&mut self, x: u8, y: u8) {
// TODO: Confirm that the default behaviour
// for this opcode includes a wrapping subtraction
// subtract Vx and Vy, if Vx > Vy VF is set to 1, otherwise 0 // subtract Vx and Vy, if Vx > Vy VF is set to 1, otherwise 0
// then set Vx to Vx - Vy // then set Vx to Vx - Vy
let vx = self.v[x as usize]; let x = x as usize;
let vy = self.v[y as usize]; let y = y as usize;
self.v[0xF] = if vx > vy { 1 } else { 0 }; self.v[0xF] = if self.v[x] > self.v[y] { 1 } else { 0 };
self.v[x as usize] = vx.wrapping_sub(vy); self.v[x] = self.v[x].wrapping_sub(self.v[y]);
} }
fn shr(&mut self, x: u8) { fn shr(&mut self, x: u8) {
@ -288,18 +286,18 @@ impl Chip8 {
// then shift Vx one to the right // then shift Vx one to the right
let x = x as usize; let x = x as usize;
self.v[0xF] = if (self.v[x] & 1) == 1 { 1 } else { 0 }; self.v[0xF] = if (self.v[x] & 0x01) == 0x01 { 1 } else { 0 };
self.v[x] >>= 1; self.v[x] >>= 1;
} }
fn subn_vx_vy(&mut self, x: u8, y: u8) { fn subn_vx_vy(&mut self, x: u8, y: u8) {
// subtract Vy and Vx, if Vy > Vx VF is set to 1, otherwise 0 // subtract Vy and Vx, if Vy > Vx VF is set to 1, otherwise 0
// then set Vx = Vy - Vx // then set Vx = Vy - Vx
let vx = self.v[x as usize]; let x = x as usize;
let vy = self.v[y as usize]; let y = y as usize;
self.v[0xF] = if vy > vx { 1 } else { 0 }; self.v[0xF] = if self.v[y] > self.v[x] { 1 } else { 0 };
self.v[x as usize] = vy.wrapping_sub(vx); self.v[x as usize] = self.v[y].wrapping_sub(self.v[x]);
} }
fn shl(&mut self, x: u8) { fn shl(&mut self, x: u8) {
@ -325,7 +323,7 @@ impl Chip8 {
fn jmp_addr_with_offset(&mut self, nnn: u16) { fn jmp_addr_with_offset(&mut self, nnn: u16) {
// set program counter to addr + V0 // set program counter to addr + V0
self.pc = nnn + self.v[0] as u16; self.pc = nnn + self.v[0] as u16 - 2; // see Chip8#jmp_addr
} }
fn rand(&mut self, x: u8, kk: u8) { fn rand(&mut self, x: u8, kk: u8) {
@ -347,7 +345,6 @@ impl Chip8 {
fn skip_on_press(&mut self, x: u8) { fn skip_on_press(&mut self, x: u8) {
// if current key is the same as the on in Vx // if current key is the same as the on in Vx
// program counter is increased by 2 // program counter is increased by 2
if self.key.is_pressed(self.v[x as usize]) { if self.key.is_pressed(self.v[x as usize]) {
self.pc += 2; self.pc += 2;
} }
@ -356,7 +353,6 @@ impl Chip8 {
fn skip_not_pressed(&mut self, x: u8) { fn skip_not_pressed(&mut self, x: u8) {
// if current key is not the sameas the one in Vx // if current key is not the sameas the one in Vx
// increment the program counter by 2 // increment the program counter by 2
if !self.key.is_pressed(self.v[x as usize]) { if !self.key.is_pressed(self.v[x as usize]) {
self.pc += 2; self.pc += 2;
} }
@ -389,12 +385,16 @@ impl Chip8 {
fn add_vx_to_i(&mut self, x: u8) { fn add_vx_to_i(&mut self, x: u8) {
// set I to be I + Vx // set I to be I + Vx
self.i += self.v[x as usize] as u16; // Althought not standard, we check for overflow as well here
// Memory is 4KB (12-bits) so anything mor than that "overflows"
let sum = self.i + self.v[x as usize] as u16;
self.v[0xF] = if sum > 0x0FFF { 1 } else { 0 };
self.i = sum & 0x0FFF;
} }
fn set_i_to_hex_sprite_loc(&mut self, x: u8) { fn set_i_to_hex_sprite_loc(&mut self, x: u8) {
// set I to location of hex sprite related to Vx // set I to location of hex sprite related to Vx
self.i = self.v[x as usize] as u16 * 5; self.i = 0x50 + (5 * self.v[x as usize] as u16);
} }
fn copy_digits_to_i(&mut self, x: u8) { fn copy_digits_to_i(&mut self, x: u8) {
@ -402,11 +402,11 @@ impl Chip8 {
// take tens digit and place it at I + 1 // take tens digit and place it at I + 1
// take ones digit and place it at I + 2 // take ones digit and place it at I + 2
let i = self.i as usize; let i = self.i as usize;
let mut iter = Self::digits(self.v[x as usize] as usize); let mut digit = Self::digits(self.v[x as usize] as usize);
let ones = iter.next().unwrap(); // Ther has to at least be a ones lol let ones = digit.next().unwrap(); // Ther has to at least be a ones lol
let tens = iter.next().unwrap_or(0); let tens = digit.next().unwrap_or(0);
let hundreds = iter.next().unwrap_or(0); let hundreds = digit.next().unwrap_or(0);
self.memory[i] = hundreds as u8; self.memory[i] = hundreds as u8;
self.memory[i + 1] = tens as u8; self.memory[i + 1] = tens as u8;
@ -415,7 +415,6 @@ impl Chip8 {
fn copy_from_vx_to_memory(&mut self, x: u8) { fn copy_from_vx_to_memory(&mut self, x: u8) {
// copy values v0 -> Vx to memory starting at i // copy values v0 -> Vx to memory starting at i
for n in 0..=(x as usize) { for n in 0..=(x as usize) {
self.memory[self.i as usize + n] = self.v[n]; self.memory[self.i as usize + n] = self.v[n];
} }
@ -423,9 +422,7 @@ impl Chip8 {
fn load_into_vx_from_i(&mut self, x: u8) { fn load_into_vx_from_i(&mut self, x: u8) {
// read what will be values of v0 -> vx from memory starting at i // read what will be values of v0 -> vx from memory starting at i
let x = x as usize; for n in 0..=(x as usize) {
for n in 0..=x {
self.v[n] = self.memory[self.i as usize + n]; self.v[n] = self.memory[self.i as usize + n];
} }
} }