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) {
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")
}
}

View File

@ -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| {

View File

@ -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],
}
}
}