use std::env; use crate::utils::{ BitIndex, get_bit, set_bit, join_bytes, add_half_carry, sub_half_carry, add_half_carry_16bit, }; use crate::bus::{Bus, INTERRUPT_ENABLE_ADDRESS, INTERRUPT_FLAG_ADDRESS}; #[derive(Debug, Copy, Clone)] pub enum Register { A, // Accumulator F, // Flags B, C, D, E, H, L, // This registers are just the same as above but combined to get a 16 bits register AF, BC, DE, HL, SP, // Stack pointer PC, // Program counter } type Rg = Register; impl Register { pub fn is_8bit(&self) -> bool { match self { Rg::A | Rg::F | Rg::B | Rg::C | Rg::D | Rg::E | Rg::H | Rg::L => true, Rg::AF | Rg::BC | Rg::DE | Rg::HL | Rg::SP | Rg::PC => false, } } pub fn is_16bit(&self) -> bool { !self.is_8bit() } } #[derive(Debug, Copy, Clone)] pub enum FlagRegister { Zero, // Set when the result of a math operation is zero or if two values matches using the CP instruction Substract, // Set if a substraction was performed in the last math instruction HalfCarry, // Set if a carry ocurred from the lower nibble in the last math operation Carry, // Set if a carry was ocurrend from the last math operation or if register A is the smaller value when executing the CP instruction } #[derive(Debug, Copy, Clone)] pub enum Interrupt { VBlank, LCDSTAT, Timer, Serial, Joypad, } impl Interrupt { fn get_bit_index(&self) -> BitIndex { match self { Interrupt::VBlank => BitIndex::I0, Interrupt::LCDSTAT => BitIndex::I1, Interrupt::Timer => BitIndex::I2, Interrupt::Serial => BitIndex::I3, Interrupt::Joypad => BitIndex::I4, } } pub fn get(&self, byte: u8) -> bool { get_bit(byte, self.get_bit_index()) } pub fn set(&self, byte: u8, val: bool) -> u8 { set_bit(byte, val, self.get_bit_index()) } pub fn get_vector(&self) -> u16 { match self { Interrupt::VBlank => 0x40, Interrupt::LCDSTAT => 0x48, Interrupt::Timer => 0x50, Interrupt::Serial => 0x58, Interrupt::Joypad => 0x60, } } } pub struct Registers { a: u8, f: u8, b: u8, c: u8, d: u8, e: u8, h: u8, l: u8, sp: u16, pc: u16, } impl Registers { pub fn new() -> Self { Self { a: 0x01, f: 0xB0, // The first 4 lower bits are always set to 0 b: 0x00, c: 0x13, d: 0x00, e: 0xD8, h: 0x01, l: 0x4D, sp: 0xFFFE, pc: 0x0100, // On power up, the Gameboy executes the instruction at hex 100 } } pub fn get(&self, register: Register) -> u16 { match register { Register::A => self.a as u16, Register::B => self.b as u16, Register::C => self.c as u16, Register::D => self.d as u16, Register::E => self.e as u16, Register::F => self.f as u16, Register::H => self.h as u16, Register::L => self.l as u16, Register::AF => join_bytes(self.a, self.f), Register::BC => join_bytes(self.b, self.c), Register::DE => join_bytes(self.d, self.e), Register::HL => join_bytes(self.h, self.l), Register::SP => self.sp, Register::PC => self.pc, } } pub fn get_8bit(&self, register: Register) -> u8 { self.get(register).to_be_bytes()[1] } pub fn set(&mut self, register: Register, val: u16) { let bytes = val.to_be_bytes(); match register { Register::A => self.a = bytes[1], Register::B => self.b = bytes[1], Register::C => self.c = bytes[1], Register::D => self.d = bytes[1], Register::E => self.e = bytes[1], Register::F => self.f = bytes[1], Register::H => self.h = bytes[1], Register::L => self.l = bytes[1], Register::AF => {self.a = bytes[0];self.f = bytes[1];}, Register::BC => {self.b = bytes[0];self.c = bytes[1];}, Register::DE => {self.d = bytes[0];self.e = bytes[1];}, Register::HL => {self.h = bytes[0];self.l = bytes[1];}, Register::SP => self.sp = val, Register::PC => self.pc = val, } } pub fn get_flag(&self, flag: FlagRegister) -> bool { match flag { FlagRegister::Zero => get_bit(self.f, BitIndex::I7), FlagRegister::Substract => get_bit(self.f, BitIndex::I6), FlagRegister::HalfCarry => get_bit(self.f, BitIndex::I5), FlagRegister::Carry => get_bit(self.f, BitIndex::I4), } } pub fn set_flag(&mut self, flag: FlagRegister, val: bool) { match flag { FlagRegister::Zero => self.f = set_bit(self.f, val, BitIndex::I7), FlagRegister::Substract => self.f = set_bit(self.f, val, BitIndex::I6), FlagRegister::HalfCarry => self.f = set_bit(self.f, val, BitIndex::I5), FlagRegister::Carry => self.f = set_bit(self.f, val, BitIndex::I4), } } pub fn increment(&mut self, register: Register, times: u16) { let val = self.get(register); self.set(register, val.wrapping_add(times)); } pub fn decrement(&mut self, register: Register, times: u16) { let val = self.get(register); self.set(register, val.wrapping_sub(times)); } } #[derive(Debug)] #[allow(non_camel_case_types)] pub enum OpcodeParameter { Register(Register), Register_U8(Register, u8), Register_U16(Register, u16), Register_I8(Register, i8), Register_I16(Register, u16), U8_Register(u8, Register), U16_Register(u16, Register), I8_Register(u8, Register), I16_Register(u16, Register), Register_16BitAddress(Register, u16), Register_Register(Register, Register), Register_RegisterDecrement(Register, Register), RegisterDecrement_Register(Register, Register), Register_RegisterIncrement(Register, Register), RegisterIncrement_Register(Register, Register), Register_FF00plusRegister(Register, Register), FF00plusRegister_Register(Register, Register), Register_FF00plusU8(Register, u8), FF00plusU8_Register(u8, Register), Register_RegisterPlusI8(Register, Register, i8), U8(u8), I8(i8), U16(u16), I16(i16), FlagRegisterReset(FlagRegister), FlagRegisterSet(FlagRegister), FlagRegisterReset_U16(FlagRegister, u16), FlagRegisterSet_U16(FlagRegister, u16), FlagRegisterReset_I16(FlagRegister, i16), FlagRegisterSet_I16(FlagRegister, i16), FlagRegisterReset_U8(FlagRegister, u8), FlagRegisterSet_U8(FlagRegister, u8), FlagRegisterReset_I8(FlagRegister, i8), FlagRegisterSet_I8(FlagRegister, i8), NoParam, } #[derive(Debug, Copy, Clone)] pub struct OpcodeParameterBytes(u8, u8, u8, u8); impl OpcodeParameterBytes { pub fn from_address(address: u16, bus: &Bus)-> OpcodeParameterBytes { OpcodeParameterBytes( bus.read(address), bus.read(address.wrapping_add(1)), bus.read(address.wrapping_add(2)), bus.read(address.wrapping_add(3)), ) } pub fn parse_opcode(&self) -> (Opcode, Cycles) { let opcode = self.0; let two_byte_param = join_bytes(self.2, self.1); match opcode { 0x06 => (Opcode::LD(OpcodeParameter::Register_U8(Register::B, self.1)), Cycles(1)), 0x0E => (Opcode::LD(OpcodeParameter::Register_U8(Register::C, self.1)), Cycles(3)), 0x16 => (Opcode::LD(OpcodeParameter::Register_U8(Register::D, self.1)), Cycles(2)), 0x1E => (Opcode::LD(OpcodeParameter::Register_U8(Register::E, self.1)), Cycles(2)), 0x26 => (Opcode::LD(OpcodeParameter::Register_U8(Register::H, self.1)), Cycles(2)), 0x2E => (Opcode::LD(OpcodeParameter::Register_U8(Register::L, self.1)), Cycles(2)), 0x7F => (Opcode::LD(OpcodeParameter::Register_Register(Register::A, Register::A)), Cycles(1)), 0x78 => (Opcode::LD(OpcodeParameter::Register_Register(Register::A, Register::B)), Cycles(1)), 0x79 => (Opcode::LD(OpcodeParameter::Register_Register(Register::A, Register::C)), Cycles(1)), 0x7A => (Opcode::LD(OpcodeParameter::Register_Register(Register::A, Register::D)), Cycles(1)), 0x7B => (Opcode::LD(OpcodeParameter::Register_Register(Register::A, Register::E)), Cycles(1)), 0x7C => (Opcode::LD(OpcodeParameter::Register_Register(Register::A, Register::H)), Cycles(1)), 0x7D => (Opcode::LD(OpcodeParameter::Register_Register(Register::A, Register::L)), Cycles(1)), 0x7E => (Opcode::LD(OpcodeParameter::Register_Register(Register::A, Register::HL)), Cycles(2)), 0x40 => (Opcode::LD(OpcodeParameter::Register_Register(Register::B, Register::B)), Cycles(1)), 0x41 => (Opcode::LD(OpcodeParameter::Register_Register(Register::B, Register::C)), Cycles(1)), 0x42 => (Opcode::LD(OpcodeParameter::Register_Register(Register::B, Register::D)), Cycles(1)), 0x43 => (Opcode::LD(OpcodeParameter::Register_Register(Register::B, Register::E)), Cycles(1)), 0x44 => (Opcode::LD(OpcodeParameter::Register_Register(Register::B, Register::H)), Cycles(1)), 0x45 => (Opcode::LD(OpcodeParameter::Register_Register(Register::B, Register::L)), Cycles(1)), 0x46 => (Opcode::LD(OpcodeParameter::Register_Register(Register::B, Register::HL)), Cycles(2)), 0x48 => (Opcode::LD(OpcodeParameter::Register_Register(Register::C, Register::B)), Cycles(1)), 0x49 => (Opcode::LD(OpcodeParameter::Register_Register(Register::C, Register::C)), Cycles(1)), 0x4A => (Opcode::LD(OpcodeParameter::Register_Register(Register::C, Register::D)), Cycles(1)), 0x4B => (Opcode::LD(OpcodeParameter::Register_Register(Register::C, Register::E)), Cycles(1)), 0x4C => (Opcode::LD(OpcodeParameter::Register_Register(Register::C, Register::H)), Cycles(1)), 0x4D => (Opcode::LD(OpcodeParameter::Register_Register(Register::C, Register::L)), Cycles(1)), 0x4E => (Opcode::LD(OpcodeParameter::Register_Register(Register::C, Register::HL)), Cycles(2)), 0x50 => (Opcode::LD(OpcodeParameter::Register_Register(Register::D, Register::B)), Cycles(1)), 0x51 => (Opcode::LD(OpcodeParameter::Register_Register(Register::D, Register::C)), Cycles(1)), 0x52 => (Opcode::LD(OpcodeParameter::Register_Register(Register::D, Register::D)), Cycles(1)), 0x53 => (Opcode::LD(OpcodeParameter::Register_Register(Register::D, Register::E)), Cycles(1)), 0x54 => (Opcode::LD(OpcodeParameter::Register_Register(Register::D, Register::H)), Cycles(1)), 0x55 => (Opcode::LD(OpcodeParameter::Register_Register(Register::D, Register::L)), Cycles(1)), 0x56 => (Opcode::LD(OpcodeParameter::Register_Register(Register::D, Register::HL)), Cycles(2)), 0x58 => (Opcode::LD(OpcodeParameter::Register_Register(Register::E, Register::B)), Cycles(1)), 0x59 => (Opcode::LD(OpcodeParameter::Register_Register(Register::E, Register::C)), Cycles(1)), 0x5A => (Opcode::LD(OpcodeParameter::Register_Register(Register::E, Register::D)), Cycles(1)), 0x5B => (Opcode::LD(OpcodeParameter::Register_Register(Register::E, Register::E)), Cycles(1)), 0x5C => (Opcode::LD(OpcodeParameter::Register_Register(Register::E, Register::H)), Cycles(1)), 0x5D => (Opcode::LD(OpcodeParameter::Register_Register(Register::E, Register::L)), Cycles(1)), 0x5E => (Opcode::LD(OpcodeParameter::Register_Register(Register::E, Register::HL)), Cycles(2)), 0x60 => (Opcode::LD(OpcodeParameter::Register_Register(Register::H, Register::B)), Cycles(1)), 0x61 => (Opcode::LD(OpcodeParameter::Register_Register(Register::H, Register::C)), Cycles(1)), 0x62 => (Opcode::LD(OpcodeParameter::Register_Register(Register::H, Register::D)), Cycles(1)), 0x63 => (Opcode::LD(OpcodeParameter::Register_Register(Register::H, Register::E)), Cycles(1)), 0x64 => (Opcode::LD(OpcodeParameter::Register_Register(Register::H, Register::H)), Cycles(1)), 0x65 => (Opcode::LD(OpcodeParameter::Register_Register(Register::H, Register::L)), Cycles(1)), 0x66 => (Opcode::LD(OpcodeParameter::Register_Register(Register::H, Register::HL)), Cycles(2)), 0x68 => (Opcode::LD(OpcodeParameter::Register_Register(Register::L, Register::B)), Cycles(1)), 0x69 => (Opcode::LD(OpcodeParameter::Register_Register(Register::L, Register::C)), Cycles(1)), 0x6A => (Opcode::LD(OpcodeParameter::Register_Register(Register::L, Register::D)), Cycles(1)), 0x6B => (Opcode::LD(OpcodeParameter::Register_Register(Register::L, Register::E)), Cycles(1)), 0x6C => (Opcode::LD(OpcodeParameter::Register_Register(Register::L, Register::H)), Cycles(1)), 0x6D => (Opcode::LD(OpcodeParameter::Register_Register(Register::L, Register::L)), Cycles(1)), 0x6E => (Opcode::LD(OpcodeParameter::Register_Register(Register::L, Register::HL)), Cycles(2)), 0x70 => (Opcode::LD(OpcodeParameter::Register_Register(Register::HL, Register::B)), Cycles(2)), 0x71 => (Opcode::LD(OpcodeParameter::Register_Register(Register::HL, Register::C)), Cycles(2)), 0x72 => (Opcode::LD(OpcodeParameter::Register_Register(Register::HL, Register::D)), Cycles(2)), 0x73 => (Opcode::LD(OpcodeParameter::Register_Register(Register::HL, Register::E)), Cycles(2)), 0x74 => (Opcode::LD(OpcodeParameter::Register_Register(Register::HL, Register::H)), Cycles(2)), 0x75 => (Opcode::LD(OpcodeParameter::Register_Register(Register::HL, Register::L)), Cycles(2)), 0x47 => (Opcode::LD(OpcodeParameter::Register_Register(Register::B, Register::A)), Cycles(1)), 0x4F => (Opcode::LD(OpcodeParameter::Register_Register(Register::C, Register::A)), Cycles(1)), 0x57 => (Opcode::LD(OpcodeParameter::Register_Register(Register::D, Register::A)), Cycles(1)), 0x5F => (Opcode::LD(OpcodeParameter::Register_Register(Register::E, Register::A)), Cycles(1)), 0x67 => (Opcode::LD(OpcodeParameter::Register_Register(Register::H, Register::A)), Cycles(1)), 0x6F => (Opcode::LD(OpcodeParameter::Register_Register(Register::L, Register::A)), Cycles(1)), 0x02 => (Opcode::LD(OpcodeParameter::Register_Register(Register::BC, Register::A)), Cycles(2)), 0x12 => (Opcode::LD(OpcodeParameter::Register_Register(Register::DE, Register::A)), Cycles(2)), 0x77 => (Opcode::LD(OpcodeParameter::Register_Register(Register::HL, Register::A)), Cycles(2)), 0x36 => (Opcode::LD(OpcodeParameter::Register_U8(Register::HL, self.1)), Cycles(3)), 0x0A => (Opcode::LD(OpcodeParameter::Register_Register(Register::A, Register::BC)), Cycles(2)), 0x1A => (Opcode::LD(OpcodeParameter::Register_Register(Register::A, Register::DE)), Cycles(2)), 0xFA => (Opcode::LD(OpcodeParameter::Register_U16(Register::A, two_byte_param)), Cycles(4)), 0x3E => (Opcode::LD(OpcodeParameter::Register_U8(Register::A, self.1)), Cycles(2)), 0xEA => (Opcode::LD(OpcodeParameter::U16_Register(two_byte_param, Register::A)), Cycles(4)), 0xF2 => (Opcode::LD(OpcodeParameter::Register_FF00plusRegister(Register::A, Register::C)), Cycles(2)), 0xE2 => (Opcode::LD(OpcodeParameter::FF00plusRegister_Register(Register::C, Register::A)), Cycles(2)), 0x3A => (Opcode::LDD(OpcodeParameter::Register_RegisterDecrement(Register::A, Register::HL)), Cycles(2)), 0x32 => (Opcode::LDD(OpcodeParameter::RegisterDecrement_Register(Register::HL, Register::A)), Cycles(2)), 0x2A => (Opcode::LDI(OpcodeParameter::Register_RegisterIncrement(Register::A, Register::HL)), Cycles(2)), 0x22 => (Opcode::LDI(OpcodeParameter::RegisterIncrement_Register(Register::HL, Register::A)), Cycles(2)), 0xE0 => (Opcode::LD(OpcodeParameter::FF00plusU8_Register(self.1, Register::A)), Cycles(3)), 0xF0 => (Opcode::LD(OpcodeParameter::Register_FF00plusU8(Register::A, self.1)), Cycles(3)), 0x01 => (Opcode::LD(OpcodeParameter::Register_U16(Register::BC, two_byte_param)), Cycles(3)), 0x11 => (Opcode::LD(OpcodeParameter::Register_U16(Register::DE, two_byte_param)), Cycles(3)), 0x21 => (Opcode::LD(OpcodeParameter::Register_U16(Register::HL, two_byte_param)), Cycles(3)), 0x31 => (Opcode::LD(OpcodeParameter::Register_U16(Register::SP, two_byte_param)), Cycles(3)), 0xF9 => (Opcode::LD(OpcodeParameter::Register_Register(Register::SP, Register::HL)), Cycles(2)), 0xF8 => (Opcode::LD(OpcodeParameter::Register_RegisterPlusI8(Register::HL, Register::SP, self.1 as i8)), Cycles(3)), 0x08 => (Opcode::LD(OpcodeParameter::U16_Register(two_byte_param, Register::SP)), Cycles(5)), 0xC5 => (Opcode::PUSH(Register::BC), Cycles(4)), 0xD5 => (Opcode::PUSH(Register::DE), Cycles(4)), 0xE5 => (Opcode::PUSH(Register::HL), Cycles(4)), 0xF5 => (Opcode::PUSH(Register::AF), Cycles(4)), 0xC1 => (Opcode::POP(Register::BC), Cycles(3)), 0xD1 => (Opcode::POP(Register::DE), Cycles(3)), 0xE1 => (Opcode::POP(Register::HL), Cycles(3)), 0xF1 => (Opcode::POP(Register::AF), Cycles(3)), 0x87 => (Opcode::ADD(OpcodeParameter::Register_Register(Register::A, Register::A)), Cycles(1)), 0x80 => (Opcode::ADD(OpcodeParameter::Register_Register(Register::A, Register::B)), Cycles(1)), 0x81 => (Opcode::ADD(OpcodeParameter::Register_Register(Register::A, Register::C)), Cycles(1)), 0x82 => (Opcode::ADD(OpcodeParameter::Register_Register(Register::A, Register::D)), Cycles(1)), 0x83 => (Opcode::ADD(OpcodeParameter::Register_Register(Register::A, Register::E)), Cycles(1)), 0x84 => (Opcode::ADD(OpcodeParameter::Register_Register(Register::A, Register::H)), Cycles(1)), 0x85 => (Opcode::ADD(OpcodeParameter::Register_Register(Register::A, Register::L)), Cycles(1)), 0x86 => (Opcode::ADD(OpcodeParameter::Register_Register(Register::A, Register::HL)), Cycles(2)), 0xC6 => (Opcode::ADD(OpcodeParameter::Register_U8(Register::A, self.1)), Cycles(2)), 0x09 => (Opcode::ADD(OpcodeParameter::Register_Register(Register::HL, Register::BC)), Cycles(2)), 0x19 => (Opcode::ADD(OpcodeParameter::Register_Register(Register::HL, Register::DE)), Cycles(2)), 0x29 => (Opcode::ADD(OpcodeParameter::Register_Register(Register::HL, Register::HL)), Cycles(2)), 0x39 => (Opcode::ADD(OpcodeParameter::Register_Register(Register::HL, Register::SP)), Cycles(2)), 0xE8 => (Opcode::ADD(OpcodeParameter::Register_I8(Register::SP, self.1 as i8)), Cycles(4)), 0x8F => (Opcode::ADC(OpcodeParameter::Register_Register(Register::A, Register::A)), Cycles(1)), 0x88 => (Opcode::ADC(OpcodeParameter::Register_Register(Register::A, Register::B)), Cycles(1)), 0x89 => (Opcode::ADC(OpcodeParameter::Register_Register(Register::A, Register::C)), Cycles(1)), 0x8A => (Opcode::ADC(OpcodeParameter::Register_Register(Register::A, Register::D)), Cycles(1)), 0x8B => (Opcode::ADC(OpcodeParameter::Register_Register(Register::A, Register::E)), Cycles(1)), 0x8C => (Opcode::ADC(OpcodeParameter::Register_Register(Register::A, Register::H)), Cycles(1)), 0x8D => (Opcode::ADC(OpcodeParameter::Register_Register(Register::A, Register::L)), Cycles(1)), 0x8E => (Opcode::ADC(OpcodeParameter::Register_Register(Register::A, Register::HL)), Cycles(2)), 0xCE => (Opcode::ADC(OpcodeParameter::Register_U8(Register::A, self.1)), Cycles(2)), 0x97 => (Opcode::SUB(OpcodeParameter::Register_Register(Register::A, Register::A)), Cycles(1)), 0x90 => (Opcode::SUB(OpcodeParameter::Register_Register(Register::A, Register::B)), Cycles(1)), 0x91 => (Opcode::SUB(OpcodeParameter::Register_Register(Register::A, Register::C)), Cycles(1)), 0x92 => (Opcode::SUB(OpcodeParameter::Register_Register(Register::A, Register::D)), Cycles(1)), 0x93 => (Opcode::SUB(OpcodeParameter::Register_Register(Register::A, Register::E)), Cycles(1)), 0x94 => (Opcode::SUB(OpcodeParameter::Register_Register(Register::A, Register::H)), Cycles(1)), 0x95 => (Opcode::SUB(OpcodeParameter::Register_Register(Register::A, Register::L)), Cycles(1)), 0x96 => (Opcode::SUB(OpcodeParameter::Register_Register(Register::A, Register::HL)), Cycles(2)), 0xD6 => (Opcode::SUB(OpcodeParameter::Register_U8(Register::A, self.1)), Cycles(2)), 0x9F => (Opcode::SBC(OpcodeParameter::Register_Register(Register::A, Register::A)), Cycles(1)), 0x98 => (Opcode::SBC(OpcodeParameter::Register_Register(Register::A, Register::B)), Cycles(1)), 0x99 => (Opcode::SBC(OpcodeParameter::Register_Register(Register::A, Register::C)), Cycles(1)), 0x9A => (Opcode::SBC(OpcodeParameter::Register_Register(Register::A, Register::D)), Cycles(1)), 0x9B => (Opcode::SBC(OpcodeParameter::Register_Register(Register::A, Register::E)), Cycles(1)), 0x9C => (Opcode::SBC(OpcodeParameter::Register_Register(Register::A, Register::H)), Cycles(1)), 0x9D => (Opcode::SBC(OpcodeParameter::Register_Register(Register::A, Register::L)), Cycles(1)), 0x9E => (Opcode::SBC(OpcodeParameter::Register_Register(Register::A, Register::HL)), Cycles(2)), 0xDE => (Opcode::SBC(OpcodeParameter::Register_U8(Register::A, self.1)), Cycles(2)), 0xA7 => (Opcode::AND(OpcodeParameter::Register_Register(Register::A, Register::A)), Cycles(1)), 0xA0 => (Opcode::AND(OpcodeParameter::Register_Register(Register::A, Register::B)), Cycles(1)), 0xA1 => (Opcode::AND(OpcodeParameter::Register_Register(Register::A, Register::C)), Cycles(1)), 0xA2 => (Opcode::AND(OpcodeParameter::Register_Register(Register::A, Register::D)), Cycles(1)), 0xA3 => (Opcode::AND(OpcodeParameter::Register_Register(Register::A, Register::E)), Cycles(1)), 0xA4 => (Opcode::AND(OpcodeParameter::Register_Register(Register::A, Register::H)), Cycles(1)), 0xA5 => (Opcode::AND(OpcodeParameter::Register_Register(Register::A, Register::L)), Cycles(1)), 0xA6 => (Opcode::AND(OpcodeParameter::Register_Register(Register::A, Register::HL)), Cycles(2)), 0xE6 => (Opcode::AND(OpcodeParameter::Register_U8(Register::A, self.1)), Cycles(2)), 0xB7 => (Opcode::OR(OpcodeParameter::Register_Register(Register::A, Register::A)), Cycles(1)), 0xB0 => (Opcode::OR(OpcodeParameter::Register_Register(Register::A, Register::B)), Cycles(1)), 0xB1 => (Opcode::OR(OpcodeParameter::Register_Register(Register::A, Register::C)), Cycles(1)), 0xB2 => (Opcode::OR(OpcodeParameter::Register_Register(Register::A, Register::D)), Cycles(1)), 0xB3 => (Opcode::OR(OpcodeParameter::Register_Register(Register::A, Register::E)), Cycles(1)), 0xB4 => (Opcode::OR(OpcodeParameter::Register_Register(Register::A, Register::H)), Cycles(1)), 0xB5 => (Opcode::OR(OpcodeParameter::Register_Register(Register::A, Register::L)), Cycles(1)), 0xB6 => (Opcode::OR(OpcodeParameter::Register_Register(Register::A, Register::HL)), Cycles(2)), 0xF6 => (Opcode::OR(OpcodeParameter::Register_U8(Register::A, self.1)), Cycles(2)), 0xAF => (Opcode::XOR(OpcodeParameter::Register_Register(Register::A, Register::A)), Cycles(1)), 0xA8 => (Opcode::XOR(OpcodeParameter::Register_Register(Register::A, Register::B)), Cycles(1)), 0xA9 => (Opcode::XOR(OpcodeParameter::Register_Register(Register::A, Register::C)), Cycles(1)), 0xAA => (Opcode::XOR(OpcodeParameter::Register_Register(Register::A, Register::D)), Cycles(1)), 0xAB => (Opcode::XOR(OpcodeParameter::Register_Register(Register::A, Register::E)), Cycles(1)), 0xAC => (Opcode::XOR(OpcodeParameter::Register_Register(Register::A, Register::H)), Cycles(1)), 0xAD => (Opcode::XOR(OpcodeParameter::Register_Register(Register::A, Register::L)), Cycles(1)), 0xAE => (Opcode::XOR(OpcodeParameter::Register_Register(Register::A, Register::HL)), Cycles(2)), 0xEE => (Opcode::XOR(OpcodeParameter::Register_U8(Register::A, self.1)), Cycles(2)), 0xBF => (Opcode::CP(OpcodeParameter::Register_Register(Register::A, Register::A)), Cycles(1)), 0xB8 => (Opcode::CP(OpcodeParameter::Register_Register(Register::A, Register::B)), Cycles(1)), 0xB9 => (Opcode::CP(OpcodeParameter::Register_Register(Register::A, Register::C)), Cycles(1)), 0xBA => (Opcode::CP(OpcodeParameter::Register_Register(Register::A, Register::D)), Cycles(1)), 0xBB => (Opcode::CP(OpcodeParameter::Register_Register(Register::A, Register::E)), Cycles(1)), 0xBC => (Opcode::CP(OpcodeParameter::Register_Register(Register::A, Register::H)), Cycles(1)), 0xBD => (Opcode::CP(OpcodeParameter::Register_Register(Register::A, Register::L)), Cycles(1)), 0xBE => (Opcode::CP(OpcodeParameter::Register_Register(Register::A, Register::HL)), Cycles(2)), 0xFE => (Opcode::CP(OpcodeParameter::Register_U8(Register::A, self.1)), Cycles(2)), 0x3C => (Opcode::INC(true, false, Register::A), Cycles(1)), 0x04 => (Opcode::INC(true, false, Register::B), Cycles(1)), 0x0C => (Opcode::INC(true, false, Register::C), Cycles(1)), 0x14 => (Opcode::INC(true, false, Register::D), Cycles(1)), 0x1C => (Opcode::INC(true, false, Register::E), Cycles(1)), 0x24 => (Opcode::INC(true, false, Register::H), Cycles(1)), 0x2C => (Opcode::INC(true, false, Register::L), Cycles(1)), 0x34 => (Opcode::INC(true, true, Register::HL), Cycles(3)), 0x03 => (Opcode::INC(false, false, Register::BC), Cycles(2)), 0x13 => (Opcode::INC(false, false, Register::DE), Cycles(2)), 0x23 => (Opcode::INC(false, false, Register::HL), Cycles(2)), 0x33 => (Opcode::INC(false, false, Register::SP), Cycles(2)), 0x3D => (Opcode::DEC(true, false, Register::A), Cycles(1)), 0x05 => (Opcode::DEC(true, false, Register::B), Cycles(1)), 0x0D => (Opcode::DEC(true, false, Register::C), Cycles(1)), 0x15 => (Opcode::DEC(true, false, Register::D), Cycles(1)), 0x1D => (Opcode::DEC(true, false, Register::E), Cycles(1)), 0x25 => (Opcode::DEC(true, false, Register::H), Cycles(1)), 0x2D => (Opcode::DEC(true, false, Register::L), Cycles(1)), 0x35 => (Opcode::DEC(true, true, Register::HL), Cycles(3)), 0x0B => (Opcode::DEC(false, false, Register::BC), Cycles(2)), 0x1B => (Opcode::DEC(false, false, Register::DE), Cycles(2)), 0x2B => (Opcode::DEC(false, false, Register::HL), Cycles(2)), 0x3B => (Opcode::DEC(false, false, Register::SP), Cycles(2)), 0x27 => (Opcode::DAA, Cycles(1)), 0x2F => (Opcode::CPL, Cycles(1)), 0x3F => (Opcode::CCF, Cycles(1)), 0x37 => (Opcode::SCF, Cycles(1)), 0x17 => (Opcode::RLA, Cycles(1)), 0x07 => (Opcode::RLCA, Cycles(1)), 0x0F => (Opcode::RRCA, Cycles(1)), 0x1F => (Opcode::RRA, Cycles(1)), 0xCB => match self.1 { 0x00 => (Opcode::PrefixCB(Box::new(Opcode::RLC(Register::B))), Cycles(2)), 0x01 => (Opcode::PrefixCB(Box::new(Opcode::RLC(Register::C))), Cycles(2)), 0x02 => (Opcode::PrefixCB(Box::new(Opcode::RLC(Register::D))), Cycles(2)), 0x03 => (Opcode::PrefixCB(Box::new(Opcode::RLC(Register::E))), Cycles(2)), 0x04 => (Opcode::PrefixCB(Box::new(Opcode::RLC(Register::H))), Cycles(2)), 0x05 => (Opcode::PrefixCB(Box::new(Opcode::RLC(Register::L))), Cycles(2)), 0x06 => (Opcode::PrefixCB(Box::new(Opcode::RLC(Register::HL))), Cycles(4)), 0x07 => (Opcode::PrefixCB(Box::new(Opcode::RLC(Register::A))), Cycles(2)), 0x08 => (Opcode::PrefixCB(Box::new(Opcode::RRC(Register::B))), Cycles(2)), 0x09 => (Opcode::PrefixCB(Box::new(Opcode::RRC(Register::C))), Cycles(2)), 0x0A => (Opcode::PrefixCB(Box::new(Opcode::RRC(Register::D))), Cycles(2)), 0x0B => (Opcode::PrefixCB(Box::new(Opcode::RRC(Register::E))), Cycles(2)), 0x0C => (Opcode::PrefixCB(Box::new(Opcode::RRC(Register::H))), Cycles(2)), 0x0D => (Opcode::PrefixCB(Box::new(Opcode::RRC(Register::L))), Cycles(2)), 0x0E => (Opcode::PrefixCB(Box::new(Opcode::RRC(Register::HL))), Cycles(4)), 0x0F => (Opcode::PrefixCB(Box::new(Opcode::RRC(Register::A))), Cycles(2)), 0x10 => (Opcode::PrefixCB(Box::new(Opcode::RL(Register::B))), Cycles(2)), 0x11 => (Opcode::PrefixCB(Box::new(Opcode::RL(Register::C))), Cycles(2)), 0x12 => (Opcode::PrefixCB(Box::new(Opcode::RL(Register::D))), Cycles(2)), 0x13 => (Opcode::PrefixCB(Box::new(Opcode::RL(Register::E))), Cycles(2)), 0x14 => (Opcode::PrefixCB(Box::new(Opcode::RL(Register::H))), Cycles(2)), 0x15 => (Opcode::PrefixCB(Box::new(Opcode::RL(Register::L))), Cycles(2)), 0x16 => (Opcode::PrefixCB(Box::new(Opcode::RL(Register::HL))), Cycles(4)), 0x17 => (Opcode::PrefixCB(Box::new(Opcode::RL(Register::A))), Cycles(2)), 0x18 => (Opcode::PrefixCB(Box::new(Opcode::RR(Register::B))), Cycles(2)), 0x19 => (Opcode::PrefixCB(Box::new(Opcode::RR(Register::C))), Cycles(2)), 0x1A => (Opcode::PrefixCB(Box::new(Opcode::RR(Register::D))), Cycles(2)), 0x1B => (Opcode::PrefixCB(Box::new(Opcode::RR(Register::E))), Cycles(2)), 0x1C => (Opcode::PrefixCB(Box::new(Opcode::RR(Register::H))), Cycles(2)), 0x1D => (Opcode::PrefixCB(Box::new(Opcode::RR(Register::L))), Cycles(2)), 0x1E => (Opcode::PrefixCB(Box::new(Opcode::RR(Register::HL))), Cycles(2)), 0x1F => (Opcode::PrefixCB(Box::new(Opcode::RR(Register::A))), Cycles(2)), 0x20 => (Opcode::PrefixCB(Box::new(Opcode::SLA(Register::B))), Cycles(2)), 0x21 => (Opcode::PrefixCB(Box::new(Opcode::SLA(Register::C))), Cycles(2)), 0x22 => (Opcode::PrefixCB(Box::new(Opcode::SLA(Register::D))), Cycles(2)), 0x23 => (Opcode::PrefixCB(Box::new(Opcode::SLA(Register::E))), Cycles(2)), 0x24 => (Opcode::PrefixCB(Box::new(Opcode::SLA(Register::H))), Cycles(2)), 0x25 => (Opcode::PrefixCB(Box::new(Opcode::SLA(Register::L))), Cycles(2)), 0x26 => (Opcode::PrefixCB(Box::new(Opcode::SLA(Register::HL))), Cycles(4)), 0x27 => (Opcode::PrefixCB(Box::new(Opcode::SLA(Register::A))), Cycles(2)), 0x28 => (Opcode::PrefixCB(Box::new(Opcode::SRA(Register::B))), Cycles(2)), 0x29 => (Opcode::PrefixCB(Box::new(Opcode::SRA(Register::C))), Cycles(2)), 0x2A => (Opcode::PrefixCB(Box::new(Opcode::SRA(Register::D))), Cycles(2)), 0x2B => (Opcode::PrefixCB(Box::new(Opcode::SRA(Register::E))), Cycles(2)), 0x2C => (Opcode::PrefixCB(Box::new(Opcode::SRA(Register::H))), Cycles(2)), 0x2D => (Opcode::PrefixCB(Box::new(Opcode::SRA(Register::L))), Cycles(2)), 0x2E => (Opcode::PrefixCB(Box::new(Opcode::SRA(Register::HL))), Cycles(4)), 0x2F => (Opcode::PrefixCB(Box::new(Opcode::SRA(Register::A))), Cycles(2)), 0x30 => (Opcode::PrefixCB(Box::new(Opcode::SWAP(Register::B))), Cycles(2)), 0x31 => (Opcode::PrefixCB(Box::new(Opcode::SWAP(Register::C))), Cycles(2)), 0x32 => (Opcode::PrefixCB(Box::new(Opcode::SWAP(Register::D))), Cycles(2)), 0x33 => (Opcode::PrefixCB(Box::new(Opcode::SWAP(Register::E))), Cycles(2)), 0x34 => (Opcode::PrefixCB(Box::new(Opcode::SWAP(Register::H))), Cycles(2)), 0x35 => (Opcode::PrefixCB(Box::new(Opcode::SWAP(Register::L))), Cycles(2)), 0x36 => (Opcode::PrefixCB(Box::new(Opcode::SWAP(Register::HL))), Cycles(4)), 0x37 => (Opcode::PrefixCB(Box::new(Opcode::SWAP(Register::A))), Cycles(2)), 0x38 => (Opcode::PrefixCB(Box::new(Opcode::SRL(Register::B))), Cycles(2)), 0x39 => (Opcode::PrefixCB(Box::new(Opcode::SRL(Register::C))), Cycles(2)), 0x3A => (Opcode::PrefixCB(Box::new(Opcode::SRL(Register::D))), Cycles(2)), 0x3B => (Opcode::PrefixCB(Box::new(Opcode::SRL(Register::E))), Cycles(2)), 0x3C => (Opcode::PrefixCB(Box::new(Opcode::SRL(Register::H))), Cycles(2)), 0x3D => (Opcode::PrefixCB(Box::new(Opcode::SRL(Register::L))), Cycles(2)), 0x3E => (Opcode::PrefixCB(Box::new(Opcode::SRL(Register::HL))), Cycles(4)), 0x3F => (Opcode::PrefixCB(Box::new(Opcode::SRL(Register::A))), Cycles(2)), 0x40 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I0, Register::B))), Cycles(2)), 0x41 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I0, Register::C))), Cycles(2)), 0x42 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I0, Register::D))), Cycles(2)), 0x43 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I0, Register::E))), Cycles(2)), 0x44 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I0, Register::H))), Cycles(2)), 0x45 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I0, Register::L))), Cycles(2)), 0x46 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I0, Register::HL))), Cycles(3)), 0x47 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I0, Register::A))), Cycles(2)), 0x48 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I1, Register::B))), Cycles(2)), 0x49 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I1, Register::C))), Cycles(2)), 0x4A => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I1, Register::D))), Cycles(2)), 0x4B => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I1, Register::E))), Cycles(2)), 0x4C => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I1, Register::H))), Cycles(2)), 0x4D => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I1, Register::L))), Cycles(2)), 0x4E => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I1, Register::HL))), Cycles(3)), 0x4F => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I1, Register::A))), Cycles(2)), 0x50 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I2, Register::B))), Cycles(2)), 0x51 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I2, Register::C))), Cycles(2)), 0x52 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I2, Register::D))), Cycles(2)), 0x53 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I2, Register::E))), Cycles(2)), 0x54 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I2, Register::H))), Cycles(2)), 0x55 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I2, Register::L))), Cycles(2)), 0x56 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I2, Register::HL))), Cycles(3)), 0x57 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I2, Register::A))), Cycles(2)), 0x58 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I3, Register::B))), Cycles(2)), 0x59 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I3, Register::C))), Cycles(2)), 0x5A => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I3, Register::D))), Cycles(2)), 0x5B => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I3, Register::E))), Cycles(2)), 0x5C => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I3, Register::H))), Cycles(2)), 0x5D => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I3, Register::L))), Cycles(2)), 0x5E => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I3, Register::HL))), Cycles(3)), 0x5F => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I3, Register::A))), Cycles(2)), 0x60 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I4, Register::B))), Cycles(2)), 0x61 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I4, Register::C))), Cycles(2)), 0x62 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I4, Register::D))), Cycles(2)), 0x63 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I4, Register::E))), Cycles(2)), 0x64 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I4, Register::H))), Cycles(2)), 0x65 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I4, Register::L))), Cycles(2)), 0x66 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I4, Register::HL))), Cycles(3)), 0x67 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I4, Register::A))), Cycles(2)), 0x68 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I5, Register::B))), Cycles(2)), 0x69 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I5, Register::C))), Cycles(2)), 0x6A => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I5, Register::D))), Cycles(2)), 0x6B => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I5, Register::E))), Cycles(2)), 0x6C => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I5, Register::H))), Cycles(2)), 0x6D => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I5, Register::L))), Cycles(2)), 0x6E => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I5, Register::HL))), Cycles(3)), 0x6F => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I5, Register::A))), Cycles(2)), 0x70 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I6, Register::B))), Cycles(2)), 0x71 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I6, Register::C))), Cycles(2)), 0x72 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I6, Register::D))), Cycles(2)), 0x73 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I6, Register::E))), Cycles(2)), 0x74 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I6, Register::H))), Cycles(2)), 0x75 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I6, Register::L))), Cycles(2)), 0x76 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I6, Register::HL))), Cycles(3)), 0x77 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I6, Register::A))), Cycles(2)), 0x78 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I7, Register::B))), Cycles(2)), 0x79 => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I7, Register::C))), Cycles(2)), 0x7A => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I7, Register::D))), Cycles(2)), 0x7B => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I7, Register::E))), Cycles(2)), 0x7C => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I7, Register::H))), Cycles(2)), 0x7D => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I7, Register::L))), Cycles(2)), 0x7E => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I7, Register::HL))), Cycles(3)), 0x7F => (Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I7, Register::A))), Cycles(2)), 0x80 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I0, Register::B))), Cycles(2)), 0x81 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I0, Register::C))), Cycles(2)), 0x82 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I0, Register::D))), Cycles(2)), 0x83 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I0, Register::E))), Cycles(2)), 0x84 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I0, Register::H))), Cycles(2)), 0x85 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I0, Register::L))), Cycles(2)), 0x86 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I0, Register::HL))), Cycles(4)), 0x87 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I0, Register::A))), Cycles(2)), 0x88 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I1, Register::B))), Cycles(2)), 0x89 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I1, Register::C))), Cycles(2)), 0x8A => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I1, Register::D))), Cycles(2)), 0x8B => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I1, Register::E))), Cycles(2)), 0x8C => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I1, Register::H))), Cycles(2)), 0x8D => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I1, Register::L))), Cycles(2)), 0x8E => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I1, Register::HL))), Cycles(4)), 0x8F => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I1, Register::A))), Cycles(2)), 0x90 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I2, Register::B))), Cycles(2)), 0x91 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I2, Register::C))), Cycles(2)), 0x92 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I2, Register::D))), Cycles(2)), 0x93 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I2, Register::E))), Cycles(2)), 0x94 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I2, Register::H))), Cycles(2)), 0x95 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I2, Register::L))), Cycles(2)), 0x96 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I2, Register::HL))), Cycles(4)), 0x97 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I2, Register::A))), Cycles(2)), 0x98 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I3, Register::B))), Cycles(2)), 0x99 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I3, Register::C))), Cycles(2)), 0x9A => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I3, Register::D))), Cycles(2)), 0x9B => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I3, Register::E))), Cycles(2)), 0x9C => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I3, Register::H))), Cycles(2)), 0x9D => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I3, Register::L))), Cycles(2)), 0x9E => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I3, Register::HL))), Cycles(4)), 0x9F => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I3, Register::A))), Cycles(2)), 0xA0 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I4, Register::B))), Cycles(2)), 0xA1 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I4, Register::C))), Cycles(2)), 0xA2 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I4, Register::D))), Cycles(2)), 0xA3 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I4, Register::E))), Cycles(2)), 0xA4 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I4, Register::H))), Cycles(2)), 0xA5 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I4, Register::L))), Cycles(2)), 0xA6 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I4, Register::HL))), Cycles(4)), 0xA7 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I4, Register::A))), Cycles(2)), 0xA8 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I5, Register::B))), Cycles(2)), 0xA9 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I5, Register::C))), Cycles(2)), 0xAA => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I5, Register::D))), Cycles(2)), 0xAB => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I5, Register::E))), Cycles(2)), 0xAC => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I5, Register::H))), Cycles(2)), 0xAD => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I5, Register::L))), Cycles(2)), 0xAE => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I5, Register::HL))), Cycles(4)), 0xAF => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I5, Register::A))), Cycles(2)), 0xB0 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I6, Register::B))), Cycles(2)), 0xB1 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I6, Register::C))), Cycles(2)), 0xB2 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I6, Register::D))), Cycles(2)), 0xB3 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I6, Register::E))), Cycles(2)), 0xB4 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I6, Register::H))), Cycles(2)), 0xB5 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I6, Register::L))), Cycles(2)), 0xB6 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I6, Register::HL))), Cycles(4)), 0xB7 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I6, Register::A))), Cycles(2)), 0xB8 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I7, Register::B))), Cycles(2)), 0xB9 => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I7, Register::C))), Cycles(2)), 0xBA => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I7, Register::D))), Cycles(2)), 0xBB => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I7, Register::E))), Cycles(2)), 0xBC => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I7, Register::H))), Cycles(2)), 0xBD => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I7, Register::L))), Cycles(2)), 0xBE => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I7, Register::HL))), Cycles(4)), 0xBF => (Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I7, Register::A))), Cycles(2)), 0xC0 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I0, Register::B))), Cycles(2)), 0xC1 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I0, Register::C))), Cycles(2)), 0xC2 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I0, Register::D))), Cycles(2)), 0xC3 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I0, Register::E))), Cycles(2)), 0xC4 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I0, Register::H))), Cycles(2)), 0xC5 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I0, Register::L))), Cycles(2)), 0xC6 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I0, Register::HL))), Cycles(4)), 0xC7 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I0, Register::A))), Cycles(2)), 0xC8 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I1, Register::B))), Cycles(2)), 0xC9 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I1, Register::C))), Cycles(2)), 0xCA => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I1, Register::D))), Cycles(2)), 0xCB => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I1, Register::E))), Cycles(2)), 0xCC => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I1, Register::H))), Cycles(2)), 0xCD => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I1, Register::L))), Cycles(2)), 0xCE => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I1, Register::HL))), Cycles(4)), 0xCF => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I1, Register::A))), Cycles(2)), 0xD0 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I2, Register::B))), Cycles(2)), 0xD1 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I2, Register::C))), Cycles(2)), 0xD2 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I2, Register::D))), Cycles(2)), 0xD3 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I2, Register::E))), Cycles(2)), 0xD4 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I2, Register::H))), Cycles(2)), 0xD5 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I2, Register::L))), Cycles(2)), 0xD6 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I2, Register::HL))), Cycles(4)), 0xD7 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I2, Register::A))), Cycles(2)), 0xD8 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I3, Register::B))), Cycles(2)), 0xD9 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I3, Register::C))), Cycles(2)), 0xDA => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I3, Register::D))), Cycles(2)), 0xDB => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I3, Register::E))), Cycles(2)), 0xDC => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I3, Register::H))), Cycles(2)), 0xDD => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I3, Register::L))), Cycles(2)), 0xDE => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I3, Register::HL))), Cycles(4)), 0xDF => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I3, Register::A))), Cycles(2)), 0xE0 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I4, Register::B))), Cycles(2)), 0xE1 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I4, Register::C))), Cycles(2)), 0xE2 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I4, Register::D))), Cycles(2)), 0xE3 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I4, Register::E))), Cycles(2)), 0xE4 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I4, Register::H))), Cycles(2)), 0xE5 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I4, Register::L))), Cycles(2)), 0xE6 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I4, Register::HL))), Cycles(4)), 0xE7 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I4, Register::A))), Cycles(2)), 0xE8 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I5, Register::B))), Cycles(2)), 0xE9 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I5, Register::C))), Cycles(2)), 0xEA => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I5, Register::D))), Cycles(2)), 0xEB => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I5, Register::E))), Cycles(2)), 0xEC => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I5, Register::H))), Cycles(2)), 0xED => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I5, Register::L))), Cycles(2)), 0xEE => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I5, Register::HL))), Cycles(4)), 0xEF => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I5, Register::A))), Cycles(2)), 0xF0 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I6, Register::B))), Cycles(2)), 0xF1 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I6, Register::C))), Cycles(2)), 0xF2 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I6, Register::D))), Cycles(2)), 0xF3 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I6, Register::E))), Cycles(2)), 0xF4 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I6, Register::H))), Cycles(2)), 0xF5 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I6, Register::L))), Cycles(2)), 0xF6 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I6, Register::HL))), Cycles(4)), 0xF7 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I6, Register::A))), Cycles(2)), 0xF8 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I7, Register::B))), Cycles(2)), 0xF9 => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I7, Register::C))), Cycles(2)), 0xFA => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I7, Register::D))), Cycles(2)), 0xFB => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I7, Register::E))), Cycles(2)), 0xFC => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I7, Register::H))), Cycles(2)), 0xFD => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I7, Register::L))), Cycles(2)), 0xFE => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I7, Register::HL))), Cycles(4)), 0xFF => (Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I7, Register::A))), Cycles(2)), }, 0xC3 => (Opcode::JP(OpcodeParameter::U16(two_byte_param)), Cycles(4)), 0xC2 => (Opcode::JP(OpcodeParameter::FlagRegisterReset_U16(FlagRegister::Zero, two_byte_param)), Cycles(3)), 0xCA => (Opcode::JP(OpcodeParameter::FlagRegisterSet_U16(FlagRegister::Zero, two_byte_param)), Cycles(3)), 0xD2 => (Opcode::JP(OpcodeParameter::FlagRegisterReset_U16(FlagRegister::Carry, two_byte_param)), Cycles(3)), 0xDA => (Opcode::JP(OpcodeParameter::FlagRegisterSet_U16(FlagRegister::Carry, two_byte_param)), Cycles(3)), 0xE9 => (Opcode::JP(OpcodeParameter::Register(Register::HL)), Cycles(1)), 0x18 => (Opcode::JR(OpcodeParameter::I8(self.1 as i8)), Cycles(3)), 0x20 => (Opcode::JR(OpcodeParameter::FlagRegisterReset_I8(FlagRegister::Zero, self.1 as i8)), Cycles(2)), 0x28 => (Opcode::JR(OpcodeParameter::FlagRegisterSet_I8(FlagRegister::Zero, self.1 as i8)), Cycles(2)), 0x30 => (Opcode::JR(OpcodeParameter::FlagRegisterReset_I8(FlagRegister::Carry, self.1 as i8)), Cycles(2)), 0x38 => (Opcode::JR(OpcodeParameter::FlagRegisterSet_I8(FlagRegister::Carry, self.1 as i8)), Cycles(2)), 0xCD => (Opcode::CALL(OpcodeParameter::U16(two_byte_param)), Cycles(6)), 0xC4 => (Opcode::CALL(OpcodeParameter::FlagRegisterReset_U16(FlagRegister::Zero, two_byte_param)), Cycles(3)), 0xCC => (Opcode::CALL(OpcodeParameter::FlagRegisterSet_U16(FlagRegister::Zero, two_byte_param)), Cycles(3)), 0xD4 => (Opcode::CALL(OpcodeParameter::FlagRegisterReset_U16(FlagRegister::Carry, two_byte_param)), Cycles(3)), 0xDC => (Opcode::CALL(OpcodeParameter::FlagRegisterSet_U16(FlagRegister::Carry, two_byte_param)), Cycles(3)), 0xC7 => (Opcode::RST(0x00), Cycles(4)), 0xCF => (Opcode::RST(0x08), Cycles(4)), 0xD7 => (Opcode::RST(0x10), Cycles(4)), 0xDF => (Opcode::RST(0x18), Cycles(4)), 0xE7 => (Opcode::RST(0x20), Cycles(4)), 0xEF => (Opcode::RST(0x28), Cycles(4)), 0xF7 => (Opcode::RST(0x30), Cycles(4)), 0xFF => (Opcode::RST(0x38), Cycles(4)), 0xC9 => (Opcode::RET(OpcodeParameter::NoParam), Cycles(4)), 0xC0 => (Opcode::RET(OpcodeParameter::FlagRegisterReset(FlagRegister::Zero)), Cycles(2)), 0xC8 => (Opcode::RET(OpcodeParameter::FlagRegisterSet(FlagRegister::Zero)), Cycles(2)), 0xD0 => (Opcode::RET(OpcodeParameter::FlagRegisterReset(FlagRegister::Carry)), Cycles(2)), 0xD8 => (Opcode::RET(OpcodeParameter::FlagRegisterSet(FlagRegister::Carry)), Cycles(2)), 0xD9 => (Opcode::RETI, Cycles(4)), 0xF3 => (Opcode::DI, Cycles(1)), 0xFB => (Opcode::EI, Cycles(1)), 0x76 => (Opcode::HALT, Cycles(1)), 0x10 => (Opcode::STOP, Cycles(1)), 0x00 => (Opcode::NOP, Cycles(1)), _ => (Opcode::IllegalInstruction, Cycles(1)), } } } #[derive(Debug)] pub enum Opcode { LD(OpcodeParameter), LDD(OpcodeParameter), LDI(OpcodeParameter), LDHL(OpcodeParameter), PUSH(Register), POP(Register), ADD(OpcodeParameter), ADC(OpcodeParameter), SUB(OpcodeParameter), SBC(OpcodeParameter), AND(OpcodeParameter), OR(OpcodeParameter), XOR(OpcodeParameter), CP(OpcodeParameter), INC(bool, bool, Register), DEC(bool, bool, Register), DAA, CPL, CCF, SCF, NOP, HALT, STOP, DI, EI, RLCA, RLA, RRCA, RRA, SWAP(Register), RLC(Register), RL(Register), RRC(Register), RR(Register), SLA(Register), SRA(Register), SRL(Register), BIT(BitIndex, Register), SET(BitIndex, Register), RES(BitIndex, Register), JP(OpcodeParameter), JR(OpcodeParameter), CALL(OpcodeParameter), RST(u8), RET(OpcodeParameter), RETI, PrefixCB(Box), IllegalInstruction, } // Store cycles in M #[derive(Debug, Copy, Clone)] pub struct Cycles(pub usize); impl Cycles { pub fn to_t(&self) -> Self { Self(self.0 * 4) } } pub struct CPU { registers: Registers, cycles: Cycles, last_op_cycles: Cycles, exec_calls_count: usize, is_halted: bool, ime: bool, // Interrupt Master Enable ei_delay: bool, enable_logs: bool, } impl CPU { pub fn new() -> Self { Self { registers: Registers::new(), cycles: Cycles(0), last_op_cycles: Cycles(0), exec_calls_count: 0, is_halted: false, ei_delay: false, ime: true, enable_logs: !env::var("CPU_LOG").is_err() || !env::var("CPU_LOGS").is_err(), } } pub fn get_exec_calls_count(&self) -> usize { self.exec_calls_count } fn increment_exec_calls_count(&mut self) { self.exec_calls_count += 1; } fn increment_cycles(&mut self, cycles: Cycles) { self.cycles.0 += cycles.0; } pub fn reset_cycles(&mut self) { self.cycles = Cycles(0); } pub fn get_cycles(&mut self) -> Cycles { self.cycles } pub fn set_last_op_cycles(&mut self, cycles_start: Cycles, cycles_end: Cycles) { self.last_op_cycles = Cycles(cycles_end.0 - cycles_start.0); } pub fn get_last_op_cycles(&self) -> Cycles { self.last_op_cycles } fn log(&self, parameter_bytes: OpcodeParameterBytes) { println!("A: {:02X} F: {:02X} B: {:02X} C: {:02X} D: {:02X} E: {:02X} H: {:02X} L: {:02X} SP: {:04X} PC: 00:{:04X} ({:02X} {:02X} {:02X} {:02X})", self.registers.get(Register::A), self.registers.get(Register::F), self.registers.get(Register::B), self.registers.get(Register::C), self.registers.get(Register::D), self.registers.get(Register::E), self.registers.get(Register::H), self.registers.get(Register::L), self.registers.get(Register::SP), self.registers.get(Register::PC), parameter_bytes.0, parameter_bytes.1, parameter_bytes.2, parameter_bytes.3, ); } pub fn handle_interrupt(&mut self, bus: &mut Bus, interrupt: Interrupt) { // println!("Interrupt: {:?}", interrupt); bus.set_interrupt_flag(interrupt, false); self.ime = false; self.registers.decrement(Register::PC, 3); self.exec(Opcode::CALL(OpcodeParameter::U16(interrupt.get_vector())), bus); } pub fn check_interrupts(&mut self, bus: &mut Bus) -> Option { let interrupts = (bus.read(INTERRUPT_ENABLE_ADDRESS) & 0b00011111) & (bus.read(INTERRUPT_FLAG_ADDRESS) & 0b00011111); if interrupts != 0 { self.is_halted = false; } if !self.ime { return None; } if Interrupt::VBlank.get(interrupts) { return Some(Interrupt::VBlank); } else if Interrupt::LCDSTAT.get(interrupts) { return Some(Interrupt::LCDSTAT); } else if Interrupt::Timer.get(interrupts) { return Some(Interrupt::Timer); } else if Interrupt::Serial.get(interrupts) { return Some(Interrupt::Serial); } else if Interrupt::Joypad.get(interrupts) { return Some(Interrupt::Joypad); } None } pub fn ei_delay(&mut self, bus: &mut Bus) { if self.ei_delay && !self.ime { self.ei_delay = false; self.run(bus); self.ime = true; } } pub fn run(&mut self, bus: &mut Bus) { let cycles_start = self.get_cycles(); if let Some(interrupt) = self.check_interrupts(bus) { self.handle_interrupt(bus, interrupt); self.increment_cycles(Cycles(5)); } else if !self.is_halted { let program_counter = self.registers.get(Register::PC); let parameter_bytes = OpcodeParameterBytes::from_address(program_counter, bus); let (opcode, cycles) = parameter_bytes.parse_opcode(); if self.enable_logs { self.log(parameter_bytes); self.increment_exec_calls_count(); } self.increment_cycles(cycles); self.exec(opcode, bus); self.ei_delay(bus); } else if self.is_halted { self.increment_cycles(Cycles(1)); } let cycles_end = self.get_cycles(); self.set_last_op_cycles(cycles_start, cycles_end); } pub fn exec(&mut self, opcode: Opcode, bus: &mut Bus) { match opcode { // Load Opcode::LD(params) => match params { OpcodeParameter::Register_Register(reg1, reg2) => { self.registers.increment(Register::PC, 1); if reg1.is_16bit() && reg2.is_8bit() { let val = self.registers.get_8bit(reg2); let addr = self.registers.get(reg1); bus.write(addr, val); } else if reg1.is_8bit() && reg2.is_16bit() { let val = bus.read(self.registers.get(reg2)) as u16; self.registers.set(reg1, val); } else { self.registers.set(reg1, self.registers.get(reg2)); } }, OpcodeParameter::Register_U16(register, val) => { self.registers.increment(Register::PC, 3); match register.is_8bit() { true => self.registers.set(register, bus.read(val) as u16), false => self.registers.set(register, val), }; }, OpcodeParameter::Register_U8(register, val) => { self.registers.increment(Register::PC, 2); match register.is_8bit() { true => self.registers.set(register, val as u16), false => bus.write(self.registers.get(register), val), } }, OpcodeParameter::U16_Register(address, register) => { self.registers.increment(Register::PC, 3); let value = self.registers.get(register); let bytes = value.to_be_bytes(); match register.is_8bit() { true => bus.write(address, bytes[1]), false => bus.write_16bit(address, value), }; }, OpcodeParameter::Register_FF00plusU8(register, val) => { self.registers.increment(Register::PC, 2); self.registers.set(register, bus.read(0xFF00 + (val as u16)) as u16); }, OpcodeParameter::FF00plusU8_Register(val, register) => { self.registers.increment(Register::PC, 2); match register.is_8bit() { true => bus.write(0xFF00 + (val as u16), self.registers.get_8bit(register)), false => bus.write_16bit(0xFF00 + (val as u16), self.registers.get(register)), } }, OpcodeParameter::Register_FF00plusRegister(reg1, reg2) => { self.registers.increment(Register::PC, 1); let addr = 0xFF00 + self.registers.get(reg2); self.registers.set(reg1, bus.read(addr) as u16); }, OpcodeParameter::FF00plusRegister_Register(reg1, reg2) => { self.registers.increment(Register::PC, 1); let addr = 0xFF00 + self.registers.get(reg1); bus.write(addr, self.registers.get_8bit(reg2)); }, OpcodeParameter::Register_RegisterPlusI8(reg1, reg2, value) => { self.registers.increment(Register::PC, 2); let reg2_value = self.registers.get(reg2); self.registers.set_flag(FlagRegister::Zero, false); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::Carry, (reg2_value & 0x00FF) + ((value as u16) & 0x00FF) > 0xFF); self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(reg2_value.to_be_bytes()[1], value as u8)); let res = (self.registers.get(reg2) as i16).wrapping_add(value as i16); self.registers.set(reg1, res as u16); }, _ => {}, }, // Increment or decrement program counter by signed N Opcode::JR(params) => { self.registers.increment(Register::PC, 2); let mut condition_met = false; let mut value = 0 as i16; match params { OpcodeParameter::I8(val) => { condition_met = true; value = val as i16; }, OpcodeParameter::FlagRegisterReset_I8(flag, val) => { condition_met = !self.registers.get_flag(flag); value = val as i16; }, OpcodeParameter::FlagRegisterSet_I8(flag, val) => { condition_met = self.registers.get_flag(flag); value = val as i16; }, _ => {}, }; if condition_met { self.increment_cycles(Cycles(1)); let pc = (self.registers.get(Register::PC) as i16) + (value as i16); self.registers.set(Register::PC, pc as u16); } }, // Load and increment Opcode::LDI(params) => match params { OpcodeParameter::Register_RegisterIncrement(reg1, reg2) => { self.registers.increment(Register::PC, 1); let val = bus.read(self.registers.get(reg2)); self.registers.set(reg1, val as u16); self.registers.increment(reg2, 1); }, OpcodeParameter::RegisterIncrement_Register(reg1, reg2) => { self.registers.increment(Register::PC, 1); let val = self.registers.get_8bit(reg2); bus.write(self.registers.get(reg1), val); self.registers.increment(reg1, 1); }, _ => {}, }, // Load and decrement Opcode::LDD(params) => match params { OpcodeParameter::Register_RegisterDecrement(reg1, reg2) => { self.registers.increment(Register::PC, 1); let val = bus.read(self.registers.get(reg2)); self.registers.set(reg1, val as u16); self.registers.decrement(reg2, 1); }, OpcodeParameter::RegisterDecrement_Register(reg1, reg2) => { self.registers.increment(Register::PC, 1); let val = self.registers.get_8bit(reg2); bus.write(self.registers.get(reg1), val); self.registers.decrement(reg1, 1); }, _ => {}, }, Opcode::AND(params) => { match params { OpcodeParameter::Register_Register(reg1, reg2) => { self.registers.increment(Register::PC, 1); if reg2.is_8bit() { self.registers.set(reg1, self.registers.get(reg1) & self.registers.get(reg2)); } else { let val = bus.read(self.registers.get(reg2)) as u16; self.registers.set(reg1, self.registers.get(reg1) & val); } self.registers.set_flag(FlagRegister::Zero, self.registers.get(reg1) == 0); }, OpcodeParameter::Register_U8(reg, val) => { self.registers.increment(Register::PC, 2); self.registers.set(reg, self.registers.get(reg) & (val as u16)); self.registers.set_flag(FlagRegister::Zero, self.registers.get(reg) == 0); }, _ => {}, }; self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, true); self.registers.set_flag(FlagRegister::Carry, false); }, Opcode::OR(params) => { match params { OpcodeParameter::Register_Register(reg1, reg2) => { self.registers.increment(Register::PC, 1); if reg2.is_8bit() { self.registers.set(reg1, self.registers.get(reg1) | self.registers.get(reg2)); } else { let val = bus.read(self.registers.get(reg2)) as u16; self.registers.set(reg1, self.registers.get(reg1) | val); } self.registers.set_flag(FlagRegister::Zero, self.registers.get(reg1) == 0); }, OpcodeParameter::Register_U8(reg, val) => { self.registers.increment(Register::PC, 2); self.registers.set(reg, self.registers.get(reg) | (val as u16)); self.registers.set_flag(FlagRegister::Zero, self.registers.get(reg) == 0); }, _ => {}, }; self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); self.registers.set_flag(FlagRegister::Carry, false); }, Opcode::XOR(params) => { match params { OpcodeParameter::Register_Register(reg1, reg2) => { self.registers.increment(Register::PC, 1); if reg2.is_8bit() { self.registers.set(reg1, self.registers.get(reg1) ^ self.registers.get(reg2)); } else { let val = bus.read(self.registers.get(reg2)) as u16; self.registers.set(reg1, self.registers.get(reg1) ^ val); } self.registers.set_flag(FlagRegister::Zero, self.registers.get(reg1) == 0); }, OpcodeParameter::Register_U8(reg, val) => { self.registers.increment(Register::PC, 2); self.registers.set(reg, self.registers.get(reg) ^ (val as u16)); self.registers.set_flag(FlagRegister::Zero, self.registers.get(reg) == 0); }, _ => {}, }; self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); self.registers.set_flag(FlagRegister::Carry, false); }, // Substract without storing the value Opcode::CP(params) => { let mut val1: i16 = 0; let mut val2: i16 = 0; match params { OpcodeParameter::Register_U8(register, val) => { self.registers.increment(Register::PC, 2); val1 = self.registers.get(register) as i16; val2 = val as i16; }, OpcodeParameter::Register_Register(reg1, reg2) => { self.registers.increment(Register::PC, 1); val1 = self.registers.get(reg1) as i16; match reg2.is_8bit() { true => val2 = self.registers.get(reg2) as i16, false => val2 = bus.read(self.registers.get(reg2)) as i16, }; } _ => {}, }; self.registers.set_flag(FlagRegister::Zero, (val1 - val2) == 0); self.registers.set_flag(FlagRegister::Substract, true); self.registers.set_flag(FlagRegister::HalfCarry, sub_half_carry(val1.to_be_bytes()[1], val2.to_be_bytes()[1])); self.registers.set_flag(FlagRegister::Carry, val2 > val1); }, Opcode::ADD(params) => { self.registers.increment(Register::PC, 1); self.registers.set_flag(FlagRegister::Substract, false); match params { OpcodeParameter::Register_Register(reg1, reg2) => { if reg1.is_8bit() && reg2.is_8bit() { let res = (self.registers.get(reg1) as u16) + (self.registers.get(reg2) as u16); self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(self.registers.get_8bit(reg1), self.registers.get_8bit(reg2))); self.registers.increment(reg1, self.registers.get(reg2)); self.registers.set_flag(FlagRegister::Zero, self.registers.get(reg1) == 0); self.registers.set_flag(FlagRegister::Carry, res > 0xFF); } else if reg1.is_16bit() && reg2.is_16bit() { let val1 = self.registers.get(reg1); let val2 = self.registers.get(reg2); self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry_16bit(val1, val2)); let res = (val1 as usize) + (val2 as usize); self.registers.increment(reg1, self.registers.get(reg2)); let carry = res > 0xFFFF; self.registers.set_flag(FlagRegister::Carry, carry); } else if reg1.is_8bit() && reg2.is_16bit() { let val1 = self.registers.get(reg1); let val2 = bus.read(self.registers.get(reg2)) as u16; self.registers.increment(reg1, val2); self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(val1.to_be_bytes()[1], val2.to_be_bytes()[1])); self.registers.set_flag(FlagRegister::Zero, self.registers.get(reg1) == 0); self.registers.set_flag(FlagRegister::Carry, (val1 as usize + val2 as usize) > 0xFF); } }, OpcodeParameter::Register_U8(reg1, val) => { self.registers.increment(Register::PC, 1); match reg1.is_8bit() { true => { let val1 = self.registers.get(reg1); let val2 = val as u16; self.registers.increment(reg1, val2); self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(val1.to_be_bytes()[1], val2.to_be_bytes()[1])); self.registers.set_flag(FlagRegister::Zero, self.registers.get(reg1) == 0); self.registers.set_flag(FlagRegister::Carry, (val1 as u16) + (val2 as u16) > 0xFF); }, false => { let addr = self.registers.get(reg1); let val1 = bus.read(addr); let val2 = val; let res = val1.wrapping_add(val2); bus.write(addr, res); self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(val1, val2)); self.registers.set_flag(FlagRegister::Zero, res == 0); self.registers.set_flag(FlagRegister::Carry, (val1 as u16) + (val2 as u16) > 0xFF); }, }; }, OpcodeParameter::Register_I8(reg, value) => { self.registers.increment(Register::PC, 1); self.registers.set_flag(FlagRegister::Zero, false); self.registers.set_flag(FlagRegister::Carry, (self.registers.get(reg) & 0x00FF) + ((value as u16) & 0x00FF) > 0xFF); self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(self.registers.get_8bit(reg), value as u8)); let res = (self.registers.get(reg) as i16).wrapping_add(value as i16); self.registers.set(reg, res as u16); }, _ => {}, }; }, Opcode::ADC(params) => { let mut carry_prev = false; let mut half_carry_prev = false; match params { OpcodeParameter::Register_Register(reg1, reg2) => { let carry = self.registers.get_flag(FlagRegister::Carry); self.exec(Opcode::ADD(OpcodeParameter::Register_Register(reg1, reg2)), bus); carry_prev = self.registers.get_flag(FlagRegister::Carry); half_carry_prev = self.registers.get_flag(FlagRegister::HalfCarry); if carry { self.registers.decrement(Register::PC, 2); self.exec(Opcode::ADD(OpcodeParameter::Register_U8(reg1, 1)), bus); } }, OpcodeParameter::Register_U8(reg1, val) => { let carry = self.registers.get_flag(FlagRegister::Carry); self.exec(Opcode::ADD(OpcodeParameter::Register_U8(reg1, val)), bus); carry_prev = self.registers.get_flag(FlagRegister::Carry); half_carry_prev = self.registers.get_flag(FlagRegister::HalfCarry); if carry { self.registers.decrement(Register::PC, 2); self.exec(Opcode::ADD(OpcodeParameter::Register_U8(reg1, 1)), bus); } }, OpcodeParameter::Register_I8(reg1, val) => { let carry = self.registers.get_flag(FlagRegister::Carry); self.exec(Opcode::ADD(OpcodeParameter::Register_I8(reg1, val)), bus); carry_prev = self.registers.get_flag(FlagRegister::Carry); half_carry_prev = self.registers.get_flag(FlagRegister::HalfCarry); if carry { self.registers.decrement(Register::PC, 2); self.exec(Opcode::ADD(OpcodeParameter::Register_I8(reg1, 1)), bus); } }, _ => {}, }; self.registers.set_flag(FlagRegister::Carry, carry_prev || self.registers.get_flag(FlagRegister::Carry)); self.registers.set_flag(FlagRegister::HalfCarry, half_carry_prev || self.registers.get_flag(FlagRegister::HalfCarry)); }, Opcode::SUB(params) => { self.registers.increment(Register::PC, 1); let mut register = Register::A; let mut val1: u16 = 0; let mut val2: u16 = 0; match params { OpcodeParameter::Register_Register(reg1, reg2) => { register = reg1; val1 = self.registers.get(reg1); if reg1.is_8bit() && reg2.is_8bit() { val2 = self.registers.get(reg2); } else if reg1.is_8bit() && reg2.is_16bit() { val2 = bus.read(self.registers.get(reg2)) as u16; } }, OpcodeParameter::Register_U8(reg1, val) => { self.registers.increment(Register::PC, 1); register = reg1; val1 = self.registers.get(reg1); val2 = val as u16; }, _ => {}, }; let carry = val2 > val1; if carry { val1 = val1 | 0x100; } let result = val1.wrapping_sub(val2); self.registers.set(register, result); self.registers.set_flag(FlagRegister::Zero, self.registers.get(register) == 0); self.registers.set_flag(FlagRegister::Substract, true); self.registers.set_flag(FlagRegister::Carry, carry); self.registers.set_flag(FlagRegister::HalfCarry, sub_half_carry(val1.to_be_bytes()[1], val2.to_be_bytes()[1])); }, Opcode::SBC(params) => { let mut carry_prev = false; let mut half_carry_prev = false; match params { OpcodeParameter::Register_Register(reg1, reg2) => { let carry = self.registers.get_flag(FlagRegister::Carry); self.exec(Opcode::SUB(OpcodeParameter::Register_Register(reg1, reg2)), bus); carry_prev = self.registers.get_flag(FlagRegister::Carry); half_carry_prev = self.registers.get_flag(FlagRegister::HalfCarry); if carry { self.registers.decrement(Register::PC, 2); self.exec(Opcode::SUB(OpcodeParameter::Register_U8(reg1, 1)), bus); } }, OpcodeParameter::Register_U8(reg1, val) => { let carry = self.registers.get_flag(FlagRegister::Carry); self.exec(Opcode::SUB(OpcodeParameter::Register_U8(reg1, val)), bus); carry_prev = self.registers.get_flag(FlagRegister::Carry); half_carry_prev = self.registers.get_flag(FlagRegister::HalfCarry); if carry { self.registers.decrement(Register::PC, 2); self.exec(Opcode::SUB(OpcodeParameter::Register_U8(reg1, 1)), bus); } }, OpcodeParameter::Register_I8(reg1, val) => { let carry = self.registers.get_flag(FlagRegister::Carry); self.exec(Opcode::ADD(OpcodeParameter::Register_I8(reg1, val)), bus); carry_prev = self.registers.get_flag(FlagRegister::Carry); half_carry_prev = self.registers.get_flag(FlagRegister::HalfCarry); if carry { self.registers.decrement(Register::PC, 2); self.exec(Opcode::SUB(OpcodeParameter::Register_I8(reg1, 1)), bus); } }, _ => {}, }; self.registers.set_flag(FlagRegister::Carry, carry_prev || self.registers.get_flag(FlagRegister::Carry)); self.registers.set_flag(FlagRegister::HalfCarry, half_carry_prev || self.registers.get_flag(FlagRegister::HalfCarry)); }, // Increment by 1 Opcode::INC(affect_flags, on_address, register) => { self.registers.increment(Register::PC, 1); if on_address { let addr = self.registers.get(register); let prev_value = bus.read(addr); bus.write(addr, prev_value.wrapping_add(1)); if affect_flags { self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(prev_value, 1)); self.registers.set_flag(FlagRegister::Zero, bus.read(addr) == 0); } } else { let prev_value = self.registers.get(register); self.registers.increment(register, 1); if affect_flags { let mut byte_compare = 0; match register.is_8bit() { true => byte_compare = prev_value.to_be_bytes()[1], false => byte_compare = prev_value.to_be_bytes()[0], } let result = self.registers.get(register); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, add_half_carry(byte_compare, 1)); self.registers.set_flag(FlagRegister::Zero, result == 0); } } }, // Decrement by 1 Opcode::DEC(affect_flags, on_address, register) => { self.registers.increment(Register::PC, 1); if on_address { let addr = self.registers.get(register); let prev_value = bus.read(addr); bus.write(addr, prev_value.wrapping_sub(1)); if affect_flags { self.registers.set_flag(FlagRegister::Substract, true); self.registers.set_flag(FlagRegister::HalfCarry, sub_half_carry(prev_value, 1)); self.registers.set_flag(FlagRegister::Zero, bus.read(addr) == 0); } } else { let prev_value = self.registers.get(register); self.registers.decrement(register, 1); if affect_flags { let mut byte_compare = 0; match register.is_8bit() { true => byte_compare = prev_value.to_be_bytes()[1], false => byte_compare = prev_value.to_be_bytes()[0], } let result = self.registers.get(register); self.registers.set_flag(FlagRegister::Substract, true); self.registers.set_flag(FlagRegister::HalfCarry, sub_half_carry(byte_compare, 1)); self.registers.set_flag(FlagRegister::Zero, result == 0); } } }, // BCD correction Opcode::DAA => { self.registers.increment(Register::PC, 1); let mut val = self.registers.get_8bit(Register::A); if !self.registers.get_flag(FlagRegister::Substract) { if self.registers.get_flag(FlagRegister::Carry) || val > 0x99 { val = val.wrapping_add(0x60); self.registers.set_flag(FlagRegister::Carry, true); } if self.registers.get_flag(FlagRegister::HalfCarry) || ((val & 0x0F) > 0x09) { val = val.wrapping_add(0x6); } } else { if self.registers.get_flag(FlagRegister::Carry) { val = val.wrapping_sub(0x60); } if self.registers.get_flag(FlagRegister::HalfCarry) { val = val.wrapping_sub(0x6); } } self.registers.set(Register::A, val as u16); self.registers.set_flag(FlagRegister::HalfCarry, false); self.registers.set_flag(FlagRegister::Zero, val == 0); }, // Jump to address Opcode::JP(params) => match params { OpcodeParameter::U16(address) => self.registers.set(Register::PC, address), OpcodeParameter::Register(register) => self.registers.set(Register::PC, self.registers.get(register)), OpcodeParameter::FlagRegisterReset_U16(flag, addr) => { self.registers.increment(Register::PC, 3); if !self.registers.get_flag(flag) { self.registers.set(Register::PC, addr); self.increment_cycles(Cycles(1)); } }, OpcodeParameter::FlagRegisterSet_U16(flag, addr) => { self.registers.increment(Register::PC, 3); if self.registers.get_flag(flag) { self.registers.set(Register::PC, addr); self.increment_cycles(Cycles(1)); } }, _ => {}, }, // CALL Opcode::CALL(params) => { self.registers.increment(Register::PC, 3); let mut condition_met = false; let mut addr = self.registers.get(Register::PC); match params { OpcodeParameter::U16(address) => { condition_met = true; addr = address; }, OpcodeParameter::FlagRegisterReset_U16(flag, address) => { condition_met = !self.registers.get_flag(flag); addr = address; if condition_met {self.increment_cycles(Cycles(3))}; }, OpcodeParameter::FlagRegisterSet_U16(flag, address) => { condition_met = self.registers.get_flag(flag); addr = address; if condition_met {self.increment_cycles(Cycles(3))}; }, _ => {}, }; if condition_met { let pc = self.registers.get(Register::PC); self.registers.decrement(Register::SP, 2); let sp = self.registers.get(Register::SP); bus.write_16bit(sp, pc); self.registers.set(Register::PC, addr); } }, // RST, same as Call Opcode::RST(address) => { self.registers.decrement(Register::PC, 2); self.exec(Opcode::CALL(OpcodeParameter::U16(address as u16)), bus); }, // PUSH onto the stack Opcode::PUSH(register) => { self.registers.increment(Register::PC, 1); let val = self.registers.get(register).to_be_bytes(); self.registers.decrement(Register::SP, 1); bus.write(self.registers.get(Register::SP), val[0]); self.registers.decrement(Register::SP, 1); bus.write(self.registers.get(Register::SP), val[1]); }, // POP onto the stack Opcode::POP(register) => { self.registers.increment(Register::PC, 1); let sp = self.registers.get(Register::SP); let val = bus.read_16bit(sp); match register { Register::AF => self.registers.set(register, val & 0xFFF0), _ => self.registers.set(register, val), }; self.registers.increment(Register::SP, 2); }, // RET, same as POP PC when no parameter is specified Opcode::RET(params) => { self.registers.increment(Register::PC, 1); match params { OpcodeParameter::NoParam => self.exec(Opcode::POP(Register::PC), bus), OpcodeParameter::FlagRegisterReset(flag) => { if !self.registers.get_flag(flag) { self.exec(Opcode::POP(Register::PC), bus); self.increment_cycles(Cycles(3)); } }, OpcodeParameter::FlagRegisterSet(flag) => { if self.registers.get_flag(flag) { self.exec(Opcode::POP(Register::PC), bus); self.increment_cycles(Cycles(3)); } }, _ => {}, }; }, // Rotate A Left Opcode::RLCA => { self.registers.increment(Register::PC, 1); let val = self.registers.get_8bit(Register::A); self.registers.set_flag(FlagRegister::Carry, get_bit(val, BitIndex::I7)); let result = val.rotate_left(1); self.registers.set(Register::A, result as u16); self.registers.set_flag(FlagRegister::Zero, false); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); }, // Rotate A Right Opcode::RRCA => { self.registers.increment(Register::PC, 1); let val = self.registers.get_8bit(Register::A); self.registers.set_flag(FlagRegister::Carry, get_bit(val, BitIndex::I0)); let result = val.rotate_right(1); self.registers.set(Register::A, result as u16); self.registers.set_flag(FlagRegister::Zero, false); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); }, Opcode::RLA => { self.registers.increment(Register::PC, 1); let val = self.registers.get_8bit(Register::A); let old_carry = self.registers.get_flag(FlagRegister::Carry); let new_carry = get_bit(val, BitIndex::I7); let val = val << 1 | (old_carry as u8); self.registers.set(Register::A, val as u16); self.registers.set_flag(FlagRegister::Carry, new_carry); self.registers.set_flag(FlagRegister::Zero, false); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); }, Opcode::RRA => { self.registers.increment(Register::PC, 1); let val = self.registers.get_8bit(Register::A); let old_carry = self.registers.get_flag(FlagRegister::Carry); let new_carry = get_bit(val, BitIndex::I0); let val = val >> 1 | ((old_carry as u8) << 7); self.registers.set(Register::A, val as u16); self.registers.set_flag(FlagRegister::Carry, new_carry); self.registers.set_flag(FlagRegister::Zero, false); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); }, Opcode::PrefixCB(opcode) => { self.registers.increment(Register::PC, 2); match *opcode { Opcode::RLC(register) => { let mut result = 0; let mut val = 0; if register.is_8bit() { val = self.registers.get_8bit(register); result = val.rotate_left(1); self.registers.set(register, result as u16); } else { let addr = self.registers.get(register); val = bus.read(addr); result = val.rotate_left(1); bus.write(addr, result); } self.registers.set_flag(FlagRegister::Zero, result == 0); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); self.registers.set_flag(FlagRegister::Carry, get_bit(val, BitIndex::I7)); }, Opcode::RRC(register) => { let mut result = 0; let mut val = 0; if register.is_8bit() { val = self.registers.get_8bit(register); result = val.rotate_right(1); self.registers.set(register, result as u16); } else { let addr = self.registers.get(register); val = bus.read(addr); result = val.rotate_right(1); bus.write(addr, result); } self.registers.set_flag(FlagRegister::Zero, result == 0); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); self.registers.set_flag(FlagRegister::Carry, get_bit(val, BitIndex::I0)); }, Opcode::RL(register) => { let mut val = 0; match register.is_8bit() { true => val = self.registers.get_8bit(register), false => val = bus.read(self.registers.get(register)), }; let old_carry = self.registers.get_flag(FlagRegister::Carry); let new_carry = get_bit(val, BitIndex::I7); let val = val << 1 | (old_carry as u8); match register.is_8bit() { true => self.registers.set(register, val as u16), false => bus.write(self.registers.get(register), val), }; self.registers.set_flag(FlagRegister::Carry, new_carry); self.registers.set_flag(FlagRegister::Zero, val == 0); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); }, Opcode::RR(register) => { let mut val = 0; match register.is_8bit() { true => val = self.registers.get_8bit(register), false => val = bus.read(self.registers.get(register)), }; let old_carry = self.registers.get_flag(FlagRegister::Carry); let new_carry = get_bit(val, BitIndex::I0); let val = val >> 1 | ((old_carry as u8) << 7); match register.is_8bit() { true => self.registers.set(register, val as u16), false => bus.write(self.registers.get(register), val), }; self.registers.set_flag(FlagRegister::Carry, new_carry); self.registers.set_flag(FlagRegister::Zero, val == 0); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); }, Opcode::SLA(register) => { let mut val = 0; match register.is_8bit() { true => val = self.registers.get_8bit(register) as i8, false => val = bus.read(self.registers.get(register)) as i8, }; let res = val << 1; match register.is_8bit() { true => self.registers.set(register, res as u16), false => bus.write(self.registers.get(register), res as u8), }; self.registers.set_flag(FlagRegister::Carry, get_bit(val as u8, BitIndex::I7)); self.registers.set_flag(FlagRegister::Zero, res == 0); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); }, Opcode::SRA(register) => { let mut val = 0; match register.is_8bit() { true => val = self.registers.get_8bit(register) as i8, false => val = bus.read(self.registers.get(register)) as i8, }; let res = val >> 1; match register.is_8bit() { true => self.registers.set(register, res as u16), false => bus.write(self.registers.get(register), res as u8), }; self.registers.set_flag(FlagRegister::Carry, get_bit(val as u8, BitIndex::I0)); self.registers.set_flag(FlagRegister::Zero, res == 0); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); }, Opcode::SRL(register) => { let mut val = 0; match register.is_8bit() { true => val = self.registers.get_8bit(register), false => val = bus.read(self.registers.get(register)), }; let carry = get_bit(val, BitIndex::I0); let val = val >> 1; match register.is_8bit() { true => self.registers.set(register, val as u16), false => bus.write(self.registers.get(register), val), }; self.registers.set_flag(FlagRegister::Carry, carry); self.registers.set_flag(FlagRegister::Zero, val == 0); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); }, Opcode::SWAP(register) => { let mut val = 0; match register.is_8bit() { true => val = self.registers.get_8bit(register), false => val = bus.read(self.registers.get(register)), }; let val = (val << 4) | (val >> 4); match register.is_8bit() { true => self.registers.set(register, val as u16), false => bus.write(self.registers.get(register), val), }; self.registers.set_flag(FlagRegister::Zero, val == 0); self.registers.set_flag(FlagRegister::Carry, false); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); }, Opcode::BIT(index, register) => { let mut val = 0; match register.is_8bit() { true => val = self.registers.get_8bit(register), false => val = bus.read(self.registers.get(register)), }; let res = get_bit(val, index); self.registers.set_flag(FlagRegister::Zero, !res); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, true); }, Opcode::RES(index, register) => { let mut val = 0; match register.is_8bit() { true => val = self.registers.get_8bit(register), false => val = bus.read(self.registers.get(register)), }; let val = set_bit(val, false, index); match register.is_8bit() { true => self.registers.set(register, val as u16), false => bus.write(self.registers.get(register), val), }; }, Opcode::SET(index, register) => { let mut val = 0; match register.is_8bit() { true => val = self.registers.get_8bit(register), false => val = bus.read(self.registers.get(register)), }; let val = set_bit(val, true, index); match register.is_8bit() { true => self.registers.set(register, val as u16), false => bus.write(self.registers.get(register), val), }; }, _ => {}, }; }, Opcode::CPL => { self.registers.increment(Register::PC, 1); self.registers.set(Register::A, !self.registers.get(Register::A)); self.registers.set_flag(FlagRegister::Substract, true); self.registers.set_flag(FlagRegister::HalfCarry, true); }, // Invert the carry flag Opcode::CCF => { self.registers.increment(Register::PC, 1); self.registers.set_flag(FlagRegister::Carry, !self.registers.get_flag(FlagRegister::Carry)); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); }, // Set the carry flag Opcode::SCF => { self.registers.increment(Register::PC, 1); self.registers.set_flag(FlagRegister::Carry, true); self.registers.set_flag(FlagRegister::Substract, false); self.registers.set_flag(FlagRegister::HalfCarry, false); }, // Enable interrupts Opcode::EI => { self.registers.increment(Register::PC, 1); self.ei_delay = true; }, // Disable interrupts Opcode::DI => { self.registers.increment(Register::PC, 1); self.ime = false; }, // Same as enabling interrupts and then executing RET Opcode::RETI => { self.exec(Opcode::RET(OpcodeParameter::NoParam), bus); self.ime = true; }, // Don't execute instructions until an interrupt is requested Opcode::HALT => { self.registers.increment(Register::PC, 1); self.is_halted = true; }, Opcode::STOP => { self.registers.increment(Register::PC, 2); }, Opcode::NOP => self.registers.increment(Register::PC, 1), Opcode::IllegalInstruction => { println!("Illegal instruction!"); self.registers.increment(Register::PC, 1); }, _ => unreachable!(), }; } } #[cfg(test)] mod tests { use super::*; #[test] fn test_registers_setters_getters() { // Test 8 bit setters and getters let mut registers = Registers::new(); registers.set(Register::A, 0b01010101); assert_eq!(registers.get(Register::A), 0b01010101); registers.set(Register::F, 0b01010101); assert_eq!(registers.get(Register::F), 0b01010101); registers.set(Register::B, 0b01010101); assert_eq!(registers.get(Register::B), 0b01010101); registers.set(Register::C, 0b01010101); assert_eq!(registers.get(Register::C), 0b01010101); registers.set(Register::D, 0b01010101); assert_eq!(registers.get(Register::D), 0b01010101); registers.set(Register::E, 0b01010101); assert_eq!(registers.get(Register::E), 0b01010101); registers.set(Register::H, 0b01010101); assert_eq!(registers.get(Register::H), 0b01010101); registers.set(Register::L, 0b01010101); assert_eq!(registers.get(Register::L), 0b01010101); // Test 16 bit setters and getters let mut registers = Registers::new(); registers.set(Register::A, 0b01010101); registers.set(Register::F, 0b11111111); assert_eq!(registers.get(Register::AF), 0b0101010111111111); registers.set(Register::AF, 0b1111111101010101); assert_eq!(registers.get(Register::AF), 0b1111111101010101); registers.set(Register::B, 0b01010101); registers.set(Register::C, 0b11111111); assert_eq!(registers.get(Register::BC), 0b0101010111111111); registers.set(Register::BC, 0b1111111101010101); assert_eq!(registers.get(Register::BC), 0b1111111101010101); registers.set(Register::D, 0b01010101); registers.set(Register::E, 0b11111111); assert_eq!(registers.get(Register::DE), 0b0101010111111111); registers.set(Register::DE, 0b1111111101010101); assert_eq!(registers.get(Register::DE), 0b1111111101010101); registers.set(Register::H, 0b01010101); registers.set(Register::L, 0b11111111); assert_eq!(registers.get(Register::HL), 0b0101010111111111); registers.set(Register::HL, 0b1111111101010101); assert_eq!(registers.get(Register::HL), 0b1111111101010101); registers.set(Register::SP, 0b0101010111111111); assert_eq!(registers.get(Register::SP), 0b0101010111111111); registers.set(Register::PC, 0b0101010111111111); assert_eq!(registers.get(Register::PC), 0b0101010111111111); } #[test] fn test_ld_instructions() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0xFF); cpu.exec(Opcode::LD(OpcodeParameter::Register_Register(Register::B, Register::A)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0xFF); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.exec(Opcode::LD(OpcodeParameter::Register_U16(Register::SP, 0xF1F1)), &mut bus); assert_eq!(cpu.registers.get(Register::SP), 0xF1F1); assert_eq!(cpu.registers.get(Register::PC), 0x103); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xC000; bus.write(addr, 0xF1); cpu.exec(Opcode::LD(OpcodeParameter::Register_U16(Register::A, addr)), &mut bus); assert_eq!(cpu.registers.get(Register::A), 0xF1); assert_eq!(cpu.registers.get(Register::PC), 0x103); let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.exec(Opcode::LD(OpcodeParameter::Register_U8(Register::B, 0xF1)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0xF1); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.registers.set(Register::SP, 0x1234); cpu.exec(Opcode::LD(OpcodeParameter::U16_Register(0xF0F0, Register::SP)), &mut bus); assert_eq!(bus.read_16bit(0xF0F0), 0x1234); assert_eq!(cpu.registers.get(Register::PC), 0x103); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xC000; cpu.registers.set(Register::A, 0x12); cpu.exec(Opcode::LD(OpcodeParameter::U16_Register(addr, Register::A)), &mut bus); assert_eq!(bus.read(addr), 0x12); assert_eq!(cpu.registers.get(Register::PC), 0x103); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xC000; cpu.registers.set(Register::A, 0xFF); cpu.registers.set(Register::HL, addr); bus.write(addr, 0x00); cpu.exec(Opcode::LD(OpcodeParameter::Register_Register(Register::HL, Register::A)), &mut bus); assert_eq!(bus.read(addr), 0xFF); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xC000; cpu.registers.set(Register::A, 0x00); cpu.registers.set(Register::HL, addr); bus.write(addr, 0xFF); cpu.exec(Opcode::LD(OpcodeParameter::Register_Register(Register::A, Register::HL)), &mut bus); assert_eq!(cpu.registers.get(Register::A), 0xFF); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xFF00; cpu.registers.set(Register::A, 0xF1); cpu.exec(Opcode::LD(OpcodeParameter::FF00plusU8_Register(0x42, Register::A)), &mut bus); assert_eq!(bus.read(addr + 0x42), 0xF1); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xFF00; cpu.registers.set(Register::A, 0x00); bus.write(addr + 0x42, 0xF1); cpu.exec(Opcode::LD(OpcodeParameter::Register_FF00plusU8(Register::A, 0x42)), &mut bus); assert_eq!(cpu.registers.get(Register::A), 0xF1); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); let val = 100; cpu.registers.set(Register::SP, val); cpu.exec(Opcode::LD(OpcodeParameter::Register_RegisterPlusI8(Register::HL, Register::SP, -5)), &mut bus); assert_eq!(cpu.registers.get(Register::HL), val - 5); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.registers.set(Register::HL, 0x0000); cpu.registers.set(Register::SP, 0x000F); cpu.exec(Opcode::LD(OpcodeParameter::Register_RegisterPlusI8(Register::HL, Register::SP, 0x01)), &mut bus); assert_eq!(cpu.registers.get(Register::HL), 0x0010); assert_eq!(cpu.registers.get(Register::PC), 0x102); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); let mut cpu = CPU::new(); let addr = 0xC000; cpu.registers.set(Register::HL, addr); cpu.exec(Opcode::LD(OpcodeParameter::Register_U8(Register::HL, 0xF1)), &mut bus); assert_eq!(bus.read(addr), 0xF1); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::C, 1); bus.write(0xFF01, 0xF1); cpu.exec(Opcode::LD(OpcodeParameter::Register_FF00plusRegister(Register::A, Register::C)), &mut bus); assert_eq!(cpu.registers.get(Register::A), 0xF1); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::C, 1); cpu.registers.set(Register::A, 0xF1); cpu.exec(Opcode::LD(OpcodeParameter::FF00plusRegister_Register(Register::C, Register::A)), &mut bus); assert_eq!(bus.read(0xFF01), 0xF1); assert_eq!(cpu.registers.get(Register::PC), 0x101); } #[test] fn test_ldi_instructions() { let mut bus = Bus::new(); let mut cpu = CPU::new(); let addr = 0xC000; cpu.registers.set(Register::A, 0x00); cpu.registers.set(Register::HL, addr); bus.write(addr, 0xF1); cpu.exec(Opcode::LDI(OpcodeParameter::Register_RegisterIncrement(Register::A, Register::HL)), &mut bus); assert_eq!(bus.read(addr), 0xF1); assert_eq!(cpu.registers.get(Register::A), 0xF1); assert_eq!(cpu.registers.get(Register::HL), addr + 1); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut bus = Bus::new(); let mut cpu = CPU::new(); let addr = 0xC000; cpu.registers.set(Register::A, 0x1F); cpu.registers.set(Register::HL, addr); cpu.exec(Opcode::LDI(OpcodeParameter::RegisterIncrement_Register(Register::HL, Register::A)), &mut bus); assert_eq!(bus.read(addr), 0x1F); assert_eq!(cpu.registers.get(Register::HL), addr + 1); assert_eq!(cpu.registers.get(Register::PC), 0x101); } #[test] fn test_ldd_instructions() { let mut bus = Bus::new(); let mut cpu = CPU::new(); let addr = 0xC000; cpu.registers.set(Register::A, 0x00); cpu.registers.set(Register::HL, addr); bus.write(addr, 0xF1); cpu.exec(Opcode::LDD(OpcodeParameter::Register_RegisterDecrement(Register::A, Register::HL)), &mut bus); assert_eq!(bus.read(addr), 0xF1); assert_eq!(cpu.registers.get(Register::A), 0xF1); assert_eq!(cpu.registers.get(Register::HL), addr - 1); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut bus = Bus::new(); let mut cpu = CPU::new(); let addr = 0xC000; cpu.registers.set(Register::A, 0x1F); cpu.registers.set(Register::HL, addr); cpu.exec(Opcode::LDD(OpcodeParameter::RegisterDecrement_Register(Register::HL, Register::A)), &mut bus); assert_eq!(bus.read(addr), 0x1F); assert_eq!(cpu.registers.get(Register::HL), addr - 1); assert_eq!(cpu.registers.get(Register::PC), 0x101); } #[test] fn test_jp_instructions() { let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.exec(Opcode::JP(OpcodeParameter::U16(0x1F1F)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 0x1F1F); let mut cpu = CPU::new(); let addr = 0xC000; cpu.registers.set(Register::HL, addr); cpu.exec(Opcode::JP(OpcodeParameter::Register(Register::HL)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), addr); let mut cpu = CPU::new(); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.exec(Opcode::JP(OpcodeParameter::FlagRegisterReset_U16(FlagRegister::Zero, addr)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), addr); let mut cpu = CPU::new(); cpu.registers.set_flag(FlagRegister::Zero, true); cpu.exec(Opcode::JP(OpcodeParameter::FlagRegisterSet_U16(FlagRegister::Zero, addr)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), addr); let mut cpu = CPU::new(); cpu.registers.set_flag(FlagRegister::Zero, true); cpu.exec(Opcode::JP(OpcodeParameter::FlagRegisterReset_U16(FlagRegister::Zero, addr)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 0x103); let mut cpu = CPU::new(); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.exec(Opcode::JP(OpcodeParameter::FlagRegisterSet_U16(FlagRegister::Zero, addr)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 0x103); } #[test] fn test_jr_instructions() { let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.registers.set(Register::PC, 100); cpu.exec(Opcode::JR(OpcodeParameter::I8(-5)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 95 + 2); cpu.registers.set(Register::PC, 100); cpu.exec(Opcode::JR(OpcodeParameter::I8(5)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 105 + 2); cpu.registers.set(Register::PC, 100); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.exec(Opcode::JR(OpcodeParameter::FlagRegisterReset_I8(FlagRegister::Zero, -5)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 95 + 2); cpu.registers.set(Register::PC, 100); cpu.registers.set_flag(FlagRegister::Zero, true); cpu.exec(Opcode::JR(OpcodeParameter::FlagRegisterSet_I8(FlagRegister::Zero, -5)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 95 + 2); cpu.registers.set(Register::PC, 100); cpu.registers.set_flag(FlagRegister::Zero, true); cpu.exec(Opcode::JR(OpcodeParameter::FlagRegisterReset_I8(FlagRegister::Zero, -5)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 100 + 2); cpu.registers.set(Register::PC, 100); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.exec(Opcode::JR(OpcodeParameter::FlagRegisterSet_I8(FlagRegister::Zero, -5)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 100 + 2); cpu.registers.set(Register::PC, 100); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.exec(Opcode::JR(OpcodeParameter::FlagRegisterReset_I8(FlagRegister::Zero, 5)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 105 + 2); } #[test] fn test_di_instructions() { let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.exec(Opcode::DI, &mut bus); assert_eq!(cpu.ime, false); assert_eq!(cpu.registers.get(Register::PC), 0x101); } #[test] fn test_ei_instructions() { let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.exec(Opcode::EI, &mut bus); assert_eq!(cpu.ime, true); assert_eq!(cpu.registers.get(Register::PC), 0x101); } #[test] fn test_rlca_instructions() { let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.registers.set(Register::A, 0b00000010); cpu.exec(Opcode::RLCA, &mut bus); assert_eq!(cpu.registers.get(Register::A), 0b00000100); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.registers.set(Register::A, 0b10000000); cpu.exec(Opcode::RLCA, &mut bus); assert_eq!(cpu.registers.get(Register::A), 0b00000001); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.registers.set(Register::A, 0x01); cpu.exec(Opcode::RLCA, &mut bus); assert_eq!(cpu.registers.get(Register::A), 0x02); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); } #[test] fn test_rrca_instructions() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b01000000); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::RRCA, &mut bus); assert_eq!(cpu.registers.get(Register::A), 0b00100000); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.registers.set(Register::A, 0b00000001); cpu.exec(Opcode::RRCA, &mut bus); assert_eq!(cpu.registers.get(Register::A), 0b10000000); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::PC), 0x101); } #[test] fn test_call_instructions() { let mut bus = Bus::new(); let mut cpu = CPU::new(); let sp = 0xFFDF; cpu.registers.set(Register::SP, sp); cpu.registers.set(Register::PC, 0x1234); cpu.exec(Opcode::CALL(OpcodeParameter::U16(0xF0F0)), &mut bus); assert_eq!(bus.read_16bit(sp - 2), 0x1234 + 3); assert_eq!(cpu.registers.get(Register::SP), sp - 2); assert_eq!(cpu.registers.get(Register::PC), 0xF0F0); let mut cpu = CPU::new(); let sp = 0xFFDF; cpu.registers.set(Register::SP, sp); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set(Register::PC, 0x1234); cpu.exec(Opcode::CALL(OpcodeParameter::FlagRegisterReset_U16(FlagRegister::Zero, 0xF0F0)), &mut bus); assert_eq!(bus.read_16bit(sp - 2), 0x1234 + 3); assert_eq!(cpu.registers.get(Register::SP), sp - 2); assert_eq!(cpu.registers.get(Register::PC), 0xF0F0); let mut cpu = CPU::new(); let sp = 0xFFDF; cpu.registers.set(Register::SP, sp); cpu.registers.set_flag(FlagRegister::Zero, true); cpu.exec(Opcode::CALL(OpcodeParameter::FlagRegisterReset_U16(FlagRegister::Zero, 0xF0F0)), &mut bus); assert_eq!(bus.read_16bit(sp - 2), 0x1234 + 3); assert_eq!(cpu.registers.get(Register::SP), sp); assert_eq!(cpu.registers.get(Register::PC), 0x103); let mut cpu = CPU::new(); let sp = 0xFFDF; cpu.registers.set(Register::SP, sp); cpu.registers.set_flag(FlagRegister::Zero, true); cpu.registers.set(Register::PC, 0x1234); cpu.exec(Opcode::CALL(OpcodeParameter::FlagRegisterSet_U16(FlagRegister::Zero, 0xF0F0)), &mut bus); assert_eq!(bus.read_16bit(sp - 2), 0x1234 + 3); assert_eq!(cpu.registers.get(Register::SP), sp - 2); assert_eq!(cpu.registers.get(Register::PC), 0xF0F0); let mut cpu = CPU::new(); let sp = 0xFFDF; cpu.registers.set(Register::SP, sp); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.exec(Opcode::CALL(OpcodeParameter::FlagRegisterSet_U16(FlagRegister::Zero, 0xF0F0)), &mut bus); assert_eq!(bus.read_16bit(sp - 2), 0x1234 + 3); assert_eq!(cpu.registers.get(Register::SP), sp); assert_eq!(cpu.registers.get(Register::PC), 0x103); } #[test] fn test_rst_instructions() { let mut bus = Bus::new(); let mut cpu = CPU::new(); let sp = 0xFFDF; cpu.registers.set(Register::SP, sp); cpu.registers.set(Register::PC, 0x1234); cpu.exec(Opcode::RST(0xF0), &mut bus); assert_eq!(bus.read_16bit(sp - 2), 0x1234 + 1); assert_eq!(cpu.registers.get(Register::SP), sp - 2); assert_eq!(cpu.registers.get(Register::PC), 0x00F0); } #[test] fn test_push_instructions() { let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xD000; cpu.registers.set(Register::SP, addr); cpu.registers.set(Register::AF, 0x1234); cpu.exec(Opcode::PUSH(Register::AF), &mut bus); assert_eq!(bus.read_16bit(addr - 2), 0x1234); assert_eq!(cpu.registers.get(Register::SP), addr - 2); assert_eq!(cpu.registers.get(Register::PC), 0x101); } #[test] fn test_pop_instructions() { let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xD000; cpu.registers.set(Register::SP, addr); bus.write_16bit(addr, 0x1234); cpu.exec(Opcode::POP(Register::PC), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 0x1234); assert_eq!(cpu.registers.get(Register::SP), addr + 2); } #[test] fn test_ret_instructions() { let mut cpu = CPU::new(); let mut bus = Bus::new(); let sp = 0xD000; cpu.registers.set(Register::SP, sp); bus.write_16bit(sp, 0x1234); cpu.exec(Opcode::RET(OpcodeParameter::NoParam), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 0x1234); assert_eq!(cpu.registers.get(Register::SP), sp + 2); let mut cpu = CPU::new(); let mut bus = Bus::new(); let sp = 0xD000; cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set(Register::SP, sp); bus.write_16bit(sp, 0x1234); cpu.exec(Opcode::RET(OpcodeParameter::FlagRegisterReset(FlagRegister::Zero)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 0x1234); assert_eq!(cpu.registers.get(Register::SP), sp + 2); let mut cpu = CPU::new(); let mut bus = Bus::new(); let sp = 0xD000; cpu.registers.set_flag(FlagRegister::Zero, true); cpu.registers.set(Register::SP, sp); bus.write_16bit(sp, 0x1234); cpu.exec(Opcode::RET(OpcodeParameter::FlagRegisterReset(FlagRegister::Zero)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 0x101); assert_eq!(cpu.registers.get(Register::SP), sp); let mut cpu = CPU::new(); let mut bus = Bus::new(); let sp = 0xD000; cpu.registers.set_flag(FlagRegister::Zero, true); cpu.registers.set(Register::SP, sp); bus.write_16bit(sp, 0x1234); cpu.exec(Opcode::RET(OpcodeParameter::FlagRegisterSet(FlagRegister::Zero)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 0x1234); assert_eq!(cpu.registers.get(Register::SP), sp + 2); let mut cpu = CPU::new(); let mut bus = Bus::new(); let sp = 0xD000; cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set(Register::SP, sp); bus.write_16bit(sp, 0x1234); cpu.exec(Opcode::RET(OpcodeParameter::FlagRegisterSet(FlagRegister::Zero)), &mut bus); assert_eq!(cpu.registers.get(Register::PC), 0x101); assert_eq!(cpu.registers.get(Register::SP), sp); } #[test] fn test_and_instructions() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0xF1); cpu.registers.set(Register::C, 0x1F); cpu.exec(Opcode::AND(OpcodeParameter::Register_Register(Register::B, Register::C)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0xF1 & 0x1F); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0x00); cpu.registers.set(Register::C, 0x00); cpu.exec(Opcode::AND(OpcodeParameter::Register_Register(Register::B, Register::C)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0x00); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xC000; cpu.registers.set(Register::B, 0x1F); cpu.registers.set(Register::HL, addr); bus.write(addr, 0x1F); cpu.exec(Opcode::AND(OpcodeParameter::Register_Register(Register::B, Register::HL)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0x1F & 0x1F); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xC000; cpu.registers.set(Register::B, 0x00); cpu.registers.set(Register::HL, addr); bus.write(addr, 0x00); cpu.exec(Opcode::AND(OpcodeParameter::Register_Register(Register::B, Register::HL)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0x00); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0x1F); cpu.exec(Opcode::AND(OpcodeParameter::Register_U8(Register::B, 0x1A)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0x1F & 0x1A); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0x00); cpu.exec(Opcode::AND(OpcodeParameter::Register_U8(Register::B, 0x00)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0x00); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_or_instructions() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0xF1); cpu.registers.set(Register::C, 0x1F); cpu.exec(Opcode::OR(OpcodeParameter::Register_Register(Register::B, Register::C)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0xF1 | 0x1F); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0x00); cpu.registers.set(Register::C, 0x00); cpu.exec(Opcode::OR(OpcodeParameter::Register_Register(Register::B, Register::C)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0x00); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xC000; cpu.registers.set(Register::B, 0x1F); cpu.registers.set(Register::HL, addr); bus.write(addr, 0x1F); cpu.exec(Opcode::OR(OpcodeParameter::Register_Register(Register::B, Register::HL)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0x1F | 0x1F); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xC000; cpu.registers.set(Register::B, 0x00); cpu.registers.set(Register::HL, addr); bus.write(addr, 0x00); cpu.exec(Opcode::OR(OpcodeParameter::Register_Register(Register::B, Register::HL)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0x00); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0x1F); cpu.exec(Opcode::OR(OpcodeParameter::Register_U8(Register::B, 0x1F)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0x1F | 0x1F); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0x00); cpu.exec(Opcode::OR(OpcodeParameter::Register_U8(Register::B, 0x00)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0x00); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_xor_instructions() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0xF1); cpu.registers.set(Register::C, 0x1F); cpu.exec(Opcode::XOR(OpcodeParameter::Register_Register(Register::B, Register::C)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0xF1 ^ 0x1F); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0x00); cpu.registers.set(Register::C, 0x00); cpu.exec(Opcode::XOR(OpcodeParameter::Register_Register(Register::B, Register::C)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0x00); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xC000; cpu.registers.set(Register::B, 0x1F); cpu.registers.set(Register::HL, addr); bus.write(addr, 0xF1); cpu.exec(Opcode::XOR(OpcodeParameter::Register_Register(Register::B, Register::HL)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0x1F ^ 0xF1); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xC000; cpu.registers.set(Register::B, 0x00); cpu.registers.set(Register::HL, addr); bus.write(addr, 0x00); cpu.exec(Opcode::XOR(OpcodeParameter::Register_Register(Register::B, Register::HL)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0x00); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0x1F); cpu.exec(Opcode::XOR(OpcodeParameter::Register_U8(Register::B, 0xF1)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0x1F ^ 0xF1); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0x00); cpu.exec(Opcode::XOR(OpcodeParameter::Register_U8(Register::B, 0x00)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0x00); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_cp_instructions() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0xF1); cpu.exec(Opcode::CP(OpcodeParameter::Register_U8(Register::B, 0xF1)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0b00110000); cpu.exec(Opcode::CP(OpcodeParameter::Register_U8(Register::B, 0b00000100)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0b01000000); cpu.exec(Opcode::CP(OpcodeParameter::Register_U8(Register::B, 0b10000000)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0xF1); cpu.registers.set(Register::C, 0xF1); cpu.exec(Opcode::CP(OpcodeParameter::Register_Register(Register::B, Register::C)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0b00110000); cpu.registers.set(Register::C, 0b00000100); cpu.exec(Opcode::CP(OpcodeParameter::Register_Register(Register::B, Register::C)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0b01000000); cpu.registers.set(Register::C, 0b10000000); cpu.exec(Opcode::CP(OpcodeParameter::Register_Register(Register::B, Register::C)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xC000; cpu.registers.set(Register::B, 0xF1); cpu.registers.set(Register::HL, addr); bus.write(addr, 0xF1); cpu.exec(Opcode::CP(OpcodeParameter::Register_Register(Register::B, Register::HL)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xC000; cpu.registers.set(Register::B, 0b00110000); cpu.registers.set(Register::HL, addr); bus.write(addr, 0b00000100); cpu.exec(Opcode::CP(OpcodeParameter::Register_Register(Register::B, Register::HL)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xC000; cpu.registers.set(Register::B, 0b01000000); cpu.registers.set(Register::HL, addr); bus.write(addr, 0b10000000); cpu.exec(Opcode::CP(OpcodeParameter::Register_Register(Register::B, Register::HL)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::PC), 0x101); } #[test] fn test_add_instructions() { // let mut bus = Bus::new(); let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0b00001000); cpu.registers.set(Register::C, 0b00001000); cpu.exec(Opcode::ADD(OpcodeParameter::Register_Register(Register::B, Register::C)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0b00010000); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0b10000000); cpu.registers.set(Register::C, 0b10000000); cpu.exec(Opcode::ADD(OpcodeParameter::Register_Register(Register::B, Register::C)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0x00); cpu.registers.set(Register::B, 0x80); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.exec(Opcode::ADD(OpcodeParameter::Register_Register(Register::A, Register::B)), &mut bus); assert_eq!(cpu.registers.get(Register::A), 0x80); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xC000; cpu.registers.set(Register::B, 40); cpu.registers.set(Register::HL, addr); bus.write(addr, 40); cpu.exec(Opcode::ADD(OpcodeParameter::Register_Register(Register::B, Register::HL)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 80); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 40); cpu.exec(Opcode::ADD(OpcodeParameter::Register_U8(Register::B, 40)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 80); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); let addr = 0xC000; cpu.registers.set(Register::HL, addr); bus.write(addr, 40); cpu.exec(Opcode::ADD(OpcodeParameter::Register_U8(Register::HL, 40)), &mut bus); assert_eq!(bus.read(addr), 80); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 40); cpu.exec(Opcode::ADD(OpcodeParameter::Register_I8(Register::B, -40 as i8)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::SP, 0x0000); cpu.exec(Opcode::ADD(OpcodeParameter::Register_I8(Register::SP, 0x01)), &mut bus); assert_eq!(cpu.registers.get(Register::SP), 0x0001); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.registers.set(Register::SP, 0x0100); cpu.exec(Opcode::ADD(OpcodeParameter::Register_I8(Register::SP, 0x01)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::SP), 0x0101); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::SP, 0x00FF); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::ADD(OpcodeParameter::Register_I8(Register::SP, 0x01)), &mut bus); assert_eq!(cpu.registers.get(Register::SP), 0x0100); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::SP, 0x7FFF); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::ADD(OpcodeParameter::Register_I8(Register::SP, 0x01)), &mut bus); assert_eq!(cpu.registers.get(Register::SP), 0x8000); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::SP, 0x000F); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::ADD(OpcodeParameter::Register_I8(Register::SP, 0x01)), &mut bus); assert_eq!(cpu.registers.get(Register::SP), 0x0010); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::SP, 0xFFFF); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::ADD(OpcodeParameter::Register_I8(Register::SP, 0x01)), &mut bus); assert_eq!(cpu.registers.get(Register::SP), 0x0000); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::SP, 0x0000); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::ADD(OpcodeParameter::Register_I8(Register::SP, (0xFF as u8) as i8)), &mut bus); assert_eq!(cpu.registers.get(Register::SP), 0xFFFF); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::SP, 0x0001); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::ADD(OpcodeParameter::Register_I8(Register::SP, (0xFF as u8) as i8)), &mut bus); assert_eq!(cpu.registers.get(Register::SP), 0x0000); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::BC, 0b0000100000000000); cpu.registers.set(Register::HL, 0b0000100000000000); cpu.exec(Opcode::ADD(OpcodeParameter::Register_Register(Register::BC, Register::HL)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get(Register::BC), 0b0001000000000000); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::HL, 0x0000); cpu.registers.set(Register::SP, 0x8000); cpu.exec(Opcode::ADD(OpcodeParameter::Register_Register(Register::HL, Register::SP)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::HL), 0x8000); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::HL, 0x0001); cpu.registers.set(Register::SP, 0x00FF); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::ADD(OpcodeParameter::Register_Register(Register::HL, Register::SP)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::HL), 0x0100); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set_flag(FlagRegister::Zero, true); cpu.registers.set_flag(FlagRegister::Substract, true); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.registers.set(Register::HL, 0x2608); cpu.exec(Opcode::ADD(OpcodeParameter::Register_Register(Register::HL, Register::HL)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::HL), 0x4C10); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.registers.set(Register::SP, 0x000F); cpu.registers.set(Register::HL, 0x0001); cpu.exec(Opcode::ADD(OpcodeParameter::Register_Register(Register::HL, Register::SP)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::HL), 0x0010); assert_eq!(cpu.registers.get(Register::PC), 0x101); } #[test] fn test_adc_instructions() { let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, true); cpu.registers.set(Register::A, 0xFE); cpu.exec(Opcode::ADC(OpcodeParameter::Register_U8(Register::A, 0x01)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::A), 0x00); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, true); cpu.registers.set(Register::A, 0x00); cpu.exec(Opcode::ADC(OpcodeParameter::Register_U8(Register::A, 0x0F)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::A), 0x10); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, true); cpu.registers.set(Register::A, 0x01); cpu.exec(Opcode::ADC(OpcodeParameter::Register_U8(Register::A, 0x0F)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::A), 0x11); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_sbc_instructions() { let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, true); cpu.registers.set(Register::A, 0x00); cpu.exec(Opcode::SBC(OpcodeParameter::Register_U8(Register::A, 0x00)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::A), 0xFF); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_sub_instructions() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0b00001000); cpu.registers.set(Register::C, 0b00001000); cpu.exec(Opcode::SUB(OpcodeParameter::Register_Register(Register::B, Register::C)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 0); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0b00010000); cpu.registers.set(Register::C, 0b00011000); cpu.exec(Opcode::SUB(OpcodeParameter::Register_Register(Register::B, Register::C)), &mut bus); assert_eq!(cpu.registers.get(Register::B), 248); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let mut bus = Bus::new(); let addr = 0xC000; cpu.registers.set(Register::B, 40); cpu.registers.set(Register::HL, addr); bus.write(addr, 40); cpu.exec(Opcode::SUB(OpcodeParameter::Register_Register(Register::B, Register::HL)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get(Register::B), 0); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 40); cpu.exec(Opcode::SUB(OpcodeParameter::Register_U8(Register::B, 40)), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get(Register::B), 0); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_inc_instructions() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0); cpu.exec(Opcode::INC(true, false, Register::A), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b00001111); cpu.exec(Opcode::INC(true, false, Register::A), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let addr = 0xC000; cpu.registers.set(Register::HL, addr); bus.write(addr, 0b00001111); cpu.exec(Opcode::INC(true, true, Register::HL), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(bus.read(addr), 0b00010000); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::BC, 0b0000111111111111); cpu.exec(Opcode::INC(true, false, Register::BC), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get(Register::BC), 0b0001000000000000); assert_eq!(cpu.registers.get(Register::PC), 0x101); } #[test] fn test_dec_instructions() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 1); cpu.exec(Opcode::DEC(true, false, Register::A), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get(Register::A), 0); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b00010000); cpu.exec(Opcode::DEC(true, false, Register::A), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get(Register::A), 0b00001111); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); let addr = 0xC000; cpu.registers.set(Register::HL, addr); bus.write(addr, 0b00010000); cpu.exec(Opcode::DEC(true, true, Register::HL), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(bus.read(addr), 0b00001111); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::BC, 0b0001000000000000); cpu.exec(Opcode::DEC(true, false, Register::BC), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get(Register::BC), 0b0000111111111111); assert_eq!(cpu.registers.get(Register::PC), 0x101); } #[test] fn test_rla_instruction() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b00000001); cpu.registers.set_flag(FlagRegister::Carry, true); cpu.exec(Opcode::RLA, &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::A), 0b00000011); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b10000000); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::RLA, &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::A), 0b00000000); assert_eq!(cpu.registers.get(Register::PC), 0x101); } #[test] fn test_rra_instruction() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b00000001); cpu.registers.set_flag(FlagRegister::Carry, true); cpu.exec(Opcode::RRA, &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::A), 0b10000000); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b10000000); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::RRA, &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::A), 0b01000000); assert_eq!(cpu.registers.get(Register::PC), 0x101); } #[test] fn test_prefix_cb_rlc_instruction() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b00000001); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RLC(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::A), 0b00000010); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b10000000); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RLC(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::A), 0b00000001); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RLC(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::A), 0); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); let addr = 0xC000; cpu.registers.set(Register::HL, addr); bus.write(addr, 0b00000001); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RLC(Register::HL))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(bus.read(addr), 0b00000010); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_prefix_cb_rrc_instruction() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b00000001); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RRC(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::A), 0b10000000); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b00000010); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RRC(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::A), 0b00000001); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RRC(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::A), 0); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); let addr = 0xC000; cpu.registers.set(Register::HL, addr); bus.write(addr, 0b00000001); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RRC(Register::HL))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(bus.read(addr), 0b10000000); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_prefix_cb_rl_instruction() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b00000001); cpu.registers.set_flag(FlagRegister::Carry, true); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RL(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::A), 0b00000011); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b10000000); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RL(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::A), 0b00000000); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b00000010); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RL(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::A), 0b00000100); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); let addr = 0xC000; bus.write(addr, 0b00000010); cpu.registers.set(Register::HL, addr); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RL(Register::HL))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(bus.read(addr), 0b00000100); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_prefix_cb_rr_instruction() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b00000001); cpu.registers.set_flag(FlagRegister::Carry, true); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RR(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::A), 0b10000000); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b01000000); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RR(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::A), 0b00100000); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b00000001); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RR(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::A), 0b00000000); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); let addr = 0xC000; bus.write(addr, 0b01000000); cpu.registers.set(Register::HL, addr); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RR(Register::HL))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(bus.read(addr), 0b00100000); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_prefix_cb_sla_instruction() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0x01); cpu.registers.set_flag(FlagRegister::Zero, true); cpu.registers.set_flag(FlagRegister::Substract, true); cpu.registers.set_flag(FlagRegister::HalfCarry, true); cpu.registers.set_flag(FlagRegister::Carry, true); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::SLA(Register::B))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::B), 0x02); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_prefix_cb_sra_instruction() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::B, 0x01); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, false); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::SRA(Register::B))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::B), 0x00); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_prefix_cb_srl_instruction() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b00000010); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::SRL(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::A), 0b00000001); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b00000001); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::SRL(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::A), 0b00000000); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); let addr = 0xC000; bus.write(addr, 0b00000001); cpu.registers.set(Register::HL, addr); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::SRL(Register::HL))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(bus.read(addr), 0b00000000); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_prefix_cb_swap_instruction() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b11110101); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::SWAP(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::A), 0b01011111); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b00000000); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::SWAP(Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::A), 0b00000000); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut bus = Bus::new(); let mut cpu = CPU::new(); let addr = 0xC000; cpu.registers.set(Register::HL, addr); bus.write(addr, 0b11110101); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::SWAP(Register::HL))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(bus.read(addr), 0b01011111); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_prefix_cb_bit_instruction() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b11110101); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I3, Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b11110101); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I4, Register::A))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); let addr = 0xC000; cpu.registers.set(Register::HL, addr); bus.write(addr, 0b11110101); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::BIT(BitIndex::I0 ,Register::HL))), &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_prefix_cb_res_instruction() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b11110101); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I2, Register::A))), &mut bus); assert_eq!(cpu.registers.get_8bit(Register::A), 0b11110001); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); let addr = 0xC000; cpu.registers.set(Register::HL, addr); bus.write(addr, 0b11110101); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::RES(BitIndex::I0 ,Register::HL))), &mut bus); assert_eq!(bus.read(addr), 0b11110100); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_prefix_cb_set_instruction() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0b11110101); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I1, Register::A))), &mut bus); assert_eq!(cpu.registers.get_8bit(Register::A), 0b11110111); assert_eq!(cpu.registers.get(Register::PC), 0x102); let mut cpu = CPU::new(); let addr = 0xC000; cpu.registers.set(Register::HL, addr); bus.write(addr, 0b11110101); cpu.exec(Opcode::PrefixCB(Box::new(Opcode::SET(BitIndex::I3 ,Register::HL))), &mut bus); assert_eq!(bus.read(addr), 0b11111101); assert_eq!(cpu.registers.get(Register::PC), 0x102); } #[test] fn test_daa_instruction() { let mut bus = Bus::new(); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0x0A); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::DAA, &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::A), 0x10); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0x9A); cpu.exec(Opcode::DAA, &mut bus); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), true); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); assert_eq!(cpu.registers.get(Register::A), 0x00); assert_eq!(cpu.registers.get(Register::PC), 0x101); let mut cpu = CPU::new(); cpu.registers.set(Register::A, 0x00); cpu.registers.set_flag(FlagRegister::Zero, false); cpu.registers.set_flag(FlagRegister::Substract, false); cpu.registers.set_flag(FlagRegister::HalfCarry, true); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::DAA, &mut bus); assert_eq!(cpu.registers.get(Register::A), 0x06); assert_eq!(cpu.registers.get_flag(FlagRegister::Zero), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); assert_eq!(cpu.registers.get(Register::PC), 0x101); } #[test] fn test_cpl_instructions() { let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.registers.set(Register::A, 0b11110000); cpu.exec(Opcode::CPL, &mut bus); assert_eq!(cpu.registers.get(Register::A), 0b00001111); assert_eq!(cpu.registers.get(Register::PC), 0x101); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), true); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), true); } #[test] fn test_ccf_instructions() { let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.registers.set_flag(FlagRegister::Substract, true); cpu.registers.set_flag(FlagRegister::HalfCarry, true); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::CCF, &mut bus); assert_eq!(cpu.registers.get(Register::PC), 0x101); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.registers.set_flag(FlagRegister::Substract, true); cpu.registers.set_flag(FlagRegister::HalfCarry, true); cpu.registers.set_flag(FlagRegister::Carry, true); cpu.exec(Opcode::CCF, &mut bus); assert_eq!(cpu.registers.get(Register::PC), 0x101); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), false); } #[test] fn test_scf_instructions() { let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.registers.set_flag(FlagRegister::Substract, true); cpu.registers.set_flag(FlagRegister::HalfCarry, true); cpu.registers.set_flag(FlagRegister::Carry, false); cpu.exec(Opcode::SCF, &mut bus); assert_eq!(cpu.registers.get(Register::PC), 0x101); assert_eq!(cpu.registers.get_flag(FlagRegister::Substract), false); assert_eq!(cpu.registers.get_flag(FlagRegister::HalfCarry), false); assert_eq!(cpu.registers.get_flag(FlagRegister::Carry), true); } #[test] fn test_nop_instructions() { let mut cpu = CPU::new(); let mut bus = Bus::new(); cpu.exec(Opcode::NOP, &mut bus); assert_eq!(cpu.registers.get(Register::PC), 0x101); } }