Refactor several opcodes + remove opcode property
This commit is contained in:
parent
05f52dd397
commit
f4a8840b91
77
src/emu.rs
77
src/emu.rs
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue