diff --git a/programs/RPS.ch8 b/programs/RPS.ch8 new file mode 100644 index 0000000..3ea42d4 Binary files /dev/null and b/programs/RPS.ch8 differ diff --git a/programs/flightrunner.ch8 b/programs/flightrunner.ch8 new file mode 100644 index 0000000..b379353 Binary files /dev/null and b/programs/flightrunner.ch8 differ diff --git a/programs/octojam1title.ch8 b/programs/octojam1title.ch8 new file mode 100644 index 0000000..7e8dd9f Binary files /dev/null and b/programs/octojam1title.ch8 differ diff --git a/programs/outlaw.ch8 b/programs/outlaw.ch8 new file mode 100644 index 0000000..71eff28 Binary files /dev/null and b/programs/outlaw.ch8 differ diff --git a/src/chip8.rs b/src/chip8.rs index 22b77ba..45fb4f1 100644 --- a/src/chip8.rs +++ b/src/chip8.rs @@ -11,7 +11,7 @@ static MEMORY_LIMIT: i32 = 4096; static STACK_LIMIT: i32 = 16; static VARIABLE_REGISTER_COUNT: i32 = 16; static TIMER_TICK_RATE: u32 = 60; -static DESIRED_FPS: u32 = 165; +static DESIRED_FPS: u32 = 60; static CYCLES_PER_FRAME: u32 = 10; #[derive(Clone)] diff --git a/src/chip8/cpu.rs b/src/chip8/cpu.rs index ddf10e3..914717a 100644 --- a/src/chip8/cpu.rs +++ b/src/chip8/cpu.rs @@ -63,24 +63,24 @@ pub fn execute_instruction(state: &mut Chip8State, instruction: u16) { } } (0x8, _, _, 0x5) => { - let flag = state.r_v[x as usize] > state.r_v[y as usize]; + let flag = state.r_v[x as usize] >= state.r_v[y as usize]; state.r_v[x as usize] = state.r_v[x as usize].wrapping_sub(state.r_v[y as usize]); state.r_v[0xF] = if flag { 1 } else { 0 }; } (0x8, _, _, 0x6) => { let flag = (state.r_v[x as usize] & 0b00000001) == 1; - state.r_v[0xF] = if flag { 1 } else { 0 }; state.r_v[x as usize] = state.r_v[x as usize] / 2; + state.r_v[0xF] = if flag { 1 } else { 0 }; } (0x8, _, _, 0x7) => { - let flag = state.r_v[x as usize] < state.r_v[y as usize]; + let flag = state.r_v[x as usize] <= state.r_v[y as usize]; state.r_v[x as usize] = state.r_v[y as usize].wrapping_sub(state.r_v[x as usize]); state.r_v[0xF] = if flag { 1 } else { 0 }; } (0x8, _, _, 0xE) => { let flag = ((state.r_v[x as usize] & 0b10000000) >> 7) == 1; - state.r_v[0xF] = if flag { 1 } else { 0 }; state.r_v[x as usize] = state.r_v[x as usize].wrapping_mul(2); + state.r_v[0xF] = if flag { 1 } else { 0 }; } (0x9, _, _, _) => { if state.r_v[x as usize] != state.r_v[y as usize] { @@ -97,7 +97,7 @@ pub fn execute_instruction(state: &mut Chip8State, instruction: u16) { (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::draw(state, x, y, &bytes, n); + gpu::wrapping_draw(state, x, y, &bytes, n); } (0xE, _, _, 0xE) => { let key_index = state.r_v[x as usize]; diff --git a/src/chip8/debug.rs b/src/chip8/debug.rs index 22fc0f0..e31fab7 100644 --- a/src/chip8/debug.rs +++ b/src/chip8/debug.rs @@ -22,6 +22,6 @@ pub fn print_debug(state: &Chip8State, current_instruction: u16) { } println!("Current Instruction: {:04X}", current_instruction); println!("----------------"); - println!("Press Enter to continue..."); - let _ = io::stdin().read(&mut [0u8]).unwrap(); + // println!("Press Enter to continue..."); + // let _ = io::stdin().read(&mut [0u8]).unwrap(); } diff --git a/src/chip8/gpu.rs b/src/chip8/gpu.rs index c12f2e2..9e82f42 100644 --- a/src/chip8/gpu.rs +++ b/src/chip8/gpu.rs @@ -13,10 +13,12 @@ pub fn draw(state: &mut Chip8State, vx: u8, vy: u8, bytes_to_draw: &[u8], bytes_ 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]; @@ -36,6 +38,48 @@ pub fn draw(state: &mut Chip8State, vx: u8, vy: u8, bytes_to_draw: &[u8], bytes_ } } +pub fn wrapping_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]; + + 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 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 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; + + state.display[y as usize][x as usize] = new_pixel; + + if new_pixel != current_pixel { + state.r_v[0xF] = 1; + } + + bit_idx += 1; + } + + bytes_idx += 1; + } +} + pub fn load_builtin_sprites(state: &mut Chip8State) { memory::load_bytes( state,