diff --git a/src/emu.rs b/src/emu.rs index 138d885..bf6ae12 100644 --- a/src/emu.rs +++ b/src/emu.rs @@ -108,29 +108,35 @@ impl GameBoy { } } - fn op_ld(&mut self, dst: ValSrc, src: ValSrc, modifier: i8) { + fn op_ld(&mut self, dst: ValSrc, src: ValSrc, postOp: PostOp) { let pc = self.pc as usize; - let (val, src_adr) = match src { - ValSrc::Reg(i) => (self.reg[i as usize], i as usize), - ValSrc::Direct => (self.mem[pc + 1], 0), + let (src_ref, src_adr) = match src { + ValSrc::Reg(i) => (&mut self.reg[i as usize], i as usize), + ValSrc::Direct => (&mut self.mem[pc + 1], 0), ValSrc::Mem(ref src) => match src { AddrLoc::Reg(reg) => { let mem_loc = self.reg[*reg] as usize; - (self.mem[mem_loc], mem_loc) + (&mut self.mem[mem_loc], mem_loc) } AddrLoc::Direct => todo!(), } ValSrc::HMem(_) => todo!(), }; + let val = *src_ref; + let src_str = src.repr(src_adr, val); + let (dst_ref, dst_adr) = match dst { ValSrc::Mem(ref src) => match src { AddrLoc::Direct => { let adr = self.read16(pc) as usize; (&mut self.mem[adr], adr) } - _ => todo!(), + AddrLoc::Reg(reg) => { + let adr = self.reg[*reg] as usize; + (&mut self.mem[adr], adr) + } }, ValSrc::HMem(ref src) => match src { AddrLoc::Direct => { @@ -144,10 +150,16 @@ 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} + {modifier}"); - *dst_ref = (val as i16 + modifier as i16) as u8; + println!("ld {dst_str} <- {src_str}; post: {postOp:?}"); + + *dst_ref = val; + + match postOp { + PostOp::None => (), + PostOp::Inc(reg) => self.reg[reg] += 1, + PostOp::Dec(reg) => self.reg[reg] -= 1, + } } fn op_ld16(&mut self, dst: ValSrc, src: ValSrc) { @@ -280,14 +292,8 @@ impl GameBoy { self.reg[reg as usize] -= 1; println!("Dec Reg({reg:#04b})"); } - Ld(dst, src) => self.op_ld(dst, src, 0), + Ld(dst, src, postOp) => self.op_ld(dst, src, postOp), Ld16(dst, src) => self.op_ld16(dst, src), - LdInc(src) => { - self.op_ld(ValSrc::Reg(Register::A), src, 1) - } - LdDec(src) => { - self.op_ld(ValSrc::Reg(Register::A), src, -1) - } Bit(bit_op, src) => { let v = match src { ValSrc::Reg(r) => self.reg[r], @@ -302,10 +308,12 @@ impl GameBoy { ValSrc::Direct => self.mem[pc+1], _ => panic!("invalid command") }; + + let dst = &mut self.reg[Register::A]; match bit_op { - BitOp::Or => self.reg[Register::A] |= v, - BitOp::And => self.reg[Register::A] &= v, - BitOp::Xor => self.reg[Register::A] ^= v, + BitOp::Or => *dst |= v, + BitOp::And => *dst &= v, + BitOp::Xor => *dst ^= v, } println!("{bit_op:?} {src:?}"); } diff --git a/src/op.rs b/src/op.rs index 06e77f0..eef01aa 100644 --- a/src/op.rs +++ b/src/op.rs @@ -21,10 +21,8 @@ pub enum Instr { Pop(Register), // Load - Ld(ValSrc, ValSrc), + Ld(ValSrc, ValSrc, PostOp), Ld16(ValSrc, ValSrc), - LdInc(ValSrc), // loads into A - LdDec(ValSrc), // loads into A // Arith // TODO can we do Inc16/Inc8 with one via Register::WIDE @@ -42,6 +40,13 @@ pub enum Instr { Ret, } +#[derive(Debug)] +pub enum PostOp { + None, + Inc(Register), + Dec(Register) +} + #[derive(Debug)] pub enum AddrLoc { Reg(Register), @@ -58,20 +63,18 @@ pub enum ValSrc { #[derive(Debug, Copy, Clone, PartialEq)] pub enum Register { - A, - F, - B, - C, - D, - E, - H, - L, + A, F, + B, C, + D, E, + H, L, + // Double Width AF, BC, DE, HL, + // Misc SP, } @@ -196,10 +199,18 @@ impl TryFrom for Operation { 0b11_001_101 => (Call, 6, 3), 0b11_001_001 => (Ret, 4, 1), 0b11_110_011 => (Di, 1, 1), - 0b11_101_010 => (Ld(Mem(AddrLoc::Direct), Reg(A)), 4, 3), - 0b11_100_000 => (Ld(HMem(AddrLoc::Direct), Reg(A)), 3, 2), - 0b00_101_010 => (LdInc(Mem(AddrLoc::Reg(HL))), 2, 1), - 0b00_111_010 => (LdDec(Mem(AddrLoc::Reg(HL))), 2, 1), + 0b11_101_010 => + (Ld(Mem(AddrLoc::Direct), Reg(A), PostOp::None), 4, 3), + 0b11_100_000 => + (Ld(HMem(AddrLoc::Direct), Reg(A), PostOp::None), 3, 2), + 0b00_100_010 => + (Ld(Mem(AddrLoc::Reg(HL)), Reg(A), PostOp::Inc(HL)), 2, 1), + 0b00_101_010 => + (Ld(Reg(A), Mem(AddrLoc::Reg(HL)), PostOp::Inc(HL)), 2, 1), + 0b00_110_010 => + (Ld(Mem(AddrLoc::Reg(HL)), Reg(A), PostOp::Dec(HL)), 2, 1), + 0b00_111_010 => + (Ld(Reg(A), Mem(AddrLoc::Reg(HL)), PostOp::Dec(HL)), 2, 1), 0b10_110_110 => (Bit(Or, Mem(AddrLoc::Reg(HL))), 2, 1), 0b10_101_110 => (Bit(Xor, Mem(AddrLoc::Reg(HL))), 2, 1), 0b10_100_110 => (Bit(And, Mem(AddrLoc::Reg(HL))), 2, 1), @@ -229,12 +240,12 @@ impl TryFrom for Operation { } _ if (value & (HD_MSK | T2_MSK)) == 0b00_000_110 => { let reg = Register::try_from((value & T1_MSK) >> 3)?; - (Ld(Reg(reg), Direct), 2, 2) + (Ld(Reg(reg), Direct, PostOp::None), 2, 2) } _ if (value & HD_MSK) == 0b01_000_000 => { let dst = Register::try_from((value & T1_MSK) >> 3)?; let src = Register::try_from(value & T2_MSK)?; - (Ld(Reg(dst), Reg(src)), 1, 1) + (Ld(Reg(dst), Reg(src), PostOp::None), 1, 1) } _ if (value & (HD_MSK | 0b1_000 | T2_MSK)) == 0b00_000_001 => { let reg = match payload(value) {