invadeez/src/emulator/main.rs

132 lines
3.7 KiB
Rust

use instructions::arithmetic;
use std::{env, fs};
use crate::structs::*;
mod instructions;
mod structs;
pub const MEMORY_SIZE: usize = 8192;
fn main() {
let mut state = EmulatorState {
a: 0,
b: 0,
c: 0,
d: 0,
e: 0,
h: 0,
l: 0,
sp: 0,
cc: ConditionCodes {
z: true,
s: true,
p: true,
c: true,
},
pc: 0,
ei: true,
memory: [0; MEMORY_SIZE],
};
// Load the ROM into memory
let mut args = env::args();
let filename = args
.nth(1)
.expect("Provide a path to a ROM file to emulate as an argument");
let file = fs::read(filename).expect("where file");
let to_copy = MEMORY_SIZE.min(file.len());
state.memory[..to_copy].copy_from_slice(&file[..to_copy]);
while state.pc < MEMORY_SIZE as u16 {
tick(&mut state);
}
println!("Program counter reached end of memory; exiting");
print_state(&state);
}
fn tick(state: &mut EmulatorState) {
let instruction = state.memory[state.pc as usize];
let mut next_byte = || {
state.pc += 1;
state.memory[state.pc as usize]
};
match instruction {
0x00 => {} // NOP
/* Special */
0xfb => state.ei = true, // EI
0xf3 => state.ei = false, // DI
0x76 => {
// HLT
if state.ei {
todo!()
} else {
println!("HLT called after DI; exiting.");
print_state(state);
std::process::exit(0);
}
}
/* Maths */
// INR
0x04 => arithmetic::inr(Register::B, state),
0x0c => arithmetic::inr(Register::C, state),
0x14 => arithmetic::inr(Register::D, state),
0x1c => arithmetic::inr(Register::E, state),
0x24 => arithmetic::inr(Register::H, state),
0x2c => arithmetic::inr(Register::L, state),
0x34 => arithmetic::inr(Register::M, state),
0x3c => arithmetic::inr(Register::A, state),
// DCR
0x05 => arithmetic::dcr(Register::B, state),
0x0d => arithmetic::dcr(Register::C, state),
0x15 => arithmetic::dcr(Register::D, state),
0x1d => arithmetic::dcr(Register::E, state),
0x25 => arithmetic::dcr(Register::H, state),
0x2d => arithmetic::dcr(Register::L, state),
0x35 => arithmetic::dcr(Register::M, state),
0x3d => arithmetic::dcr(Register::A, state),
// DAD
0x09 => arithmetic::dad(Register::B, state),
0x19 => arithmetic::dad(Register::D, state),
0x29 => arithmetic::dad(Register::H, state),
0x39 => arithmetic::dad(Register::SP, state),
// INX
0x03 => arithmetic::inx(Register::B, state),
0x13 => arithmetic::inx(Register::D, state),
0x23 => arithmetic::inx(Register::H, state),
0x33 => arithmetic::inx(Register::SP, state),
// DCX
0x0b => arithmetic::dcx(Register::B, state),
0x1b => arithmetic::dcx(Register::D, state),
0x2b => arithmetic::dcx(Register::H, state),
0x3b => arithmetic::dcx(Register::SP, state),
0x80..=0x87 => arithmetic::add(register_from_num(instruction & 0xf), false, state), // ADD
0x88..=0x8f => arithmetic::add(register_from_num(instruction & 0xf), state.cc.c, state), // ADC
0xc6 => arithmetic::adi(next_byte(), false, state), // ADI
0xce => arithmetic::adi(next_byte(), state.cc.c, state), // ACI
_ => not_implemented(state),
}
state.pc += 1;
}
fn not_implemented(state: &EmulatorState) {
let instruction = state.memory[state.pc as usize];
panic!(
"Unimplemented instruction {:#02X} at {:#04X}",
instruction, state.pc
);
}