now passes the flags test rom
This commit is contained in:
parent
e176ee5638
commit
4fc0bfd3d8
@ -141,25 +141,25 @@ impl Chip8CpuInstructions {
|
|||||||
0x4000u16 | (*vx_register as u16) << 8 | *byte as u16
|
0x4000u16 | (*vx_register as u16) << 8 | *byte as u16
|
||||||
}
|
}
|
||||||
Chip8CpuInstructions::SeVxVy(x_register, y_register) => {
|
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) => {
|
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) => {
|
Chip8CpuInstructions::AddVxByte(x_register, byte) => {
|
||||||
0x7000u16 | (*x_register as u16) << 8 | *byte as u16
|
0x7000u16 | (*x_register as u16) << 8 | *byte as u16
|
||||||
}
|
}
|
||||||
Chip8CpuInstructions::LdVxVy(x_register, y_register) => {
|
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) => {
|
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) => {
|
Chip8CpuInstructions::AndVxVy(x_register, y_register) => {
|
||||||
0x8002u16 | (*x_register as u16) << 8 | (*y_register as u16) << 4
|
0x8002u16 | (*x_register as u16) << 8 | (*y_register as u16) << 4
|
||||||
}
|
}
|
||||||
Chip8CpuInstructions::XorVxVy(x_register, y_register) => {
|
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) => {
|
Chip8CpuInstructions::AddVxVy(x_register, y_register) => {
|
||||||
0x8004u16 | (*x_register as u16) << 8 | (*y_register as u16) << 4
|
0x8004u16 | (*x_register as u16) << 8 | (*y_register as u16) << 4
|
||||||
@ -568,20 +568,16 @@ impl Chip8CpuInstructions {
|
|||||||
// Set Vx = Vx SHR 1.
|
// Set Vx = Vx SHR 1.
|
||||||
// SHIFT 1 Bit ---->
|
// 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.
|
// 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
|
// overflow check
|
||||||
|
let rotated = initial_value >> 1;
|
||||||
|
input.registers.poke(*x as u8, rotated);
|
||||||
if initial_value.bitand(0b1) == 1 {
|
if initial_value.bitand(0b1) == 1 {
|
||||||
input.registers.poke(0x0f, 0x01);
|
input.registers.poke(0x0f, 0x01);
|
||||||
} else {
|
} else {
|
||||||
input.registers.poke(0x0f, 0x00);
|
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) => {
|
Chip8CpuInstructions::SubnVxVy(x, y) => {
|
||||||
// 8xy7 - SUBN Vx, Vy
|
// 8xy7 - SUBN Vx, Vy
|
||||||
@ -592,15 +588,18 @@ impl Chip8CpuInstructions {
|
|||||||
let x_register = input.registers.peek(*x as u8);
|
let x_register = input.registers.peek(*x as u8);
|
||||||
let mut value_to_poke = 0;
|
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;
|
value_to_poke = (y_register as u16 + 256) - x_register as u16;
|
||||||
1 } else {
|
|
||||||
value_to_poke = (y_register - x_register) as u16;
|
|
||||||
0
|
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(0xf, new_value);
|
||||||
input.registers.poke(*x as u8, value_to_poke as u8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Chip8CpuInstructions::ShlVxVy(x, _) => {
|
Chip8CpuInstructions::ShlVxVy(x, _) => {
|
||||||
@ -608,14 +607,16 @@ impl Chip8CpuInstructions {
|
|||||||
// Set Vx = Vx SHL 1.
|
// 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.
|
// 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 initial_value = input.registers.peek(*x);
|
||||||
let rotated = initial_value.shl(1);
|
|
||||||
if 0b10000000 & initial_value == 0b10000000 {
|
// 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);
|
input.registers.poke(0x0f, 0x01);
|
||||||
} else {
|
} else {
|
||||||
input.registers.poke(0x0f, 0x00);
|
input.registers.poke(0x0f, 0x00);
|
||||||
}
|
}
|
||||||
input.registers.poke(*x as u8,rotated);
|
|
||||||
}
|
}
|
||||||
Chip8CpuInstructions::SneVxVy(vx_register, vy_register) => {
|
Chip8CpuInstructions::SneVxVy(vx_register, vy_register) => {
|
||||||
// 9xy0 - SNE Vx, Vy
|
// 9xy0 - SNE Vx, Vy
|
||||||
@ -655,7 +656,7 @@ impl Chip8CpuInstructions {
|
|||||||
let new_value: u8 = random();
|
let new_value: u8 = random();
|
||||||
input.registers.poke(*x as u8, new_value & *byte as u8)
|
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.
|
// 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.
|
// 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);
|
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}");
|
println!("CHIP8CPUINSTRUCTION:DRAWVXNIBBLE -> READ BYTE [0x{byte_index:2x}]\t{current_byte:02x}\t{current_byte:08b}");
|
||||||
for bit_index in 0..8 {
|
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;
|
let current_bit = (current_byte.shr(7 - bit_index) & 0x1u8) == 0x1u8;
|
||||||
input.video_memory.poke(data_offset, current_bit);
|
input.video_memory.poke(data_offset, current_bit);
|
||||||
}
|
}
|
||||||
@ -822,7 +823,7 @@ impl Chip8CpuInstructions {
|
|||||||
input.registers.poke(index as u8, src_value);
|
input.registers.poke(index as u8, src_value);
|
||||||
println!("POKING Register 0x{index:02x} with 0x{src_value:04x} using offset 0x{offset:04x}");
|
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 => {}
|
Chip8CpuInstructions::XXXXERRORINSTRUCTION => {}
|
||||||
};
|
};
|
||||||
@ -1274,7 +1275,7 @@ mod test {
|
|||||||
assert_eq!(x.registers.peek(0xf), 0x0);
|
assert_eq!(x.registers.peek(0xf), 0x0);
|
||||||
|
|
||||||
let mut x = Chip8Computer::new();
|
let mut x = Chip8Computer::new();
|
||||||
x.registers.poke(0x1, 0b10101010);
|
x.registers.poke(0x1, 0b10101010);
|
||||||
Chip8CpuInstructions::ShlVxVy(0x1, 0x1).execute(&mut x);
|
Chip8CpuInstructions::ShlVxVy(0x1, 0x1).execute(&mut x);
|
||||||
assert_eq!(x.registers.peek(0x1), 0b01010100);
|
assert_eq!(x.registers.peek(0x1), 0b01010100);
|
||||||
assert_eq!(x.registers.peek(0xf), 0x1);
|
assert_eq!(x.registers.peek(0xf), 0x1);
|
||||||
@ -1371,8 +1372,7 @@ mod test {
|
|||||||
for (idx, value) in to_load.iter().enumerate() {
|
for (idx, value) in to_load.iter().enumerate() {
|
||||||
assert_eq!(x.registers.peek(idx as u8), *value);
|
assert_eq!(x.registers.peek(idx as u8), *value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn Sknkpvx_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,
|
// If the least-significant bit of Vx is 1, then VF is set to 1,
|
||||||
// otherwise 0. Then Vx is divided by 2.
|
// otherwise 0. Then Vx is divided by 2.
|
||||||
let mut x = Chip8Computer::new();
|
let mut x = Chip8Computer::new();
|
||||||
// 0b10000000 -> 0b01000000
|
// 0b10101010 -> 0b01010101
|
||||||
let start_value = 0b10000000;
|
x.registers.poke(0x01, 0b10101010);
|
||||||
let end_value = 0b01000000;
|
x.registers.poke(0x0f, 0x0);
|
||||||
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);
|
|
||||||
|
|
||||||
// 0b00000001 -> 0b00000000
|
Chip8CpuInstructions::ShlVxVy(0x01, 0x00).execute(&mut x);
|
||||||
let start_value = 0b00000001;
|
assert_eq!(x.registers.peek(0x01), 0b01010100);
|
||||||
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);
|
|
||||||
assert_eq!(x.registers.peek(0x0f), 1);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,5 +6,4 @@ fn smoke() { assert!(true) }
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_rom_1_works() {
|
fn test_rom_1_works() {
|
||||||
let mut x = Chip8Computer::new();
|
let mut x = Chip8Computer::new();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user