From 4fc0bfd3d8c5741686dec421a44761658c7ccc86 Mon Sep 17 00:00:00 2001 From: Trevor Merritt Date: Thu, 10 Oct 2024 16:12:48 -0400 Subject: [PATCH] now passes the flags test rom --- gemma/src/chip8/instructions.rs | 90 +++++++++++++++++---------------- gemma/tests/computer_tests.rs | 1 - 2 files changed, 47 insertions(+), 44 deletions(-) diff --git a/gemma/src/chip8/instructions.rs b/gemma/src/chip8/instructions.rs index 825e607..7280fd7 100644 --- a/gemma/src/chip8/instructions.rs +++ b/gemma/src/chip8/instructions.rs @@ -141,25 +141,25 @@ impl Chip8CpuInstructions { 0x4000u16 | (*vx_register as u16) << 8 | *byte as u16 } Chip8CpuInstructions::SeVxVy(x_register, y_register) => { - 0x5000u16 | (*x_register as u16) << 8 | (*y_register as u16 )<< 4 + 0x5000u16 | (*x_register as u16) << 8 | (*y_register as u16) << 4 } Chip8CpuInstructions::LdVxByte(x_register, byte) => { - 0x6000u16 | (*x_register as u16) << 8 | ( *byte as u16) + 0x6000u16 | (*x_register as u16) << 8 | (*byte as u16) } Chip8CpuInstructions::AddVxByte(x_register, byte) => { 0x7000u16 | (*x_register as u16) << 8 | *byte as u16 } Chip8CpuInstructions::LdVxVy(x_register, y_register) => { - 0x8000u16 | (*x_register as u16) << 8 | (*y_register as u16 )<< 4 + 0x8000u16 | (*x_register as u16) << 8 | (*y_register as u16) << 4 } Chip8CpuInstructions::OrVxVy(x_register, y_register) => { - 0x8001u16 | (*x_register as u16 )<< 8 | (*y_register as u16) << 4 + 0x8001u16 | (*x_register as u16) << 8 | (*y_register as u16) << 4 } Chip8CpuInstructions::AndVxVy(x_register, y_register) => { 0x8002u16 | (*x_register as u16) << 8 | (*y_register as u16) << 4 } Chip8CpuInstructions::XorVxVy(x_register, y_register) => { - 0x8003u16 | (*x_register as u16) << 8 | (*y_register as u16) << 4 + 0x8003u16 | (*x_register as u16) << 8 | (*y_register as u16) << 4 } Chip8CpuInstructions::AddVxVy(x_register, y_register) => { 0x8004u16 | (*x_register as u16) << 8 | (*y_register as u16) << 4 @@ -568,20 +568,16 @@ impl Chip8CpuInstructions { // Set Vx = Vx SHR 1. // SHIFT 1 Bit ----> // If the least-significant bit of Vx is 1, then VF is set to 1, otherwise 0. Then Vx is divided by 2. - let initial_value = input.registers.peek(*x as u8); + let initial_value = input.registers.peek(*x); // overflow check - + let rotated = initial_value >> 1; + input.registers.poke(*x as u8, rotated); if initial_value.bitand(0b1) == 1 { input.registers.poke(0x0f, 0x01); } else { input.registers.poke(0x0f, 0x00); } - - let rotated = initial_value >> 1; - println!("[{initial_value:80b}] / [{rotated:80b}]"); - - input.registers.poke(*x as u8, initial_value.shr(1)); } Chip8CpuInstructions::SubnVxVy(x, y) => { // 8xy7 - SUBN Vx, Vy @@ -592,15 +588,18 @@ impl Chip8CpuInstructions { let x_register = input.registers.peek(*x as u8); let mut value_to_poke = 0; - let new_value = if y_register <= x_register { + let new_value = if y_register < x_register { value_to_poke = (y_register as u16 + 256) - x_register as u16; - 1 } else { - value_to_poke = (y_register - x_register) as u16; 0 + } else { + value_to_poke = (y_register - x_register) as u16; + 1 }; + println!("SUB CARRY -> REGISTER 1 = [0x{x:02x}] / [{x_register}] REGISTER 2 = [0x{y:02x}] / [{y_register}] SUB = {value_to_poke} CARRY = {new_value}"); + + input.registers.poke(*x, value_to_poke as u8); input.registers.poke(0xf, new_value); - input.registers.poke(*x as u8, value_to_poke as u8); } Chip8CpuInstructions::ShlVxVy(x, _) => { @@ -608,14 +607,16 @@ impl Chip8CpuInstructions { // Set Vx = Vx SHL 1. // // If the most-significant bit of Vx is 1, then VF is set to 1, otherwise to 0. Then Vx is multiplied by 2. - let initial_value = input.registers.peek(*x as u8); - let rotated = initial_value.shl(1); - if 0b10000000 & initial_value == 0b10000000 { + let initial_value = input.registers.peek(*x); + + // overflow check + let rotated = initial_value << 1; + input.registers.poke(*x as u8, rotated); + if initial_value.bitand(0b10000000) == 0b10000000 { input.registers.poke(0x0f, 0x01); } else { input.registers.poke(0x0f, 0x00); } - input.registers.poke(*x as u8,rotated); } Chip8CpuInstructions::SneVxVy(vx_register, vy_register) => { // 9xy0 - SNE Vx, Vy @@ -655,7 +656,7 @@ impl Chip8CpuInstructions { let new_value: u8 = random(); input.registers.poke(*x as u8, new_value & *byte as u8) } - Chip8CpuInstructions::DrawVxVyNibble(y,x, n) => { + Chip8CpuInstructions::DrawVxVyNibble(y, x, n) => { // Display n-byte sprite starting at memory location I at (Vx, Vy), set VF = collision. // The interpreter reads n bytes from memory, starting at the address stored in I. @@ -683,7 +684,7 @@ impl Chip8CpuInstructions { 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}"); 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 + bit_index) as u16; let current_bit = (current_byte.shr(7 - bit_index) & 0x1u8) == 0x1u8; input.video_memory.poke(data_offset, current_bit); } @@ -822,7 +823,7 @@ impl Chip8CpuInstructions { input.registers.poke(index as u8, src_value); println!("POKING Register 0x{index:02x} with 0x{src_value:04x} using offset 0x{offset:04x}"); } - input.registers.poke_i(offset + 1); + input.registers.poke_i(offset + 1); } Chip8CpuInstructions::XXXXERRORINSTRUCTION => {} }; @@ -1274,7 +1275,7 @@ mod test { assert_eq!(x.registers.peek(0xf), 0x0); let mut x = Chip8Computer::new(); - x.registers.poke(0x1, 0b10101010); + x.registers.poke(0x1, 0b10101010); Chip8CpuInstructions::ShlVxVy(0x1, 0x1).execute(&mut x); assert_eq!(x.registers.peek(0x1), 0b01010100); assert_eq!(x.registers.peek(0xf), 0x1); @@ -1371,8 +1372,7 @@ mod test { for (idx, value) in to_load.iter().enumerate() { assert_eq!(x.registers.peek(idx as u8), *value); } - - } + } #[test] fn Sknkpvx_test() { @@ -1529,24 +1529,28 @@ mod test { // If the least-significant bit of Vx is 1, then VF is set to 1, // otherwise 0. Then Vx is divided by 2. let mut x = Chip8Computer::new(); - // 0b10000000 -> 0b01000000 - let start_value = 0b10000000; - let end_value = 0b01000000; - x.registers.poke(0x01, start_value); - Chip8CpuInstructions::ShrVxVy(0x01, 0x00).execute(&mut x); - assert_eq!(x.registers.peek(0x01), end_value); - assert_eq!(x.registers.peek(0x0f), 0); + // 0b10101010 -> 0b01010101 + x.registers.poke(0x01, 0b10101010); + x.registers.poke(0x0f, 0x0); - // 0b00000001 -> 0b00000000 - let start_value = 0b00000001; - let end_value = 0b00000000; - let mut x = Chip8Computer::new(); - let start_value = 1; - x.registers.poke(0x01, start_value); - Chip8CpuInstructions::ShrVxVy(0x01, 0x00).execute(&mut x); - assert_eq!(x.registers.peek(0x01), end_value); + Chip8CpuInstructions::ShlVxVy(0x01, 0x00).execute(&mut x); + assert_eq!(x.registers.peek(0x01), 0b01010100); assert_eq!(x.registers.peek(0x0f), 1); - let end_value = start_value / 2; - assert_eq!(end_value, 0); + + Chip8CpuInstructions::ShlVxVy(0x01, 0x00).execute(&mut x); + assert_eq!(x.registers.peek(0x01), 0b10101000); + assert_eq!(x.registers.peek(0x0f), 0x00); + + Chip8CpuInstructions::ShlVxVy(0x01, 0x00).execute(&mut x); + assert_eq!(x.registers.peek(0x01), 0b01010000); + assert_eq!(x.registers.peek(0x0f), 0x01); + + Chip8CpuInstructions::ShlVxVy(0x01, 0x00).execute(&mut x); + assert_eq!(x.registers.peek(0x01), 0b10100000); + assert_eq!(x.registers.peek(0x0f), 0x00); + + Chip8CpuInstructions::ShlVxVy(0x01, 0x00).execute(&mut x); + assert_eq!(x.registers.peek(0x01), 0b01000000); + assert_eq!(x.registers.peek(0x0f), 0x01); } } diff --git a/gemma/tests/computer_tests.rs b/gemma/tests/computer_tests.rs index 91d36db..73c6dbe 100644 --- a/gemma/tests/computer_tests.rs +++ b/gemma/tests/computer_tests.rs @@ -6,5 +6,4 @@ fn smoke() { assert!(true) } #[test] fn test_rom_1_works() { let mut x = Chip8Computer::new(); - }