diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..94d7924 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "editor.formatOnSave": true, + "rust-analyzer.checkOnSave.command": "clippy" +} \ No newline at end of file diff --git a/src/emulator/instructions/arithmetic.rs b/src/emulator/instructions/arithmetic.rs index afeb7c9..e0944f4 100644 --- a/src/emulator/instructions/arithmetic.rs +++ b/src/emulator/instructions/arithmetic.rs @@ -1,13 +1,21 @@ -use crate::{EmulatorState, Register, get_register, structs::set_register}; +use crate::{get_register, structs::set_register, EmulatorState, Register}; /// Sets the condition code flags according to `result`. `flags` parameter /// indicates which flags will be set, 0b1111 will set all (Z, S, C, P) /// while 0b1000 will only set Z. fn set_cc(state: &mut EmulatorState, result: u16, flags: u8) { - if flags & 0b1000 > 0 { state.cc.z = (result & 0xff) == 0; } - if flags & 0b0100 > 0 { state.cc.s = (result & 0x80) > 0; } - if flags & 0b0010 > 0 { state.cc.c = result > 0xff; } - if flags & 0b0001 > 0 { state.cc.p = (result & 0xff).count_ones() % 2 == 0; } + if flags & 0b1000 > 0 { + state.cc.z = (result & 0xff) == 0; + } + if flags & 0b0100 > 0 { + state.cc.s = (result & 0x80) > 0; + } + if flags & 0b0010 > 0 { + state.cc.c = result > 0xff; + } + if flags & 0b0001 > 0 { + state.cc.p = (result & 0xff).count_ones() % 2 == 0; + } } /// Add values of `register` and `A` @@ -26,7 +34,8 @@ pub fn adi(byte: u8, state: &mut EmulatorState) { /// Add values of `register` and `A` and add +1 if carry bit is set pub fn adc(register: Register, state: &mut EmulatorState) { - let result = get_register(®ister, state) as u16 + state.a as u16 + if state.cc.c { 1 } else { 0 }; + let result = + get_register(®ister, state) as u16 + state.a as u16 + if state.cc.c { 1 } else { 0 }; set_cc(state, result, 0b1111); state.a = (result & 0xff) as u8; } @@ -41,9 +50,9 @@ pub fn aci(byte: u8, state: &mut EmulatorState) { /// Double precision add - Add B&C, D&E or H&L to H&L pub fn dad(register: Register, state: &mut EmulatorState) { let num = match register { - Register::B => u16::from_le_bytes([state.c, state.b]), - Register::D => u16::from_le_bytes([state.e, state.d]), - Register::H => u16::from_le_bytes([state.l, state.h]), + Register::B => u16::from_le_bytes([state.c, state.b]), + Register::D => u16::from_le_bytes([state.e, state.d]), + Register::H => u16::from_le_bytes([state.l, state.h]), Register::SP => state.sp, _ => panic!("Cannot perform DAD on register {:?}", register), }; diff --git a/src/emulator/main.rs b/src/emulator/main.rs index 837aece..c6699df 100644 --- a/src/emulator/main.rs +++ b/src/emulator/main.rs @@ -1,5 +1,5 @@ -use std::{fs, env}; use instructions::arithmetic; +use std::{env, fs}; use crate::structs::*; @@ -18,7 +18,12 @@ fn main() { h: 0, l: 0, sp: 0, - cc: ConditionCodes { z: true, s: true, p: true, c: true }, + cc: ConditionCodes { + z: true, + s: true, + p: true, + c: true, + }, pc: 0, ei: true, memory: [0; MEMORY_SIZE], @@ -55,7 +60,6 @@ fn tick(state: &mut EmulatorState) { 0x00 => {} // NOP /* Maths */ - // INR 0x04 => arithmetic::inr(Register::B, state), 0x0c => arithmetic::inr(Register::C, state), @@ -84,18 +88,22 @@ fn tick(state: &mut EmulatorState) { 0x80..=0x87 => arithmetic::add(register_from_num(instruction & 0xf), state), // ADD 0x88..=0x8f => arithmetic::adc(register_from_num(instruction & 0xf), state), // ADC - 0xc6 => arithmetic::adi(next_byte(), state), // ADI - 0xce => arithmetic::aci(next_byte(), state), // ACI - + 0xc6 => arithmetic::adi(next_byte(), state), // ADI + 0xce => arithmetic::aci(next_byte(), state), // ACI /* Special */ 0xfb => state.ei = true, // EI 0xf3 => state.ei = false, // DI - 0x76 => if state.ei { todo!() } else { // HLT - println!("HLT called after DI; exiting."); - print_state(state); - std::process::exit(0); - }, + 0x76 => { + if state.ei { + todo!() + } else { + // HLT + println!("HLT called after DI; exiting."); + print_state(state); + std::process::exit(0); + } + } _ => not_implemented(state), } @@ -105,5 +113,8 @@ fn tick(state: &mut EmulatorState) { fn not_implemented(state: &EmulatorState) { let instruction = state.memory[state.pc as usize]; - panic!("Unimplemented instruction {:#02X} at {:#04X}", instruction, state.pc); + panic!( + "Unimplemented instruction {:#02X} at {:#04X}", + instruction, state.pc + ); } diff --git a/src/emulator/structs.rs b/src/emulator/structs.rs index 5332ba3..7c94e2b 100644 --- a/src/emulator/structs.rs +++ b/src/emulator/structs.rs @@ -35,11 +35,16 @@ pub struct ConditionCodes { // ac: bool, } -#[derive(PartialEq)] -#[derive(Debug)] +#[derive(PartialEq, Debug)] pub enum Register { - B, C, D, E, - H, L, M, A, + B, + C, + D, + E, + H, + L, + M, + A, SP, } @@ -94,10 +99,15 @@ pub fn print_state(state: &EmulatorState) { // Registers println!("\nB\tC\tD\tE\tH\tL\tA"); - println!("{:#04x}\t{:#04x}\t{:#04x}\t{:#04x}\t{:#04x}\t{:#04x}\t{:#04x}", - state.b, state.c, state.d, state.e, state.h, state.l, state.a); + println!( + "{:#04x}\t{:#04x}\t{:#04x}\t{:#04x}\t{:#04x}\t{:#04x}\t{:#04x}", + state.b, state.c, state.d, state.e, state.h, state.l, state.a + ); // Flags println!("\nz\ts\tp\tc"); - println!("{}\t{}\t{}\t{}", state.cc.z, state.cc.s, state.cc.p, state.cc.c); + println!( + "{}\t{}\t{}\t{}", + state.cc.z, state.cc.s, state.cc.p, state.cc.c + ); }