[cpu] Add all remaining instruction decodes
This commit is contained in:
@@ -36,7 +36,7 @@ impl Device {
|
||||
stack: Vec::with_capacity(16),
|
||||
timer,
|
||||
super_chip8_mode: false,
|
||||
device_keyboard
|
||||
device_keyboard,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ impl Device {
|
||||
const FONT_DEFAULT_MEM_LOCATION_START: usize = 0x50;
|
||||
const FONT_DEFAULT_MEM_LOCATION_END: usize = 0x9F;
|
||||
const ROM_START: usize = 0x200;
|
||||
pub fn cycle(&mut self) ->EmulatorResult<()>{
|
||||
pub fn cycle(&mut self) -> EmulatorResult<()> {
|
||||
self.device_keyboard.update_keyboard()?;
|
||||
|
||||
let pc = self.registers.pc as usize;
|
||||
@@ -140,12 +140,26 @@ impl Device {
|
||||
self.registers.pc += 2;
|
||||
}
|
||||
}
|
||||
Instruction::JumpWithOffset(_, _) => {}
|
||||
Instruction::JumpWithOffset(x, num) => {
|
||||
let regnum = if self.super_chip8_mode { x } else { 0 };
|
||||
let new_pc = self.registers.v[regnum] as u16 + num ;
|
||||
self.registers.pc = new_pc;
|
||||
}
|
||||
Instruction::RandomAnd(dest, n) => {
|
||||
self.registers.v[dest] = random::<u8>() & n;
|
||||
}
|
||||
Instruction::SkipIfKeyPressed(_) => {}
|
||||
Instruction::SkipIfKeyNotPressed(_) => {}
|
||||
Instruction::SkipIfKeyPressed(x) => {
|
||||
let key_press_expected_for = self.registers.v[x];
|
||||
if self.device_keyboard.query_key_down(key_press_expected_for) {
|
||||
self.registers.pc += 2;
|
||||
}
|
||||
}
|
||||
Instruction::SkipIfKeyNotPressed(x) => {
|
||||
let key_press_expected_for = self.registers.v[x];
|
||||
if !self.device_keyboard.query_key_down(key_press_expected_for) {
|
||||
self.registers.pc += 2;
|
||||
}
|
||||
}
|
||||
Instruction::Set(x, y) => {
|
||||
self.registers.v[x] = self.registers.v[y];
|
||||
}
|
||||
@@ -170,14 +184,31 @@ impl Device {
|
||||
self.registers.v[x] = wrapped_subtraction_result;
|
||||
self.set_flag_register(is_overflow);
|
||||
}
|
||||
Instruction::RShift(_, _) => {}
|
||||
Instruction::RSub(x, y) => {
|
||||
let left = self.registers.v[y];
|
||||
let (wrapped_subtraction_result, is_overflow) = left.overflowing_sub(self.registers.v[x]);
|
||||
self.registers.v[x] = wrapped_subtraction_result;
|
||||
self.set_flag_register(is_overflow);
|
||||
}
|
||||
Instruction::LShift(_, _) => {}
|
||||
Instruction::RShift(x, y) => {
|
||||
if(self.super_chip8_mode){
|
||||
self.registers.v[x] = self.registers.v[y];
|
||||
}
|
||||
let (shift_res,did_overflow) = self.registers.v[x].overflowing_shr(1);
|
||||
self.registers.v[x] = shift_res;
|
||||
self.set_flag_register(did_overflow);
|
||||
}
|
||||
Instruction::LShift(x, y) => {
|
||||
if(self.super_chip8_mode){
|
||||
self.registers.v[x] = self.registers.v[y];
|
||||
}
|
||||
let (shift_res,did_overflow) = self.registers.v[x].overflowing_shl(1);
|
||||
self.registers.v[x] = shift_res;
|
||||
self.set_flag_register(did_overflow);
|
||||
},
|
||||
_=>{
|
||||
todo!()
|
||||
}
|
||||
};
|
||||
}
|
||||
///
|
||||
|
@@ -37,6 +37,24 @@ pub enum Instruction {
|
||||
SkipIfKeyPressed(usize),
|
||||
/// EXA1 - Check if key is not pressed
|
||||
SkipIfKeyNotPressed(usize),
|
||||
/// FX07 - Get delay timer, put into register
|
||||
FetchDelayTimer(usize),
|
||||
/// FX15 - set delay timer as register
|
||||
SetDelayTimer(usize),
|
||||
/// FX18 - Set sound timer as register
|
||||
SetSoundTimer(usize),
|
||||
/// FX1E - Add register to index
|
||||
AddToIndex(usize),
|
||||
/// FX0A - Wait for key as indicated by register
|
||||
GetKey(usize),
|
||||
/// FX29 - Set index to register-requested font char address in memory
|
||||
SetIndexToFontCharacter(usize),
|
||||
/// FX33 - Convert register val to bcd and store at location pointed by index
|
||||
DoBCDConversion(usize),
|
||||
/// FX55 - Store all registers from v0 to vx to memory location pointed to by index
|
||||
StoreRegistersToMemory(usize),
|
||||
/// FX65 - Load all registers from v0 to vx to memory location pointed to by index
|
||||
LoadRegistersFromMemory(usize),
|
||||
|
||||
// ALU operations going ahead
|
||||
/// 8XY0 - x=y
|
||||
@@ -139,6 +157,43 @@ impl Instruction {
|
||||
let x = (instruction & 0xf00) >> 8;
|
||||
Instruction::SkipIfKeyNotPressed(x as usize)
|
||||
}
|
||||
0xF if (instruction & 0xff) == 0x07 =>{
|
||||
let x = (instruction & 0xf00) >> 8;
|
||||
Instruction::FetchDelayTimer(x as usize)
|
||||
}
|
||||
0xF if (instruction & 0xff) == 0x15 =>{
|
||||
let x = (instruction & 0xf00) >> 8;
|
||||
Instruction::SetDelayTimer(x as usize)
|
||||
}
|
||||
0xF if (instruction & 0xff) == 0x18 =>{
|
||||
let x = (instruction & 0xf00) >> 8;
|
||||
Instruction::SetSoundTimer(x as usize)
|
||||
}
|
||||
0xF if (instruction & 0xff) == 0x1E =>{
|
||||
let x = (instruction & 0xf00) >> 8;
|
||||
Instruction::AddToIndex(x as usize)
|
||||
}
|
||||
0xF if (instruction & 0xff) == 0x0A =>{
|
||||
let x = (instruction & 0xf00) >> 8;
|
||||
Instruction::GetKey(x as usize)
|
||||
}
|
||||
//TODO add tests from here
|
||||
0xF if (instruction & 0xff) == 0x29 =>{
|
||||
let x = (instruction & 0xf00) >> 8;
|
||||
Instruction::SetIndexToFontCharacter(x as usize)
|
||||
}
|
||||
0xF if (instruction & 0xff) == 0x33 =>{
|
||||
let x = (instruction & 0xf00) >> 8;
|
||||
Instruction::DoBCDConversion(x as usize)
|
||||
}
|
||||
0xF if (instruction & 0xff) == 0x55 =>{
|
||||
let x = (instruction & 0xf00) >> 8;
|
||||
Instruction::StoreRegistersToMemory(x as usize)
|
||||
}
|
||||
0xF if (instruction & 0xff) == 0x65 =>{
|
||||
let x = (instruction & 0xf00) >> 8;
|
||||
Instruction::LoadRegistersFromMemory(x as usize)
|
||||
}
|
||||
_ => {
|
||||
todo!("Unimplemented instruction")
|
||||
}
|
||||
@@ -389,4 +444,59 @@ mod tests {
|
||||
assert_eq!(ins, SkipIfKeyNotPressed(0xb))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fetch_delay_timer(){
|
||||
let instruction_bytes = 0xfa07_u16.to_be_bytes();
|
||||
let ins = Instruction::decode_instruction(&instruction_bytes);
|
||||
assert_eq!(ins, FetchDelayTimer(0xa))
|
||||
}
|
||||
#[test]
|
||||
fn test_set_delay_timer(){
|
||||
let instruction_bytes = 0xfb15_u16.to_be_bytes();
|
||||
let ins = Instruction::decode_instruction(&instruction_bytes);
|
||||
assert_eq!(ins, SetDelayTimer(0xb))
|
||||
}
|
||||
#[test]
|
||||
fn test_set_sound_timer(){
|
||||
let instruction_bytes = 0xfc18_u16.to_be_bytes();
|
||||
let ins = Instruction::decode_instruction(&instruction_bytes);
|
||||
assert_eq!(ins, SetSoundTimer(0xc))
|
||||
}
|
||||
#[test]
|
||||
fn test_add_to_index(){
|
||||
let instruction_bytes = 0xfb1e_u16.to_be_bytes();
|
||||
let ins = Instruction::decode_instruction(&instruction_bytes);
|
||||
assert_eq!(ins, AddToIndex(0xb))
|
||||
}
|
||||
#[test]
|
||||
fn test_get_key(){
|
||||
let instruction_bytes = 0xf50a_u16.to_be_bytes();
|
||||
let ins = Instruction::decode_instruction(&instruction_bytes);
|
||||
assert_eq!(ins, GetKey(0x5))
|
||||
}
|
||||
#[test]
|
||||
fn test_set_index_to_font_char(){
|
||||
let instruction_bytes = 0xfb29_u16.to_be_bytes();
|
||||
let ins = Instruction::decode_instruction(&instruction_bytes);
|
||||
assert_eq!(ins, SetIndexToFontCharacter(0xb))
|
||||
}
|
||||
#[test]
|
||||
fn test_do_bcd_conversion(){
|
||||
let instruction_bytes = 0xfd33_u16.to_be_bytes();
|
||||
let ins = Instruction::decode_instruction(&instruction_bytes);
|
||||
assert_eq!(ins, DoBCDConversion(0xd))
|
||||
}
|
||||
#[test]
|
||||
fn test_store_regs_to_mem(){
|
||||
let instruction_bytes = 0xfb55_u16.to_be_bytes();
|
||||
let ins = Instruction::decode_instruction(&instruction_bytes);
|
||||
assert_eq!(ins, StoreRegistersToMemory(0xb))
|
||||
}
|
||||
#[test]
|
||||
fn test_load_regs_to_mem(){
|
||||
let instruction_bytes = 0xf965_u16.to_be_bytes();
|
||||
let ins = Instruction::decode_instruction(&instruction_bytes);
|
||||
assert_eq!(ins, LoadRegistersFromMemory(0b1001))
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user