diff --git a/.gitignore b/.gitignore index 31d0241..ca6c073 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target /test-roms +/bootrom diff --git a/src/main.rs b/src/main.rs index b17b5a5..83ee317 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,10 @@ #![feature(exclusive_range_pattern)] use clap::Parser; -use std::fs; +use std::{ + fs, + io::{self, Read, Write}, +}; /// Simple program to greet a person #[derive(Parser, Debug)] @@ -10,13 +13,26 @@ struct Args { /// ROM path #[arg(short, long)] rom: String, + + /// BootROM path + #[arg(short, long)] + bootrom: String, } -type Register = u16; -type Instruction = u8; type Address = u16; type ROM = Vec; +#[derive(Clone, Copy)] +struct Inner { + left: u8, + right: u8, +} + +union Register { + as_u8s: Inner, + as_u16: u16, +} + struct Memory { rom: ROM, vram: [u8; 8192], @@ -48,7 +64,7 @@ impl Memory { return self.ram[(address - 0xC000) as usize]; } 0xE000..0xFE00 => { - panic!("ram mirror") + return self.ram[(address - 0xE000) as usize]; } 0xFE00..0xFEA0 => { panic!("sprite attrib memory"); @@ -72,7 +88,6 @@ impl Memory { } } -#[derive(Debug)] struct State { af: Register, bc: Register, @@ -86,12 +101,12 @@ impl Default for State { fn default() -> Self { // default post-bootrom values Self { - af: 0x01B0, - bc: 0x0013, - de: 0x00D8, - hl: 0x014D, - sp: 0xFFFE, - pc: 0x0100, + af: Register { as_u16: 0x01B0 }, + bc: Register { as_u16: 0x0013 }, + de: Register { as_u16: 0x00D8 }, + hl: Register { as_u16: 0x014D }, + sp: Register { as_u16: 0xFFFE }, + pc: Register { as_u16: 0x0100 }, } } } @@ -102,32 +117,53 @@ struct CPU { } impl CPU { - fn exec_next(&mut self) { + fn exec_next(&mut self) -> u8 { let opcode = self.next_opcode(); - let p1 = self.next_opcode(); - let p2 = self.next_opcode(); + println!("opcode: {:#X}", opcode); + match opcode { 0x0 => { // noop } 0x01 => { - self.state.bc = u8s_to_u16(&p1, &p2); + self.state.bc.as_u8s.left = self.next_opcode(); + self.state.bc.as_u8s.right = self.next_opcode(); + } + 0x11 => { + self.state.de.as_u8s.left = self.next_opcode(); + self.state.de.as_u8s.right = self.next_opcode(); + } + 0x21 => { + self.state.de.as_u8s.left = self.next_opcode(); + self.state.de.as_u8s.right = self.next_opcode(); + } + 0x2C => { + unsafe { + self.state.hl.as_u8s.right += 1; + }; } 0x66 => { - self.state.hl = u8s_to_u16(&self.memory.get(self.state.hl), &p2); + unsafe { + self.state.hl.as_u8s.left = self.memory.get(self.state.hl.as_u16); + }; } 0xC3 => { - self.state.pc = u8s_to_u16(&p1, &p2); + let (a, b) = (self.next_opcode(), self.next_opcode()); + self.state.pc.as_u8s.left = a; + self.state.pc.as_u8s.right = b; } _ => { panic!("unimplemented opcode: {:#X}", opcode); } }; + return opcode; } fn next_opcode(&mut self) -> u8 { - let opcode = self.memory.get(self.state.pc); - self.state.pc += 0x1; - return opcode; + unsafe { + let opcode = self.memory.get(self.state.pc.as_u16); + self.state.pc.as_u16 += 0x1; + return opcode; + }; } } @@ -135,21 +171,17 @@ fn main() { let args = Args::parse(); let rom: ROM = fs::read(args.rom).expect("Could not load ROM"); + let bootrom: ROM = fs::read(args.bootrom).expect("Could not load BootROM"); let mut cpu = CPU { memory: Memory::init(rom), state: State::default(), }; loop { cpu.exec_next(); + pause(); } } -fn u8s_to_u16(p1: &u8, p2: &u8) -> u16 { - ((*p1 as u16) << 8) | *p2 as u16 -} - -fn u16_to_u8s(p: &u16) -> (u8, u8) { - let p1 = *p as u8; - let p2 = (*p >> 8) as u8; - (p1, p2) +fn pause() { + io::stdin().read_line(&mut String::new()).unwrap(); }