more fixed tests and covered text.
This commit is contained in:
parent
fc62512edd
commit
731f20d894
@ -1,3 +1,4 @@
|
||||
use std::ops::{Shl, Shr};
|
||||
use imgui::ColorPicker3;
|
||||
use log::debug;
|
||||
use rand::random;
|
||||
@ -53,6 +54,7 @@ pub enum Chip8CpuInstructions {
|
||||
LdVxI(u16), // 0xFx65 Load V0 to Vx in memory starting at I
|
||||
XXXXERRORINSTRUCTION,
|
||||
}
|
||||
|
||||
impl Chip8CpuInstructions {
|
||||
pub fn encode(&self) -> u16 {
|
||||
match self {
|
||||
@ -172,7 +174,7 @@ impl Chip8CpuInstructions {
|
||||
let addr_param = InstructionUtil::read_addr_from_instruction(input);
|
||||
let byte_param = InstructionUtil::read_byte_from_instruction(input);
|
||||
let nibble_param = InstructionUtil::read_nibble_from_instruction(input);
|
||||
let ubln = u16::rotate_right(InstructionUtil::read_upper_byte_lower_nibble(input), 8);
|
||||
let ubln = InstructionUtil::read_upper_byte_lower_nibble(input);
|
||||
let last_byte = input & 0xFF;
|
||||
|
||||
match input {
|
||||
@ -303,6 +305,8 @@ impl Chip8CpuInstructions {
|
||||
0xE09E..=0xEFA1 => {
|
||||
match last_byte {
|
||||
0x9E => {
|
||||
println!("DECODING {:4x}", input);
|
||||
println!("UBLN: {:4x}", ubln);
|
||||
Chip8CpuInstructions::SkpVx(ubln)
|
||||
}
|
||||
0xA1 => {
|
||||
@ -314,7 +318,7 @@ impl Chip8CpuInstructions {
|
||||
}
|
||||
}
|
||||
0xF007..=0xFF65 => {
|
||||
// println!("COMPARING LAST BYTE FROM TODECODE: {:2x} to {:4x} with {:2x}", last_byte, input, ubln);
|
||||
// println!("COMPARING LAST BYTE FROM TODECODE: {:2x} to {:4x} with {:2x}", last_byte, input, ubln);
|
||||
match last_byte {
|
||||
0x07 => {
|
||||
Chip8CpuInstructions::LdVxDt(ubln)
|
||||
@ -360,7 +364,7 @@ impl Chip8CpuInstructions {
|
||||
let _ = match self {
|
||||
// 0x0nnn Exit to System Call
|
||||
Chip8CpuInstructions::SysAddr(new_address) => {
|
||||
// println!("SYS TO [{new_address}]");
|
||||
// println!("SYS TO [{new_address}]");
|
||||
input.registers.poke_pc(*new_address as u16);
|
||||
}
|
||||
// * 0x00E0 Clear Screen
|
||||
@ -396,10 +400,10 @@ impl Chip8CpuInstructions {
|
||||
}
|
||||
}
|
||||
// 0x5xy0 Skip next instruction if Vx == Vy
|
||||
Chip8CpuInstructions::SeVxVy(x,y) => {
|
||||
Chip8CpuInstructions::SeVxVy(x, y) => {
|
||||
let lhs = input.registers.peek(*x as u8);
|
||||
let rhs = input.registers.peek(*y as u8);
|
||||
// println!("COMPARING [{lhs}] to [{rhs}]");
|
||||
// println!("COMPARING [{lhs}] to [{rhs}]");
|
||||
if lhs == rhs {
|
||||
input.registers.advance_pc();
|
||||
}
|
||||
@ -408,7 +412,7 @@ impl Chip8CpuInstructions {
|
||||
Chip8CpuInstructions::LdVxByte(register, byte) => {
|
||||
let start_value = input.registers.peek(*register as u8);
|
||||
let byte_value = *byte as u8;
|
||||
// println!("SETTING REGISTER [{register}] FROM [{start_value}] to [{byte_value}] by loading.");
|
||||
// println!("SETTING REGISTER [{register}] FROM [{start_value}] to [{byte_value}] by loading.");
|
||||
input.registers.poke(*register as u8, byte_value);
|
||||
}
|
||||
// 0x7xkk Set Vx = Vx + kk
|
||||
@ -452,7 +456,7 @@ impl Chip8CpuInstructions {
|
||||
}
|
||||
input.registers.poke(*x as u8, working as u8);
|
||||
}
|
||||
Chip8CpuInstructions::SubVxVy(x,y) => {
|
||||
Chip8CpuInstructions::SubVxVy(x, y) => {
|
||||
// 8xy5 - SUB Vx, Vy
|
||||
// Set Vx = Vx - Vy, set VF = NOT borrow.
|
||||
//
|
||||
@ -470,9 +474,9 @@ impl Chip8CpuInstructions {
|
||||
if 0xb1 & initial_value == 1 {
|
||||
input.registers.poke(0xf, 1);
|
||||
}
|
||||
input.registers.poke(*x as u8, initial_value.rotate_left(1));
|
||||
input.registers.poke(*x as u8, initial_value.shr(1));
|
||||
}
|
||||
Chip8CpuInstructions::SubnVxVy(x,y) => {
|
||||
Chip8CpuInstructions::SubnVxVy(x, y) => {
|
||||
// 8xy7 - SUBN Vx, Vy
|
||||
// Set Vx = Vy - Vx, set VF = NOT borrow.
|
||||
//
|
||||
@ -494,7 +498,7 @@ impl Chip8CpuInstructions {
|
||||
if 0x80 & initial_value == 0x80 {
|
||||
input.registers.poke(0xf, 1);
|
||||
}
|
||||
input.registers.poke(*x as u8, initial_value.rotate_left(1));
|
||||
input.registers.poke(*x as u8, initial_value.shl(1));
|
||||
}
|
||||
Chip8CpuInstructions::SneVxVy(vx_register, vy_register) => {
|
||||
// 9xy0 - SNE Vx, Vy
|
||||
@ -528,9 +532,10 @@ impl Chip8CpuInstructions {
|
||||
// Cxkk - RND Vx, byte
|
||||
// Set Vx = random byte AND kk.
|
||||
//
|
||||
// The interpreter generates a random number from 0 to 255, which is then ANDed with the value kk. The results are stored in Vx. See instruction 8xy2 for more information on AND.
|
||||
|
||||
let new_value: u8 = random() ;
|
||||
// The interpreter generates a random number from 0 to 255,
|
||||
// which is then ANDed with the value kk.
|
||||
// The results are stored in Vx.
|
||||
let new_value: u8 = random();
|
||||
input.registers.poke(*x as u8, (new_value & *byte as u8))
|
||||
}
|
||||
Chip8CpuInstructions::DrawVxVyNibble(x, y, n) => {
|
||||
@ -548,8 +553,8 @@ impl Chip8CpuInstructions {
|
||||
let start_position = input.registers.peek_i();
|
||||
let num_bytes_to_read = *n;
|
||||
for i in start_position..start_position + num_bytes_to_read {
|
||||
// let current_byte = input.memory[i as usize];
|
||||
// println!("READ BYTE [{current_byte:8b}");
|
||||
// let current_byte = input.memory[i as usize];
|
||||
// println!("READ BYTE [{current_byte:8b}");
|
||||
}
|
||||
|
||||
let mut did_change: bool = false;
|
||||
@ -572,8 +577,6 @@ impl Chip8CpuInstructions {
|
||||
//
|
||||
// Checks the keyboard, and if the key corresponding to the value of Vx is currently in the down position, PC is increased by 2.
|
||||
let key_to_check = input.registers.peek(*x as u8);
|
||||
|
||||
|
||||
}
|
||||
Chip8CpuInstructions::SnkpVx(x) => {
|
||||
|
||||
@ -581,8 +584,6 @@ impl Chip8CpuInstructions {
|
||||
// Skip next instruction if key with the value of Vx is not pressed.
|
||||
//
|
||||
// Checks the keyboard, and if the key corresponding to the value of Vx is currently in the up position, PC is increased by 2.
|
||||
|
||||
|
||||
}
|
||||
Chip8CpuInstructions::LdVxDt(x) => {
|
||||
// Fx07 - LD Vx, DT
|
||||
@ -598,15 +599,17 @@ impl Chip8CpuInstructions {
|
||||
//
|
||||
// All execution stops until a key is pressed, then the value of that key is stored in Vx.
|
||||
}
|
||||
Chip8CpuInstructions::LdDtVx(new_time) => {
|
||||
Chip8CpuInstructions::LdDtVx(source_register) => {
|
||||
// Fx15 - LD DT, Vx
|
||||
// Set delay timer = Vx.
|
||||
//
|
||||
// DT is set equal to the value of Vx.
|
||||
println!("SETTING DELAY TIMER TO [{}]", *new_time);
|
||||
input.delay_timer.set_timer(*new_time as i32);
|
||||
let new_time = input.registers.peek(*source_register as u8);
|
||||
println!("SETTING DELAY TIMER TO [{}]", new_time);
|
||||
input.delay_timer.set_timer(new_time as i32);
|
||||
}
|
||||
Chip8CpuInstructions::LdStVx(new_time) => {
|
||||
println!("SETTING SOUND TIMER TO [0x{:2x}]", *new_time);
|
||||
input.sound_timer.set_timer(*new_time as i32);
|
||||
}
|
||||
Chip8CpuInstructions::AddIVx(x) => {
|
||||
@ -623,14 +626,12 @@ impl Chip8CpuInstructions {
|
||||
// Set I = location of sprite for digit Vx.
|
||||
//
|
||||
// The value of I is set to the location for the hexadecimal sprite corresponding to the value of Vx. See section 2.4, Display, for more information on the Chip-8 hexadecimal font.
|
||||
|
||||
}
|
||||
Chip8CpuInstructions::LdBVx(x) => {
|
||||
// Fx33 - LD B, Vx
|
||||
// Store BCD representation of Vx in memory locations I, I+1, and I+2.
|
||||
//
|
||||
// The interpreter takes the decimal value of Vx, and places the hundreds digit in memory at location in I, the tens digit at location I+1, and the ones digit at location I+2.
|
||||
|
||||
}
|
||||
Chip8CpuInstructions::LdIVx(x) => {
|
||||
// Store registers V0 through Vx in memory starting at location I.
|
||||
@ -704,8 +705,8 @@ mod test {
|
||||
assert_eq!(Chip8CpuInstructions::LdBVx(0xd).encode(), 0xfd33);
|
||||
assert_eq!(Chip8CpuInstructions::LdIVx(0xe).encode(), 0xfe55);
|
||||
assert_eq!(Chip8CpuInstructions::LdVxI(0x3).encode(), 0xf365);
|
||||
assert!(matches!( Chip8CpuInstructions::decode(0x00E0u16), Chip8CpuInstructions::CLS));
|
||||
assert!(matches!( Chip8CpuInstructions::decode(0x00EEu16), Chip8CpuInstructions::RET));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0x00E0u16), Chip8CpuInstructions::CLS));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0x00EEu16), Chip8CpuInstructions::RET));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0x0123), Chip8CpuInstructions::SysAddr(0x123)));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0x0FFF), Chip8CpuInstructions::SysAddr(0xfff)));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0x1002), Chip8CpuInstructions::JpAddr(0x2)));
|
||||
@ -741,6 +742,7 @@ mod test {
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0xfd33), Chip8CpuInstructions::LdBVx(0xd)));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0xfe55), Chip8CpuInstructions::LdIVx(0xe)));
|
||||
assert!(matches!(Chip8CpuInstructions::decode(0xf365), Chip8CpuInstructions::LdVxI(0x3)));
|
||||
|
||||
}
|
||||
|
||||
/// START OF THE EXECUTION TESTS
|
||||
@ -755,9 +757,13 @@ mod test {
|
||||
Chip8CpuInstructions::SysAddr(0x0AF).execute(&mut x);
|
||||
assert_eq!(x.registers.peek_pc(), 0x0AF);
|
||||
}
|
||||
|
||||
fn cls_test() {
|
||||
// * 0x00E0 Clear Screen
|
||||
// todo: Need to write this
|
||||
let mut x = Chip8Computer::new();
|
||||
|
||||
|
||||
}
|
||||
|
||||
fn ret_test() {
|
||||
@ -875,7 +881,6 @@ mod test {
|
||||
Chip8CpuInstructions::LdVxVy(0x01, 0x02).execute(&mut x);
|
||||
assert_eq!(x.registers.peek(1), 0x02);
|
||||
assert_eq!(x.registers.peek_pc(), 0x206);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -887,7 +892,7 @@ mod test {
|
||||
let mut x = Chip8Computer::new();
|
||||
Chip8CpuInstructions::LdVxByte(1, 0x50).execute(&mut x);
|
||||
Chip8CpuInstructions::LdVxByte(2, 0x0A).execute(&mut x);
|
||||
Chip8CpuInstructions::OrVxVy(1,2).execute(&mut x);
|
||||
Chip8CpuInstructions::OrVxVy(1, 2).execute(&mut x);
|
||||
assert_eq!(x.registers.peek(1), 0x5A);
|
||||
assert_eq!(x.registers.peek_pc(), 0x206);
|
||||
}
|
||||
@ -901,7 +906,7 @@ mod test {
|
||||
let mut x = Chip8Computer::new();
|
||||
Chip8CpuInstructions::LdVxByte(1, 0xFC).execute(&mut x);
|
||||
Chip8CpuInstructions::LdVxByte(2, 0xCA).execute(&mut x);
|
||||
Chip8CpuInstructions::AndVxVy(1,2).execute(&mut x);
|
||||
Chip8CpuInstructions::AndVxVy(1, 2).execute(&mut x);
|
||||
assert_eq!(x.registers.peek(1), 0xC8);
|
||||
assert_eq!(x.registers.peek_pc(), 0x206);
|
||||
}
|
||||
@ -915,7 +920,7 @@ mod test {
|
||||
let mut x = Chip8Computer::new();
|
||||
Chip8CpuInstructions::LdVxByte(1, 0xFC).execute(&mut x);
|
||||
Chip8CpuInstructions::LdVxByte(2, 0xCA).execute(&mut x);
|
||||
Chip8CpuInstructions::XorVxVy(1,2).execute(&mut x);
|
||||
Chip8CpuInstructions::XorVxVy(1, 2).execute(&mut x);
|
||||
assert_eq!(x.registers.peek(1), 0x36);
|
||||
assert_eq!(x.registers.peek_pc(), 0x206);
|
||||
}
|
||||
@ -941,69 +946,90 @@ mod test {
|
||||
Chip8CpuInstructions::LdVxByte(0xf, 0x00).execute(&mut x);
|
||||
Chip8CpuInstructions::LdVxByte(0x1, 0xff).execute(&mut x);
|
||||
Chip8CpuInstructions::LdVxByte(0x2, 0x01).execute(&mut x);
|
||||
Chip8CpuInstructions::AddVxVy(1,2).execute(&mut x);
|
||||
Chip8CpuInstructions::AddVxVy(1, 2).execute(&mut x);
|
||||
// T2
|
||||
assert_eq!(x.registers.peek(0xf), 1);
|
||||
assert_eq!(x.registers.peek(1), 0);
|
||||
assert_eq!(x.registers.peek_pc(), 0x208)
|
||||
}
|
||||
/* #[test]
|
||||
fn SubVxVy_test() {
|
||||
todo: this test sucks. dont have the borrow concept in here.
|
||||
Set Vx = Vx - Vy, set VF = NOT borrow.
|
||||
If Vx > Vy, then VF is set to 1, otherwise 0.
|
||||
Then Vy is subtracted from Vx, and the results stored in Vx.
|
||||
let mut x = Chip8Computer::new();
|
||||
Chip8CpuInstructions::LdVxByte(1, 0x10).execute(&mut x);
|
||||
Chip8CpuInstructions::LdVxByte(2, 0x01).execute(&mut x);
|
||||
Chip8CpuInstructions::LdVxByte(0xf, 0x00).execute(&mut x);
|
||||
Chip8CpuInstructions::SubVxVy(0x1, 0x2).execute(&mut x);
|
||||
/* #[test]
|
||||
fn SubVxVy_test() {
|
||||
todo: this test sucks. dont have the borrow concept in here.
|
||||
Set Vx = Vx - Vy, set VF = NOT borrow.
|
||||
If Vx > Vy, then VF is set to 1, otherwise 0.
|
||||
Then Vy is subtracted from Vx, and the results stored in Vx.
|
||||
let mut x = Chip8Computer::new();
|
||||
Chip8CpuInstructions::LdVxByte(1, 0x10).execute(&mut x);
|
||||
Chip8CpuInstructions::LdVxByte(2, 0x01).execute(&mut x);
|
||||
Chip8CpuInstructions::LdVxByte(0xf, 0x00).execute(&mut x);
|
||||
Chip8CpuInstructions::SubVxVy(0x1, 0x2).execute(&mut x);
|
||||
|
||||
assert_eq!(x.registers.peek_pc(), 0x208);
|
||||
assert_eq!(x.registers.peek(1), 0xF);
|
||||
assert_eq!(x.registers.peek(0x10), 0);
|
||||
assert_eq!(x.registers.peek_pc(), 0x208);
|
||||
assert_eq!(x.registers.peek(1), 0xF);
|
||||
assert_eq!(x.registers.peek(0x10), 0);
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
*/
|
||||
|
||||
#[test]
|
||||
fn ShrVxVy_test() {
|
||||
/*
|
||||
Set Vx = Vx SHR 1.
|
||||
|
||||
If the least-significant bit of Vx is 1, then VF is set to 1, otherwise 0. Then Vx is divided by 2.
|
||||
*/
|
||||
let x = Chip8Computer::new();
|
||||
Chip8CpuInstructions::LdVxByte(0xf, 0x00);
|
||||
Chip8CpuInstructions::LdVxByte(0x1, 0x08); // 0b0000 1000 (0x08)
|
||||
Chip8CpuInstructions::LdVxByte(0x2, 0x2);
|
||||
Chip8CpuInstructions::ShrVxVy(0x1, 0x2); // 0b0000 0010 (0x02) (Not Set)
|
||||
assert_eq!(x.registers.peek(1), 0x02);
|
||||
let mut x = Chip8Computer::new();
|
||||
Chip8CpuInstructions::LdVxByte(0xf, 0x00).execute(&mut x);
|
||||
Chip8CpuInstructions::LdVxByte(0x1, 0x08).execute(&mut x); // 0b0000 1000 (0x08)
|
||||
Chip8CpuInstructions::LdVxByte(0x2, 0x2).execute(&mut x);
|
||||
Chip8CpuInstructions::ShrVxVy(0x1, 0x2).execute(&mut x); // 0b0000 0010 (0x02) (Not Set)
|
||||
assert_eq!(x.registers.peek(1), 0x04);
|
||||
assert_eq!(x.registers.peek(0xf), 0);
|
||||
assert_eq!(x.registers.peek_pc(), 0x206);
|
||||
assert_eq!(x.registers.peek_pc(), 0x208);
|
||||
|
||||
let x = Chip8Computer::new();
|
||||
Chip8CpuInstructions::LdVxByte(0xf, 0x00);
|
||||
Chip8CpuInstructions::LdVxByte(0x1, 0x09); // 0b0000 1001 (0x09)
|
||||
Chip8CpuInstructions::LdVxByte(0x2, 0x2);
|
||||
Chip8CpuInstructions::ShrVxVy(0x1, 0x2); // 0b0000 0010 (0x02) (Set)
|
||||
assert_eq!(x.registers.peek(1), 0x02);
|
||||
assert_eq!(x.registers.peek(0xf), 1);
|
||||
assert_eq!(x.registers.peek_pc(), 0x206);
|
||||
let mut x = Chip8Computer::new();
|
||||
Chip8CpuInstructions::LdVxByte(0xf, 0x00).execute(&mut x);
|
||||
Chip8CpuInstructions::LdVxByte(0x1, 0b00001001).execute(&mut x); // 0b0000 1001 (0x09)
|
||||
Chip8CpuInstructions::ShrVxVy(0x1, 0x2).execute(&mut x); // 0b0000 0100 (0x02) (Set)
|
||||
Chip8CpuInstructions::ShrVxVy(0x1, 0x1).execute(&mut x);
|
||||
assert_eq!(x.registers.peek(0x1), 0b00000010);
|
||||
assert_eq!(x.registers.peek(0xf), 0x1);
|
||||
assert_eq!(x.registers.peek_pc(), 0x208);
|
||||
}
|
||||
|
||||
fn SneVxVy_test() {}
|
||||
|
||||
fn LdiAddr_test() {}
|
||||
|
||||
fn JpV0Addr_test() {}
|
||||
fn RndVxByte_test() {}
|
||||
|
||||
#[test]
|
||||
fn RndVxByte_test() {
|
||||
let mut x = Chip8Computer::new();
|
||||
|
||||
// generate random number masked by 0xF0;
|
||||
let mask = 0xF0u8;
|
||||
Chip8CpuInstructions::RndVxByte(0x0, mask as u16).execute(&mut x);
|
||||
let register_value = x.registers.peek(0x0);
|
||||
assert!(register_value < mask);
|
||||
|
||||
// generate random number masked by 0x0F;
|
||||
let mask2 = 0x0Fu8;
|
||||
Chip8CpuInstructions::RndVxByte(0x1, mask2 as u16).execute(&mut x);
|
||||
let register_value = x.registers.peek(0x1);
|
||||
assert!(register_value < mask);
|
||||
}
|
||||
|
||||
fn DrawVxVyNibble_test() {}
|
||||
|
||||
fn SkpVx_test() {
|
||||
// skip if key pressed
|
||||
|
||||
|
||||
}
|
||||
|
||||
fn SnKpVx_test() {
|
||||
// skip key not pressed
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn LdVxDt_test() {
|
||||
// delay timer reading
|
||||
@ -1028,33 +1054,54 @@ mod test {
|
||||
fn LdVxK_test() {
|
||||
// Wait for a key press, store the value of the key in Vx.
|
||||
// All execution stops until a key is pressed, then the value of that key is stored in Vx.
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn LdStVx_test() {
|
||||
// sound timer setting
|
||||
}
|
||||
fn LdIVx_test() {}
|
||||
fn LdVxI_test() {}
|
||||
/*
|
||||
#[test]
|
||||
fn LdDtVx_test() {
|
||||
|
||||
// delay timer setting
|
||||
let mut x = Chip8Computer::new();
|
||||
Chip8CpuInstructions::LdVxByte(0x1, 0x10).execute(&mut x);
|
||||
Chip8CpuInstructions::LdStVx(0x10).execute(&mut x);
|
||||
|
||||
// lets set our delay timer...
|
||||
Chip8CpuInstructions::LdVxByte(0x0, 0x80).execute(&mut x);
|
||||
Chip8CpuInstructions::LdDtVx(0x0).execute(&mut x);
|
||||
// tick from 0x8 to 0x1
|
||||
for i in 0..6 { x.sound_timer.tick(); }
|
||||
|
||||
// now that we have our timer set to 0x80 we should tick it 0x10 times
|
||||
// so we are then down to 0x70
|
||||
for i in 0..0x10 {
|
||||
x.delay_timer.tick();
|
||||
}
|
||||
// Then tell the CPU to copy that timer over into our V0
|
||||
Chip8CpuInstructions::LdVxK(0x0).execute(&mut x);
|
||||
let register_value = x.registers.peek(0);
|
||||
// assert_eq!(register_value, 0x70);
|
||||
assert_eq!(x.sound_timer.current(), 0xA);
|
||||
}
|
||||
*/
|
||||
|
||||
fn LdIVx_test() {
|
||||
// Store registers V0 through Vx in memory starting at location I.
|
||||
//
|
||||
// The interpreter copies the values of registers V0 through Vx
|
||||
// into memory, starting at the address in I.
|
||||
|
||||
}
|
||||
|
||||
fn LdVxI_test() {}
|
||||
// Read registers V0 through Vx from memory starting at location I.
|
||||
//
|
||||
// The interpreter reads values from memory starting at location I into registers V0 through Vx.
|
||||
|
||||
/*
|
||||
#[test]
|
||||
fn LdDtVx_test() {
|
||||
|
||||
// delay timer setting
|
||||
let mut x = Chip8Computer::new();
|
||||
|
||||
// lets set our delay timer...
|
||||
Chip8CpuInstructions::LdVxByte(0x0, 0x80).execute(&mut x);
|
||||
Chip8CpuInstructions::LdDtVx(0x0).execute(&mut x);
|
||||
|
||||
// now that we have our timer set to 0x80 we should tick it 0x10 times
|
||||
// so we are then down to 0x70
|
||||
for i in 0..0x10 {
|
||||
x.delay_timer.tick();
|
||||
}
|
||||
// Then tell the CPU to copy that timer over into our V0
|
||||
Chip8CpuInstructions::LdVxK(0x0).execute(&mut x);
|
||||
let register_value = x.registers.peek(0);
|
||||
// assert_eq!(register_value, 0x70);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@ -56,4 +56,7 @@ impl Chip8Registers {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
#[test]
|
||||
fn smoke() { assert!(true) }
|
||||
|
||||
}
|
||||
@ -19,6 +19,7 @@ impl SoundTimer {
|
||||
}
|
||||
|
||||
pub fn tick(&mut self) {
|
||||
println!("TICKING SOUND FROM {} to {}", self.counter, self.counter - 1);
|
||||
if self.counter > 0 {
|
||||
self.counter -= 1;
|
||||
/*
|
||||
|
||||
@ -1,6 +1,25 @@
|
||||
|
||||
pub struct InstructionUtil {}
|
||||
|
||||
impl InstructionUtil {
|
||||
pub fn byte_to_bools(to_convert: u8) -> [bool; 8] {
|
||||
let mut return_values = [false; 8];
|
||||
for i in 0..8 {
|
||||
let new_value = to_convert >> i & 0x1 == 1;
|
||||
return_values[i as usize] = new_value;
|
||||
}
|
||||
return_values
|
||||
}
|
||||
|
||||
pub fn bools_to_byte(to_convert: [bool; 8]) -> u8 {
|
||||
let mut return_value = 0u8;
|
||||
for i in 0..to_convert.len() {
|
||||
let new_bit = 0x1 << i;
|
||||
if to_convert[i] {
|
||||
return_value = return_value | new_bit
|
||||
}
|
||||
}
|
||||
return_value
|
||||
}
|
||||
|
||||
pub fn split_bytes(to_split: u16) -> (u8, u8) {
|
||||
let high = to_split.rotate_left(8) as u8;
|
||||
@ -10,7 +29,7 @@ impl InstructionUtil {
|
||||
}
|
||||
|
||||
pub fn join_bytes(high: u8, low: u8) -> u16 {
|
||||
let result = (high as u16 )<< 8 | low as u16;
|
||||
let result = (high as u16) << 8 | low as u16;
|
||||
result
|
||||
}
|
||||
|
||||
@ -40,11 +59,10 @@ impl InstructionUtil {
|
||||
}
|
||||
|
||||
pub fn read_upper_byte_lower_nibble(to_read_from: u16) -> u16 {
|
||||
to_read_from & 0x0f00
|
||||
(to_read_from & 0x0f00) >> 8
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
@ -65,7 +83,7 @@ mod test {
|
||||
#[test]
|
||||
fn join_bytes() {
|
||||
// from 0xAB low and 0xCD high we get 0xABCD
|
||||
let merged = InstructionUtil::join_bytes( 0xcd, 0xab);
|
||||
let merged = InstructionUtil::join_bytes(0xcd, 0xab);
|
||||
assert_eq!(merged, 0xcdab);
|
||||
}
|
||||
|
||||
@ -83,6 +101,20 @@ mod test {
|
||||
#[test]
|
||||
fn ubln() {
|
||||
// from 0xABCD we should see B
|
||||
assert_eq!(InstructionUtil::read_upper_byte_lower_nibble(0xABCD), 0xB << 8);
|
||||
assert_eq!(InstructionUtil::read_upper_byte_lower_nibble(0xABCD), 0xB);
|
||||
assert_eq!(InstructionUtil::read_upper_byte_lower_nibble(0x0123), 0x1);
|
||||
assert_eq!(InstructionUtil::read_upper_byte_lower_nibble(0x0000), 0x0);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn byte_to_bool_changes() {
|
||||
assert_eq!(InstructionUtil::byte_to_bools(0b00000000), [false, false, false, false, false, false, false, false]);
|
||||
assert_eq!(InstructionUtil::byte_to_bools(0b11111111), [true, true, true, true, true, true, true, true]);
|
||||
assert_eq!(InstructionUtil::byte_to_bools(0b11001100), [false, false, true, true, false, false, true, true]);
|
||||
assert_eq!(InstructionUtil::byte_to_bools(0b11110000), [false, false, false, false, true, true, true, true]);
|
||||
assert_eq!(InstructionUtil::bools_to_byte([false, false, false, false, false, false, false, false]), 0b00000000);
|
||||
assert_eq!(InstructionUtil::bools_to_byte([true, true, true, true, true, true, true, true]), 0b11111111);
|
||||
assert_eq!(InstructionUtil::bools_to_byte([false, false, true, true, false, false, true, true]), 0b11001100);
|
||||
assert_eq!(InstructionUtil::bools_to_byte([false, false, false, false, true, true, true, true]), 0b11110000);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user