a whole lotta quirk fixes
This commit is contained in:
17
src/chip8.rs
17
src/chip8.rs
@@ -38,7 +38,16 @@ struct Chip8State {
|
||||
input: [bool; 16],
|
||||
}
|
||||
|
||||
pub fn run<S: AsRef<str>>(chip8_executable_filepath: S, debug_mode: bool) {
|
||||
pub struct Chip8Quirks {
|
||||
pub vf_reset: bool,
|
||||
pub memory: bool,
|
||||
pub display_wait: bool, // TODO: Looks to be working, but not in quirks test file
|
||||
pub clipping: bool, // TODO: Looks to be working, but not in quirks test file
|
||||
pub shifting: bool,
|
||||
pub jumping: bool,
|
||||
}
|
||||
|
||||
pub fn run<S: AsRef<str>>(chip8_executable_filepath: S, quirks: &Chip8Quirks, debug_mode: bool) {
|
||||
let mut state = Chip8State {
|
||||
eti_600_flag: false,
|
||||
mem: [0; 4096],
|
||||
@@ -63,10 +72,10 @@ pub fn run<S: AsRef<str>>(chip8_executable_filepath: S, debug_mode: bool) {
|
||||
let _ = memory::load_file_to_memory(&mut state, chip8_executable_filepath.as_ref());
|
||||
|
||||
// Run Program
|
||||
start(&mut state, debug_mode);
|
||||
start(&mut state, &quirks, debug_mode);
|
||||
}
|
||||
|
||||
fn start(state: &mut Chip8State, debug_mode: bool) {
|
||||
fn start(state: &mut Chip8State, quirks: &Chip8Quirks, debug_mode: bool) {
|
||||
// TODO rip out as much RL stuff from here and put into renderer
|
||||
// Init Rendering Pipeline
|
||||
let (mut rl, thread) = raylib::init()
|
||||
@@ -124,7 +133,7 @@ fn start(state: &mut Chip8State, debug_mode: bool) {
|
||||
debug::print_debug(state, instruction);
|
||||
}
|
||||
|
||||
cpu::execute_instruction(state, instruction);
|
||||
cpu::execute_instruction(state, instruction, &quirks);
|
||||
}
|
||||
|
||||
// move to timers.rs
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use crate::chip8::gpu;
|
||||
use crate::chip8::{Chip8Quirks, gpu};
|
||||
|
||||
use super::Chip8State;
|
||||
use super::memory::read_n_bytes;
|
||||
|
||||
// Need to come back and add good comments for each of the match patterns
|
||||
pub fn execute_instruction(state: &mut Chip8State, instruction: u16) {
|
||||
pub fn execute_instruction(state: &mut Chip8State, instruction: u16, quirks: &Chip8Quirks) {
|
||||
let c = ((instruction & 0xF000) >> 12) as u8;
|
||||
let x = ((instruction & 0x0F00) >> 8) as u8;
|
||||
let y = ((instruction & 0x00F0) >> 4) as u8;
|
||||
@@ -49,9 +49,24 @@ pub fn execute_instruction(state: &mut Chip8State, instruction: u16) {
|
||||
(0x6, _, _, _) => state.r_v[x as usize] = kk,
|
||||
(0x7, _, _, _) => state.r_v[x as usize] = state.r_v[x as usize].wrapping_add(kk),
|
||||
(0x8, _, _, 0x0) => state.r_v[x as usize] = state.r_v[y as usize],
|
||||
(0x8, _, _, 0x1) => state.r_v[x as usize] |= state.r_v[y as usize],
|
||||
(0x8, _, _, 0x2) => state.r_v[x as usize] &= state.r_v[y as usize],
|
||||
(0x8, _, _, 0x3) => state.r_v[x as usize] ^= state.r_v[y as usize],
|
||||
(0x8, _, _, 0x1) => {
|
||||
state.r_v[x as usize] |= state.r_v[y as usize];
|
||||
if quirks.vf_reset {
|
||||
state.r_v[0xF] = 0;
|
||||
}
|
||||
}
|
||||
(0x8, _, _, 0x2) => {
|
||||
state.r_v[x as usize] &= state.r_v[y as usize];
|
||||
if quirks.vf_reset {
|
||||
state.r_v[0xF] = 0;
|
||||
}
|
||||
}
|
||||
(0x8, _, _, 0x3) => {
|
||||
state.r_v[x as usize] ^= state.r_v[y as usize];
|
||||
if quirks.vf_reset {
|
||||
state.r_v[0xF] = 0;
|
||||
}
|
||||
}
|
||||
(0x8, _, _, 0x4) => {
|
||||
let val: u16 = state.r_v[x as usize] as u16 + state.r_v[y as usize] as u16;
|
||||
if val > u8::MAX as u16 {
|
||||
@@ -68,6 +83,9 @@ pub fn execute_instruction(state: &mut Chip8State, instruction: u16) {
|
||||
state.r_v[0xF] = if flag { 1 } else { 0 };
|
||||
}
|
||||
(0x8, _, _, 0x6) => {
|
||||
if !quirks.shifting {
|
||||
state.r_v[x as usize] = state.r_v[y as usize];
|
||||
}
|
||||
let flag = (state.r_v[x as usize] & 0b00000001) == 1;
|
||||
state.r_v[x as usize] = state.r_v[x as usize] / 2;
|
||||
state.r_v[0xF] = if flag { 1 } else { 0 };
|
||||
@@ -78,6 +96,9 @@ pub fn execute_instruction(state: &mut Chip8State, instruction: u16) {
|
||||
state.r_v[0xF] = if flag { 1 } else { 0 };
|
||||
}
|
||||
(0x8, _, _, 0xE) => {
|
||||
if !quirks.shifting {
|
||||
state.r_v[x as usize] = state.r_v[y as usize];
|
||||
}
|
||||
let flag = ((state.r_v[x as usize] & 0b10000000) >> 7) == 1;
|
||||
state.r_v[x as usize] = state.r_v[x as usize].wrapping_mul(2);
|
||||
state.r_v[0xF] = if flag { 1 } else { 0 };
|
||||
@@ -88,16 +109,25 @@ pub fn execute_instruction(state: &mut Chip8State, instruction: u16) {
|
||||
}
|
||||
}
|
||||
(0xA, _, _, _) => state.r_i = nnn,
|
||||
(0xB, _, _, _) => state.r_pc = nnn + state.r_v[0] as u16,
|
||||
(0xB, _, _, _) => {
|
||||
if quirks.jumping {
|
||||
state.r_pc = nnn + state.r_v[x as usize] as u16;
|
||||
} else {
|
||||
state.r_pc = nnn + state.r_v[0] as u16;
|
||||
}
|
||||
}
|
||||
(0xC, _, _, _) => {
|
||||
let rng = rand::random_range(0..256) as u8;
|
||||
let result = rng & kk;
|
||||
state.r_v[x as usize] = result;
|
||||
}
|
||||
(0xD, _, _, _) => {
|
||||
state.r_v[0xF] = 0;
|
||||
let bytes = read_n_bytes(&state.mem, state.mem.len(), state.r_i as usize, n as usize);
|
||||
gpu::wrapping_draw(state, x, y, &bytes, n);
|
||||
if quirks.clipping {
|
||||
gpu::clipping_draw(state, x, y, &bytes, n);
|
||||
} else {
|
||||
gpu::draw(state, x, y, &bytes, n);
|
||||
}
|
||||
}
|
||||
(0xE, _, _, 0xE) => {
|
||||
let key_index = state.r_v[x as usize];
|
||||
@@ -153,6 +183,9 @@ pub fn execute_instruction(state: &mut Chip8State, instruction: u16) {
|
||||
|
||||
i = i + 1;
|
||||
}
|
||||
if quirks.memory {
|
||||
state.r_i += i as u16;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@@ -9,68 +9,72 @@ pub static SPRITE_WIDTH: u8 = 8;
|
||||
// I probably don't need state here
|
||||
// refactor to just receive a mutatable buffer
|
||||
pub fn draw(state: &mut Chip8State, vx: u8, vy: u8, bytes_to_draw: &[u8], bytes_to_draw_len: u8) {
|
||||
state.r_v[0xF] = 0;
|
||||
let start_x = state.r_v[vx as usize] % CHIP8_DISPLAY_WIDTH as u8;
|
||||
let start_y = state.r_v[vy as usize] % CHIP8_DISPLAY_HEIGHT as u8;
|
||||
|
||||
let mut bytes_idx = 0;
|
||||
let start_x = state.r_v[vx as usize];
|
||||
let start_y = state.r_v[vy as usize];
|
||||
for y in start_y..start_y + bytes_to_draw_len {
|
||||
println!("{}", bytes_idx);
|
||||
if (y as i32) < CHIP8_DISPLAY_HEIGHT {
|
||||
// 8 is the hardcoded sprite width, has to atleast have 1 8 bit value to display
|
||||
let mut bit_idx = 0;
|
||||
for x in start_x..start_x + SPRITE_WIDTH {
|
||||
println!("(X,Y): ({},{})", x, y);
|
||||
if (x as i32) < CHIP8_DISPLAY_WIDTH {
|
||||
let sprite_pixel = ((bytes_to_draw[bytes_idx] >> (7 - bit_idx)) & 1) == 1;
|
||||
let current_pixel = state.display[y as usize][x as usize];
|
||||
let new_pixel = current_pixel ^ sprite_pixel;
|
||||
while bytes_idx < bytes_to_draw_len {
|
||||
// TODO: this should be a u8 for safety
|
||||
let y: u8 = start_y.wrapping_add(bytes_idx) % CHIP8_DISPLAY_HEIGHT as u8;
|
||||
|
||||
state.display[y as usize][x as usize] = new_pixel;
|
||||
let mut bit_idx = 0;
|
||||
while bit_idx < SPRITE_WIDTH {
|
||||
let x: u8 = start_x.wrapping_add(bit_idx) % CHIP8_DISPLAY_WIDTH as u8;
|
||||
|
||||
if new_pixel != current_pixel {
|
||||
state.r_v[0xF] = 1;
|
||||
}
|
||||
let sprite_pixel = ((bytes_to_draw[bytes_idx as usize] >> (7 - bit_idx)) & 1) == 1;
|
||||
if sprite_pixel {
|
||||
let current_pixel = state.display[y as usize][x as usize];
|
||||
|
||||
bit_idx += 1;
|
||||
if current_pixel {
|
||||
state.r_v[0xF] = 1;
|
||||
}
|
||||
|
||||
state.display[y as usize][x as usize] ^= true;
|
||||
}
|
||||
|
||||
bit_idx += 1;
|
||||
}
|
||||
|
||||
bytes_idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wrapping_draw(
|
||||
pub fn clipping_draw(
|
||||
state: &mut Chip8State,
|
||||
vx: u8,
|
||||
vy: u8,
|
||||
bytes_to_draw: &[u8],
|
||||
bytes_to_draw_len: u8,
|
||||
) {
|
||||
let mut bytes_idx = 0;
|
||||
let start_x = state.r_v[vx as usize];
|
||||
let start_y = state.r_v[vy as usize];
|
||||
state.r_v[0xF] = 0;
|
||||
let start_x = state.r_v[vx as usize] % CHIP8_DISPLAY_WIDTH as u8;
|
||||
let start_y = state.r_v[vy as usize] % CHIP8_DISPLAY_HEIGHT as u8;
|
||||
|
||||
let mut bytes_idx = 0;
|
||||
while bytes_idx < bytes_to_draw_len {
|
||||
let mut y = start_y.wrapping_add(bytes_idx);
|
||||
if y as i32 >= CHIP8_DISPLAY_HEIGHT {
|
||||
y = (y - CHIP8_DISPLAY_HEIGHT as u8) % CHIP8_DISPLAY_HEIGHT as u8;
|
||||
let y: u16 = (start_y + bytes_idx) as u16;
|
||||
// TODO: general reminder to cleanup type casts to be consistent
|
||||
if y >= CHIP8_DISPLAY_HEIGHT as u16 {
|
||||
break;
|
||||
}
|
||||
|
||||
let mut bit_idx = 0;
|
||||
|
||||
while bit_idx < SPRITE_WIDTH {
|
||||
let mut x = start_x.wrapping_add(bit_idx);
|
||||
if x as i32 >= CHIP8_DISPLAY_WIDTH {
|
||||
x = (x - CHIP8_DISPLAY_WIDTH as u8) % CHIP8_DISPLAY_WIDTH as u8;
|
||||
let x = (start_x + bit_idx) as u16;
|
||||
if x >= CHIP8_DISPLAY_WIDTH as u16 {
|
||||
break;
|
||||
}
|
||||
|
||||
let sprite_pixel = ((bytes_to_draw[bytes_idx as usize] >> (7 - bit_idx)) & 1) == 1;
|
||||
let current_pixel = state.display[y as usize][x as usize];
|
||||
let new_pixel = current_pixel ^ sprite_pixel;
|
||||
if sprite_pixel {
|
||||
let current_pixel = state.display[y as usize][x as usize];
|
||||
|
||||
state.display[y as usize][x as usize] = new_pixel;
|
||||
if current_pixel {
|
||||
state.r_v[0xF] = 1;
|
||||
}
|
||||
|
||||
if new_pixel != current_pixel {
|
||||
state.r_v[0xF] = 1;
|
||||
state.display[y as usize][x as usize] ^= true;
|
||||
}
|
||||
|
||||
bit_idx += 1;
|
||||
|
||||
18
src/main.rs
18
src/main.rs
@@ -11,17 +11,29 @@ struct Args {
|
||||
/// Set path for chip8 binary file to run
|
||||
#[arg(short, long)]
|
||||
file: Option<String>,
|
||||
#[arg(short = 'q', long = "quirks", value_delimiter = ',')]
|
||||
quirks: Vec<String>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
// TODO: should define my raylib/sound/etc handles here eventually and pass them down
|
||||
let quirks = chip8::Chip8Quirks {
|
||||
vf_reset: args.quirks.contains(&String::from("vfreset"))
|
||||
|| args.quirks.contains(&String::from("chip8")),
|
||||
memory: args.quirks.contains(&String::from("memory"))
|
||||
|| args.quirks.contains(&String::from("chip8")),
|
||||
display_wait: args.quirks.contains(&String::from("displaywait")),
|
||||
clipping: args.quirks.contains(&String::from("clipping"))
|
||||
|| args.quirks.contains(&String::from("chip8")),
|
||||
shifting: args.quirks.contains(&String::from("shifting")),
|
||||
jumping: args.quirks.contains(&String::from("jumping")),
|
||||
};
|
||||
|
||||
if let Some(filepath) = args.file {
|
||||
if args.debug {
|
||||
chip8::run(filepath, true);
|
||||
chip8::run(filepath, &quirks, true);
|
||||
} else {
|
||||
chip8::run(filepath, false);
|
||||
chip8::run(filepath, &quirks, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user