diff --git a/src/emu.rs b/src/emu.rs index 771cec0..4c0a793 100644 --- a/src/emu.rs +++ b/src/emu.rs @@ -62,7 +62,7 @@ impl Chip8 { pub fn execute_cycle(&mut self) { self.opcode = self.get_opcode(); println!("{:#x}", self.opcode); - self.handle_opcode(); + self.execute_opcode(); self.delay.tick(); self.sound.tick(); @@ -98,7 +98,7 @@ impl Chip8 { ) } - fn handle_opcode(&mut self) { + fn execute_opcode(&mut self) { let (nib_1, nib_2, nib_3, nib_4) = Self::get_nibs(self.opcode); let nnn: u16 = self.opcode & 0x0FFF; @@ -236,7 +236,7 @@ impl Chip8 { fn add_vx_byte(&mut self, x: u8, kk: u8) { // calculate Vx + kk, then store it in Vx - self.v[x as usize] += kk; + self.v[x as usize] = self.v[x as usize].wrapping_add(kk); } fn ld_vx_vy(&mut self, x: u8, y: u8) { @@ -337,7 +337,7 @@ impl Chip8 { fn draw(&mut self, x: u8, y: u8, n: u8) { let i = self.i as usize; let draw_pos = (self.v[x as usize], self.v[y as usize]); - let sprite_data = &self.v[i..(i + n as usize)]; + let sprite_data = &self.memory[i..(i + n as usize)]; let collision = self.display.draw_sprite(draw_pos, sprite_data); @@ -971,6 +971,6 @@ mod test { #[test] #[ignore] fn opcode_set_i_to_hex_sprite_loc_works() { - todo!("Figure out how this instructin works") + todo!("Figure out how this instruction works") } } diff --git a/src/main.rs b/src/main.rs index dece6ba..34a68f8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,7 +24,7 @@ fn main() { let mut chip8: Chip8 = Default::default(); chip8 - .load_rom(Path::new("./games/test_opcode.ch8")) + .load_rom(Path::new("./games/ibm_logo.ch8")) .expect("Unable to load ROM"); event_loop.run(move |event, _, control_flow| { diff --git a/src/periph.rs b/src/periph.rs index ef41917..03e2d8f 100644 --- a/src/periph.rs +++ b/src/periph.rs @@ -1,34 +1,45 @@ #[derive(Copy, Clone)] pub struct Display { - pub buf: [u8; Self::SCREEN_SIZE], + pub buf: [u8; Self::WIDTH as usize * Self::HEIGHT as usize], } impl Display { - const SCREEN_SIZE: usize = 64 * 32; + const WIDTH: u8 = 64; + const HEIGHT: u8 = 32; pub fn clear(&mut self) { - self.buf = [0x0; Self::SCREEN_SIZE] + self.buf = [0x0; Self::WIDTH as usize * Self::HEIGHT as usize] } pub fn draw_sprite(&mut self, coords: (u8, u8), data: &[u8]) -> bool { - let x = coords.0; - let y = coords.1; + let x = coords.0 % Self::WIDTH; + let y = coords.1 % Self::HEIGHT; let mut set_vf = false; - // Each Byte is a row, and there are n bytes in data - // When writing, x should not change but y should be incremented - // after each iteration in the loop. - for (i, byte) in data.iter().enumerate() { + + // Each byte in data is a row, with the column being data.len() tall + // This means when writing this sprite, x should not change, but y + // should be incremented by 1 for every new byte we draw to the graphics buffer + for (y_offset, byte) in data.iter().enumerate() { // Access every bit of the byte - for j in 0..8 { - let bit = (byte >> j) & 0x01; - let display_index = j as usize + 8 * i as usize; + for x_bit_offset in 0..8 { + // The Coordinates of this bit in the gfx buffer + let gfx_x = x + x_bit_offset; + let gfx_y = y + y_offset as u8; - let old_value = self.buf[display_index]; - self.buf[display_index] ^= bit; + let bit = (byte >> x_bit_offset) & 0x01; - if old_value == 0x01 && self.buf[display_index] == 0x00 { + // Translate the gfx_x and gfx_y to an index in the 1D buffer + let gfx_i = (Self::WIDTH as usize * gfx_y as usize) + gfx_x as usize; + + if gfx_i >= self.buf.len() { + break; // Stop Drawing this spite and move on to the next + } + + if bit == 0x1 && self.buf[gfx_i] == 0x1 { set_vf = true; } + + self.buf[gfx_i] ^= bit; } } @@ -39,7 +50,7 @@ impl Display { impl Default for Display { fn default() -> Self { Display { - buf: [0x0; Self::SCREEN_SIZE], + buf: [0x0; Self::WIDTH as usize * Self::HEIGHT as usize], } } }