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)]
pub struct Chip8 {
opcode: u16,
i: u16,
pc: u16,
sp: u8,
@ -21,7 +20,6 @@ pub struct Chip8 {
impl Default for Chip8 {
fn default() -> Self {
let mut chip8 = Chip8 {
opcode: 0,
i: 0,
pc: 0x200, // Progrm counter starts at 0x200
sp: 0,
@ -60,16 +58,16 @@ impl Chip8 {
];
pub fn execute_cycle(&mut self) {
self.opcode = self.get_opcode();
println!("{:#x}", self.opcode);
self.execute_opcode();
let opcode = self.get_opcode();
// println!("{:#x}", self.opcode);
self.execute_opcode(opcode);
self.delay.tick();
self.sound.tick();
}
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> {
@ -98,11 +96,11 @@ impl Chip8 {
)
}
fn execute_opcode(&mut self) {
let (nib_1, nib_2, nib_3, nib_4) = Self::get_nibs(self.opcode);
fn execute_opcode(&mut self, opcode: u16) {
let (nib_1, nib_2, nib_3, nib_4) = Self::get_nibs(opcode);
let nnn: u16 = self.opcode & 0x0FFF;
let kk: u8 = (self.opcode & 0x00FF) as u8;
let nnn: u16 = opcode & 0x0FFF;
let kk: u8 = (opcode & 0x00FF) as u8;
let x = nib_2;
let y = nib_3;
let n = nib_4;
@ -114,6 +112,8 @@ impl Chip8 {
(0x0, 0x0, 0xE, 0x0) => self.cls(),
// 00EE
(0x0, 0x0, 0xE, 0xE) => self.ret(),
// 0NNN
(0x0, _, _, _) => { /* Nothing to see here */ }
// 1NNN
(0x1, _, _, _) => self.jmp_addr(nnn),
// 2NNN
@ -179,7 +179,7 @@ impl Chip8 {
// Fx65
(0xF, _, 0x6, 0x5) => self.load_into_vx_from_i(x),
// 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) {
// 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) {
@ -205,7 +205,7 @@ impl Chip8 {
// pc is then set to addr
self.sp += 1;
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) {
@ -236,6 +236,7 @@ impl Chip8 {
fn add_vx_byte(&mut self, x: u8, kk: u8) {
// 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);
}
@ -265,22 +266,19 @@ impl Chip8 {
// only the lowest 8 bits of result are stored in Vx
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[x] = res;
}
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
// then set Vx to Vx - Vy
let vx = self.v[x as usize];
let vy = self.v[y as usize];
let x = x as usize;
let y = y as usize;
self.v[0xF] = if vx > vy { 1 } else { 0 };
self.v[x as usize] = vx.wrapping_sub(vy);
self.v[0xF] = if self.v[x] > self.v[y] { 1 } else { 0 };
self.v[x] = self.v[x].wrapping_sub(self.v[y]);
}
fn shr(&mut self, x: u8) {
@ -288,18 +286,18 @@ impl Chip8 {
// then shift Vx one to the right
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;
}
fn subn_vx_vy(&mut self, x: u8, y: u8) {
// subtract Vy and Vx, if Vy > Vx VF is set to 1, otherwise 0
// then set Vx = Vy - Vx
let vx = self.v[x as usize];
let vy = self.v[y as usize];
let x = x as usize;
let y = y as usize;
self.v[0xF] = if vy > vx { 1 } else { 0 };
self.v[x as usize] = vy.wrapping_sub(vx);
self.v[0xF] = if self.v[y] > self.v[x] { 1 } else { 0 };
self.v[x as usize] = self.v[y].wrapping_sub(self.v[x]);
}
fn shl(&mut self, x: u8) {
@ -325,7 +323,7 @@ impl Chip8 {
fn jmp_addr_with_offset(&mut self, nnn: u16) {
// 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) {
@ -347,7 +345,6 @@ impl Chip8 {
fn skip_on_press(&mut self, x: u8) {
// if current key is the same as the on in Vx
// program counter is increased by 2
if self.key.is_pressed(self.v[x as usize]) {
self.pc += 2;
}
@ -356,7 +353,6 @@ impl Chip8 {
fn skip_not_pressed(&mut self, x: u8) {
// if current key is not the sameas the one in Vx
// increment the program counter by 2
if !self.key.is_pressed(self.v[x as usize]) {
self.pc += 2;
}
@ -389,12 +385,16 @@ impl Chip8 {
fn add_vx_to_i(&mut self, x: u8) {
// 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) {
// 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) {
@ -402,11 +402,11 @@ impl Chip8 {
// take tens digit and place it at I + 1
// take ones digit and place it at I + 2
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 tens = iter.next().unwrap_or(0);
let hundreds = iter.next().unwrap_or(0);
let ones = digit.next().unwrap(); // Ther has to at least be a ones lol
let tens = digit.next().unwrap_or(0);
let hundreds = digit.next().unwrap_or(0);
self.memory[i] = hundreds 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) {
// copy values v0 -> Vx to memory starting at i
for n in 0..=(x as usize) {
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) {
// read what will be values of v0 -> vx from memory starting at i
let x = x as usize;
for n in 0..=x {
for n in 0..=(x as usize) {
self.v[n] = self.memory[self.i as usize + n];
}
}