diff --git a/src/emu.rs b/src/emu.rs index fac71dd..e39f5b1 100644 --- a/src/emu.rs +++ b/src/emu.rs @@ -108,13 +108,20 @@ impl GameBoy { } } - fn op_ld(&mut self, dst: Loc, src: Loc) { + fn op_ld(&mut self, dst: Loc, src: Loc, modifier: i8) { let pc = self.pc as usize; let (val, src_adr) = match src { Loc::Reg(i) => (self.reg[i as usize], i as usize), Loc::Val => (self.mem[pc + 1], 0), - Loc::Mem(_) => todo!(), + Loc::Mem(ref src) => match src { + AddrLoc::Reg(reg) => { + let mem_loc = self.reg[*reg] as usize; + (self.mem[mem_loc], mem_loc) + } + AddrLoc::Mem => todo!(), + AddrLoc::Val => todo!(), + } Loc::HMem(_) => todo!(), }; @@ -139,9 +146,9 @@ impl GameBoy { let dst_str = dst.repr(dst_adr, *dst_ref); let src_str = src.repr(src_adr, val); - println!("ld {dst_str} <- {src_str}"); + println!("ld {dst_str} <- {src_str} + {modifier}"); - *dst_ref = val; + *dst_ref = (val as i16 + modifier as i16) as u8; } fn op_ld16(&mut self, dst: Loc, src: Loc) { @@ -274,8 +281,31 @@ impl GameBoy { self.reg[reg as usize] -= 1; println!("Dec Reg({reg:#04b})"); } - Ld(dst, src) => self.op_ld(dst, src), + Ld(dst, src) => self.op_ld(dst, src, 0), Ld16(dst, src) => self.op_ld16(dst, src), + LdInc(src) => { + self.op_ld(Loc::Reg(Register::A), src, 1) + } + LdDec(src) => { + self.op_ld(Loc::Reg(Register::A), src, -1) + } + Or(src) => { + let v = match src { + Loc::Reg(r) => self.reg[r], + Loc::Mem(ref src) => { + let err_text = "Or Mem(Reg) only defined for register HR)"; + let AddrLoc::Reg(src) = src else { + panic!("Invalid op: {err_text}"); + }; + assert!(src == &Register::HL, "{err_text}"); + self.mem[self.reg[*src] as usize] + }, + Loc::Val => self.mem[pc+1], + _ => panic!("invalid command") + }; + self.reg[Register::A] |= v; + println!("Or {src:?}"); + } Di => println!("FIXME Di instruction not implemented"), } diff --git a/src/op.rs b/src/op.rs index cb3682c..be2d94c 100644 --- a/src/op.rs +++ b/src/op.rs @@ -23,11 +23,14 @@ pub enum Instr { // Load Ld(Loc, Loc), Ld16(Loc, Loc), + LdInc(Loc), // loads into A + LdDec(Loc), // loads into A // Arith // TODO can we do Inc16/Inc8 with one via Register::WIDE Inc(Register), Dec(Register), + Or(Loc), // TODO all bit can probably be done with this one // CPU ctl Di, @@ -47,14 +50,14 @@ pub enum AddrLoc { } #[derive(Debug)] -pub enum Loc { +pub enum Loc { // TODO this should probably be called ValSrc or similar Reg(Register), // direct Mem(AddrLoc), HMem(AddrLoc), - Val, + Val, // TODO and then this Direct } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq)] pub enum Register { A, F, @@ -187,6 +190,13 @@ impl TryFrom for Operation { 0b11_110_011 => (Di, 1, 1), 0b11_101_010 => (Ld(Mem(AddrLoc::Val), Reg(Register::A)), 4, 3), 0b11_100_000 => (Ld(HMem(AddrLoc::Val), Reg(Register::A)), 3, 2), + 0b00_101_010 => (LdInc(Mem(AddrLoc::Reg(Register::HL))), 2, 1), + 0b00_111_010 => (LdDec(Mem(AddrLoc::Reg(Register::HL))), 2, 1), + 0b10_110_110 => (Or(Mem(AddrLoc::Reg(Register::HL))), 2, 1), + 0b11_110_110 => (Or(Val), 2, 1), + _ if (value & (HD_MSK | T1_MSK) == 0b10_110_000) => { + (Or(Reg(Register::try_from(value & 0b111)?)), 1, 1) + } _ if (value & (HD_MSK | 0b1_000 | T2_MSK) == 0b00_000_011) => { (Inc(Register::from16_rep(payload(value))), 2, 1) }