From ef0250b5198d9614789d290a6912384ac2d04e8b Mon Sep 17 00:00:00 2001 From: Trevor Merritt Date: Fri, 11 Oct 2024 13:12:13 -0400 Subject: [PATCH] improve core to handle looping of video --- gemma/src/chip8/instructions.rs | 33 +++++++++++++++++++++++---------- gemma/src/chip8/keypad.rs | 10 ++++------ gemma/src/chip8/stack.rs | 3 ++- gemma/src/chip8/video.rs | 9 +++++++-- gemma/src/constants.rs | 7 +++++++ 5 files changed, 43 insertions(+), 19 deletions(-) diff --git a/gemma/src/chip8/instructions.rs b/gemma/src/chip8/instructions.rs index b7840d7..1032ecd 100644 --- a/gemma/src/chip8/instructions.rs +++ b/gemma/src/chip8/instructions.rs @@ -654,6 +654,9 @@ impl Chip8CpuInstructions { // which is then ANDed with the value kk. // The results are stored in Vx. let new_value: u8 = random(); + let and_value: u8 = *byte; + let result = new_value & and_value; + println!("RANDOM: [{new_value:02x}] AND: [{and_value:02x} Result: [{result:02x}]"); input.registers.poke(*x as u8, new_value & *byte as u8) } Chip8CpuInstructions::DrawVxVyNibble(y, x, n) => { @@ -674,23 +677,23 @@ impl Chip8CpuInstructions { let x_offset = input.registers.peek(*x as u8); let y_offset = input.registers.peek(*y as u8); - println!("X_OFFSET = {x_offset} / y_offset = {y_offset}"); + debug!("X_OFFSET = {x_offset} / y_offset = {y_offset}"); let target_memory_offset = x_offset as u16 * 64 + y_offset as u16; - println!("CHIP8CPUINSTRUCTION:DRAWVXNIBBLE -> STARTING AT {source_memory_offset} WRITING TO {target_memory_offset}"); + debug!("CHIP8CPUINSTRUCTION:DRAWVXNIBBLE -> STARTING AT {source_memory_offset} WRITING TO {target_memory_offset}"); let num_bytes_to_read = *n; - println!("CHIP8CPUINSTRUCTION:DRAWVXNIBBLE -> PREPARING TO READ {num_bytes_to_read} BYTES FROM MEMORY TO VIDEO"); + debug!("CHIP8CPUINSTRUCTION:DRAWVXNIBBLE -> PREPARING TO READ {num_bytes_to_read} BYTES FROM MEMORY TO VIDEO"); for byte_index in 0..num_bytes_to_read { let current_byte = input.memory.peek(byte_index as u16 + source_memory_offset); - println!("CHIP8CPUINSTRUCTION:DRAWVXNIBBLE -> READ BYTE [0x{byte_index:2x}]\t{current_byte:02x}\t{current_byte:08b}"); + debug!("CHIP8CPUINSTRUCTION:DRAWVXNIBBLE -> READ BYTE [0x{byte_index:2x}]\t{current_byte:02x}\t{current_byte:08b}"); for bit_index in 0..8 { - let data_offset = ((x_offset as u16 + byte_index as u16) * 64) + (y_offset + bit_index) as u16; + let data_offset = ((x_offset as u16 + byte_index as u16) * 64) + (y_offset as u16 + bit_index as u16) as u16; let current_bit = (current_byte.shr(7 - bit_index) & 0x1u8) == 0x1u8; input.video_memory.poke(data_offset, current_bit); } } - println!("PPOOSSTT -> CHIP8CPUINSTRUCTION:DRAWVXNIBBLE -> {}", input.video_memory.format_as_string()); + debug!("PPOOSSTT -> CHIP8CPUINSTRUCTION:DRAWVXNIBBLE -> {}", input.video_memory.format_as_string()); let mut did_change: bool = false; @@ -770,8 +773,9 @@ impl Chip8CpuInstructions { // to the value of Vx. See section 2.4, Display, for more information on // the Chip-8 hexadecimal font. - let to_offset = input.registers.peek(*x as u8) - 1; - let real_offset = to_offset as u16 * 5; + let x_value: u8 = input.registers.peek(*x); + + let real_offset = x_value as u16 * 5; input.registers.poke_i(real_offset as u16); } Chip8CpuInstructions::LdBVx(x) => { @@ -817,11 +821,11 @@ impl Chip8CpuInstructions { let offset = input.registers.peek_i(); debug!("STARTING TO READ AT {offset:03x}"); let num_loops = x + 1; - println!("WILL READ {num_loops:x} BYTES"); + debug!("WILL READ {num_loops:x} BYTES"); for index in 0..num_loops { let src_value = input.memory.peek(index as u16 + offset); input.registers.poke(index as u8, src_value); - println!("POKING Register 0x{index:02x} with 0x{src_value:04x} using offset 0x{offset:04x}"); + debug!("POKING Register 0x{index:02x} with 0x{src_value:04x} using offset 0x{offset:04x}"); } input.registers.poke_i(offset + 1); } @@ -1553,4 +1557,13 @@ mod test { assert_eq!(x.registers.peek(0x01), 0b01000000); assert_eq!(x.registers.peek(0x0f), 0x01); } + + #[test] + fn random_produces_different_numbers() { + let mut x = Chip8Computer::new(); + x.registers.poke(0x01, 0x00); + let first_number = Chip8CpuInstructions::RndVxByte(0x01, 0xff).execute(&mut x).registers.peek(0x01); + let second_number = Chip8CpuInstructions::RndVxByte(0x01, 0xff).execute(&mut x).registers.peek(0x01); + assert_ne!(first_number, second_number); + } } diff --git a/gemma/src/chip8/keypad.rs b/gemma/src/chip8/keypad.rs index 16b7da8..884f1e5 100644 --- a/gemma/src/chip8/keypad.rs +++ b/gemma/src/chip8/keypad.rs @@ -1,3 +1,5 @@ +use crate::constants::CHIP8_KEYBOARD; + #[derive(Clone, Copy)] pub struct Keypad { keys: [bool; 0x10], @@ -7,13 +9,9 @@ impl Keypad { pub fn format_as_string(&self) -> String { let mut return_value = String::new(); // draw a 4x4 grid showing the keys with * filling the cells that are depressed - let keys = [ - [0x1, 0x2, 0x3, 0xc],[0x4, 0x5, 0x6, 0xd],[0x7, 0x8, 0x9, 0xe],[0xa, 0x0, 0xb, 0xf] - ]; - - for row in keys.iter() { + for row in CHIP8_KEYBOARD.iter() { for (index, key) in row.iter().enumerate() { - let is_lit = if self.keys[*key] { "*".to_string() } else { char::from_digit(*key as u32, 16).unwrap_or(' ').to_string() }; + let is_lit = if self.keys[*key as usize] { "*".to_string() } else { char::from_digit(*key as u32, 16).unwrap_or(' ').to_string() }; match index { 3 => { // last in col diff --git a/gemma/src/chip8/stack.rs b/gemma/src/chip8/stack.rs index 1be7eaf..3ef4331 100644 --- a/gemma/src/chip8/stack.rs +++ b/gemma/src/chip8/stack.rs @@ -14,7 +14,8 @@ impl Default for Chip8Stack { impl Chip8Stack { pub fn push(&mut self, new_value: &u16) { if self.depth() == 16 { - panic!("Stack Overflow"); + println!("Deep deep stack?"); + // panic!("Stack Overflow"); } self.items.push(*new_value ); } diff --git a/gemma/src/chip8/video.rs b/gemma/src/chip8/video.rs index f045baf..09b9e80 100644 --- a/gemma/src/chip8/video.rs +++ b/gemma/src/chip8/video.rs @@ -31,14 +31,19 @@ impl Chip8Video { pub fn poke(&mut self, address: u16, new_value: bool) -> Self { trace!("OFFSET: {address} - POKING {new_value}"); - let old_value = self.memory[address as usize]; + let effective_address = if address > 2048 { + address - 2048 + } else { + address + }; + let old_value = self.memory[effective_address as usize]; if old_value != new_value { trace!("**VIDEO** TOGGLING"); self.has_frame_changed = true; } else { trace!("NOT TOGGLING"); } - self.memory[address as usize] = new_value; + self.memory[effective_address as usize] = new_value; self.to_owned() } diff --git a/gemma/src/constants.rs b/gemma/src/constants.rs index a90ba74..b728112 100644 --- a/gemma/src/constants.rs +++ b/gemma/src/constants.rs @@ -4,3 +4,10 @@ pub const CHIP8_VIDEO_WIDTH: i32 = 64i32; pub const CHIP8_VIDEO_HEIGHT: i32 = 32i32; pub const CHIP8_VIDEO_MEMORY: usize = (CHIP8_VIDEO_HEIGHT * CHIP8_VIDEO_WIDTH) as usize; pub const CHIP8_ROM_SIZE: usize = 512; + +pub const CHIP8_KEYBOARD: [[u8; 4]; 4] = [ + [0x01, 0x02, 0x03, 0x0C], + [0x04, 0x05, 0x06, 0x0D], + [0x07, 0x08, 0x09, 0x0E], + [0x0A, 0x00, 0x0B, 0x0F] +]; \ No newline at end of file