Implement working Dxyn Opcode

This commit is contained in:
Rekai Musuka 2020-07-13 18:08:15 -05:00
parent 2e2497206f
commit 05f52dd397
3 changed files with 33 additions and 22 deletions

View File

@ -62,7 +62,7 @@ impl Chip8 {
pub fn execute_cycle(&mut self) { pub fn execute_cycle(&mut self) {
self.opcode = self.get_opcode(); self.opcode = self.get_opcode();
println!("{:#x}", self.opcode); println!("{:#x}", self.opcode);
self.handle_opcode(); self.execute_opcode();
self.delay.tick(); self.delay.tick();
self.sound.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 (nib_1, nib_2, nib_3, nib_4) = Self::get_nibs(self.opcode);
let nnn: u16 = self.opcode & 0x0FFF; let nnn: u16 = self.opcode & 0x0FFF;
@ -236,7 +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
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) { 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) { fn draw(&mut self, x: u8, y: u8, n: u8) {
let i = self.i as usize; let i = self.i as usize;
let draw_pos = (self.v[x as usize], self.v[y 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); let collision = self.display.draw_sprite(draw_pos, sprite_data);
@ -971,6 +971,6 @@ mod test {
#[test] #[test]
#[ignore] #[ignore]
fn opcode_set_i_to_hex_sprite_loc_works() { fn opcode_set_i_to_hex_sprite_loc_works() {
todo!("Figure out how this instructin works") todo!("Figure out how this instruction works")
} }
} }

View File

@ -24,7 +24,7 @@ fn main() {
let mut chip8: Chip8 = Default::default(); let mut chip8: Chip8 = Default::default();
chip8 chip8
.load_rom(Path::new("./games/test_opcode.ch8")) .load_rom(Path::new("./games/ibm_logo.ch8"))
.expect("Unable to load ROM"); .expect("Unable to load ROM");
event_loop.run(move |event, _, control_flow| { event_loop.run(move |event, _, control_flow| {

View File

@ -1,34 +1,45 @@
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct Display { pub struct Display {
pub buf: [u8; Self::SCREEN_SIZE], pub buf: [u8; Self::WIDTH as usize * Self::HEIGHT as usize],
} }
impl Display { impl Display {
const SCREEN_SIZE: usize = 64 * 32; const WIDTH: u8 = 64;
const HEIGHT: u8 = 32;
pub fn clear(&mut self) { 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 { pub fn draw_sprite(&mut self, coords: (u8, u8), data: &[u8]) -> bool {
let x = coords.0; let x = coords.0 % Self::WIDTH;
let y = coords.1; let y = coords.1 % Self::HEIGHT;
let mut set_vf = false; 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 // Each byte in data is a row, with the column being data.len() tall
// after each iteration in the loop. // This means when writing this sprite, x should not change, but y
for (i, byte) in data.iter().enumerate() { // 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 // Access every bit of the byte
for j in 0..8 { for x_bit_offset in 0..8 {
let bit = (byte >> j) & 0x01; // The Coordinates of this bit in the gfx buffer
let display_index = j as usize + 8 * i as usize; let gfx_x = x + x_bit_offset;
let gfx_y = y + y_offset as u8;
let old_value = self.buf[display_index]; let bit = (byte >> x_bit_offset) & 0x01;
self.buf[display_index] ^= bit;
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; set_vf = true;
} }
self.buf[gfx_i] ^= bit;
} }
} }
@ -39,7 +50,7 @@ impl Display {
impl Default for Display { impl Default for Display {
fn default() -> Self { fn default() -> Self {
Display { Display {
buf: [0x0; Self::SCREEN_SIZE], buf: [0x0; Self::WIDTH as usize * Self::HEIGHT as usize],
} }
} }
} }