diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml index fc066c9..942e3e8 100644 --- a/.idea/dictionaries/project.xml +++ b/.idea/dictionaries/project.xml @@ -13,6 +13,7 @@ reti rrca rrla + vram \ No newline at end of file diff --git a/src/instructions.rs b/src/instructions.rs deleted file mode 100644 index a84cfd2..0000000 --- a/src/instructions.rs +++ /dev/null @@ -1,636 +0,0 @@ -use crate::registers::Registers; -struct CPU { - registers: Registers, - pc: u16, - bus: MemoryBus, - sp: u16, -} - -struct MemoryBus { - memory: [u8; 0xFFFF] -} -impl MemoryBus { - fn read_byte(&self, address: u16) -> u8 { - self.memory[address as usize] - } - fn write_byte(&mut self, address: u16, value: u8) { - self.memory[address as usize] = value; - } - -} -#[derive(Clone, Copy)] -enum Target { - U8Register(TargetRegister), - U16Register(TargetU16Register), - Address(u16), -} -#[derive(Clone, Copy)] -enum Condition { - NZ, // Not Zero - Z, // Zero - NC, // Not Carry - C, // Carry - None -} - -#[derive(Clone, Copy)] -enum LoadTarget{ - CopyR8R8(TargetRegister, TargetRegister), - CopyR8N8(TargetRegister, u8), - CopyR16N16(TargetU16Register, u16), - CopyHLR8(TargetRegister), - CopyHLN8(u8), - CopyR8HL(TargetRegister), - CopyR16A(TargetU16Register), - CopyN16A(u16), - CopyHN16A(u16), - CopyHCA, - CopyAR16(TargetU16Register), - CopyAN16(u16), - CopyHAN16(u16), - CopyHAC, - CopyHLIA, - CopyHLDA, - CopyAHLD, - CopyAHLI, - CopySPN16(u16), - CopyN16SP(u16), - CopyHLSPE8(i8), - CopySPHL, -} - - -enum Instruction { - ADC(Target), - ADD(Target), - ADDHL(TargetU16Register), - ADDSP(u8), - AND(Target), - BIT(u8, Target), - CALL(Condition, u16), - CCF, - CP(Target), - CPL, - DAA, - DEC(Target), - DECHL(TargetU16Register), - DI, - EI, - HALT, - INC(Target), - INCHL(TargetU16Register), - JP(Condition, u16), - JPHL, - JR(Condition, i8), - LD(LoadTarget), - NOP, - OR(Target), - POP(TargetU16Register), - PUSH(TargetU16Register), - RES(u8, Target), - RET(Condition), - RETI, - RL(Target), - RLC(Target), - RR(Target), - RRC(Target), - RST(u8), - SBC(Target), - SCF, - SET(u8, Target), - SLA(Target), - SRA(Target), - SRL(Target), - STOP, - SUB(Target), - SWAP(Target), - XOR(Target), -} -#[derive(Clone, Copy)] -enum TargetRegister { A, B, C, D, E, H, L, } -#[derive(Clone, Copy)] -enum TargetU16Register {AF, BC, DE, HL, SP, PC} -impl CPU { - fn check_condition(&self, condition: Condition) -> bool { - match condition { - Condition::NZ => !self.registers.f.zero, - Condition::Z => self.registers.f.zero, - Condition::NC => !self.registers.f.carry, - Condition::C => self.registers.f.carry, - Condition::None => true, - } - } - - fn get_u8_reg_value(&mut self, target: TargetRegister) -> u8 { - match target { - TargetRegister::A => { self.registers.a } - TargetRegister::B => { self.registers.b } - TargetRegister::C => { self.registers.c } - TargetRegister::D => { self.registers.d } - TargetRegister::E => { self.registers.e } - TargetRegister::H => { self.registers.h } - TargetRegister::L => { self.registers.l } - } - } - fn set_u8_reg_value(&mut self, target: TargetRegister, value: u8) { - match target { - TargetRegister::A => { self.registers.a = value } - TargetRegister::B => { self.registers.b = value } - TargetRegister::C => { self.registers.c = value } - TargetRegister::D => { self.registers.d = value } - TargetRegister::E => { self.registers.e = value } - TargetRegister::H => { self.registers.h = value } - TargetRegister::L => { self.registers.l = value } - } - } - fn get_u16_reg_value(&mut self, target: TargetU16Register) -> u16 { - match target { - TargetU16Register::AF => {self.registers.get_af()} - TargetU16Register::BC => {self.registers.get_bc()} - TargetU16Register::DE => {self.registers.get_de()} - TargetU16Register::HL => {self.registers.get_hl()} - TargetU16Register::SP => {self.sp} - TargetU16Register::PC => {self.pc} - } - } - fn set_u16_reg_value(&mut self, target: TargetU16Register, value: u16) { - match target { - TargetU16Register::AF => {self.registers.set_af(value)} - TargetU16Register::BC => {self.registers.set_bc(value)} - TargetU16Register::DE => {self.registers.set_de(value)} - TargetU16Register::HL => {self.registers.set_hl(value)} - TargetU16Register::SP => {self.sp=value} - TargetU16Register::PC => {self.pc=value} - } - } - fn push_stack(&mut self, value: u16) { - let low = (value & 0xFF) as u8; - let high = (value >> 8) as u8; - self.bus.write_byte(self.sp - 1, high); - self.bus.write_byte(self.sp - 2, low); - self.sp = self.sp.wrapping_sub(2); - } - fn pop_stack(&mut self) -> u16 { - let low = (self.bus.read_byte(self.sp) as u16) << 8; - let high = self.bus.read_byte(self.sp + 1) as u16; - self.sp = self.sp.wrapping_add(2); - high | low - } - - fn get_target_value(&mut self, target: Target) -> u8 { - match target { - Target::U8Register(target_register) => { self.get_u8_reg_value(target_register) }, - Target::U16Register(target_register) => { - let address = self.get_u16_reg_value(target_register); - self.bus.read_byte(address) - }, - Target::Address(address) => { self.bus.read_byte(address) }, - } - } - fn set_target_value(&mut self, target: Target, value: u8) { - match target { - Target::U8Register(target_register) => { self.set_u8_reg_value(target_register, value) }, - Target::U16Register(target_register) => { - let address = self.get_u16_reg_value(target_register); - self.bus.write_byte(address, value) - }, - Target::Address(address) => { self.bus.write_byte(address, value) }, - } - } - - /// - fn execute(&mut self, instruction: Instruction) { - match instruction { - Instruction::ADC(target) => { - let value = self.get_target_value(target); - let (mut new_value, did_overflow) = self.registers.a.overflowing_add(value); - new_value += did_overflow as u8; - self.registers.a = new_value; - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = false; - self.registers.f.carry = did_overflow; - self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF; - } - Instruction::ADD(target) => { - let value = self.get_target_value(target); - let (new_value, did_overflow) = self.registers.a.overflowing_add(value); - self.registers.a = new_value; - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = false; - self.registers.f.carry = did_overflow; - self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF; - } - Instruction::ADDHL(target) => { - let value = self.get_u16_reg_value(target); - let (new_value, did_overflow) = self.registers.get_hl().overflowing_add(value); - self.registers.set_hl(new_value); - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = false; - self.registers.f.carry = did_overflow; - self.registers.f.half_carry = (new_value & 0xFF) + (value & 0xFF) > 0xFF; - } - Instruction::ADDSP(value) => { - let offset = (value as i16) as u16; - let (new_value, did_overflow) = self.sp.overflowing_add(offset); - self.sp = new_value; - self.registers.f.zero = false; - self.registers.f.subtract = false; - self.registers.f.carry = did_overflow; - self.registers.f.half_carry = (new_value & 0xFF) + (offset & 0xFF) > 0xFF; - } - Instruction::AND(target) => { - let value = self.get_target_value(target); - self.registers.a = value & self.registers.a; - self.registers.f.zero = self.registers.a == 0; - self.registers.f.subtract = false; - self.registers.f.carry = false; - self.registers.f.half_carry = true; - } - Instruction::BIT(bit, target) => { - let value = self.get_target_value(target); - self.registers.f.zero = value >> bit & 0x1 == 0; - self.registers.f.subtract = false; - self.registers.f.half_carry = true; - } - Instruction::CALL(condition, address) => { - if self.check_condition(condition) { - self.sp = self.sp.wrapping_sub(2); - let pc = self.pc; - self.bus.write_byte(self.sp + 1, ((pc >> 8) & 0xFF) as u8); - self.bus.write_byte(self.sp, (pc & 0xFF) as u8); - self.pc = address; - } - } - Instruction::CCF => { - self.registers.f.subtract = false; - self.registers.f.half_carry = false; - self.registers.f.carry = !self.registers.f.carry; - } - Instruction::CP(target) => { - let value = self.get_target_value(target); - let (new_value, did_overflow) = self.registers.a.overflowing_sub(value); - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = true; - self.registers.f.carry = did_overflow; - self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF; - } - Instruction::CPL => { - self.registers.a = !self.registers.a; - self.registers.f.subtract = true; - self.registers.f.half_carry = true; - } - Instruction::DAA => { - let new_value; - let did_overflow; - let mut adjustment: u8 = 0; - if self.registers.f.subtract { - if self.registers.f.half_carry { - adjustment += 0x6; - } - if self.registers.f.carry { - adjustment += 0x60; - } - (new_value, did_overflow) = self.registers.a.overflowing_sub(adjustment); - } else { - if self.registers.f.half_carry || self.registers.a & 0xF > 0x9 { - adjustment += 0x6; - } - if self.registers.f.carry || self.registers.a > 0x99 { - adjustment += 0x60; - } - (new_value, did_overflow) = self.registers.a.overflowing_add(adjustment); - } - self.registers.a = new_value; - self.registers.f.carry = did_overflow; - self.registers.f.zero = new_value == 0; - self.registers.f.half_carry = false; - } - Instruction::DEC(target) => { - match target { - Target::U8Register(target) => { - let value = self.get_u8_reg_value(target); - let (new_value, _) = value.overflowing_sub(1); - self.set_u8_reg_value(target, new_value); - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = true; - self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF; - } - Target::U16Register(target) => { - let value = self.get_u16_reg_value(target); - let new_value = value.wrapping_sub(1); - self.set_u16_reg_value(target, new_value); - } - Target::Address(_) => {} - } - } - Instruction::DECHL(register) => { - let target = Target::U16Register(register); - let value = self.get_target_value(target); - let new_value = value.wrapping_sub(1); - self.set_target_value(target, new_value); - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = true; - self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF; - } - Instruction::DI => {} - Instruction::EI => {} - Instruction::HALT => {todo!();} - - Instruction::INC(target) => { - match target { - Target::U8Register(target) => { - let value = self.get_u8_reg_value(target); - let (new_value, _) = value.overflowing_add(1); - self.set_u8_reg_value(target, new_value); - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = false; - self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF; - } - Target::U16Register(target) => { - let value = self.get_u16_reg_value(target); - let new_value = value.wrapping_add(1); - self.set_u16_reg_value(target, new_value); - } - Target::Address(_) => {} - } - } - Instruction::INCHL(register) => { - let target = Target::U16Register(register); - let value = self.get_target_value(target); - let new_value = value.wrapping_add(1); - self.set_target_value(target, new_value); - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = true; - self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF; - } - Instruction::JP(condition, address) => { - if self.check_condition(condition) { - self.pc = address; - } - } - Instruction::JPHL => { - self.pc = self.registers.get_hl(); - } - Instruction::JR(condition, offset) => { - if self.check_condition(condition) { - self.pc = if offset.is_negative() { - self.pc.wrapping_sub(offset.abs() as u16) - } else { - self.pc.wrapping_add(offset as u16) - } - } - } - Instruction::LD(target) => { - match target { - LoadTarget::CopyR8R8(dest_register, source_register) => { - let value = self.get_u8_reg_value(source_register); - self.set_u8_reg_value(dest_register, value); - } - LoadTarget::CopyR8N8(dest_register, value) => { - self.set_u8_reg_value(dest_register, value); - } - LoadTarget::CopyR16N16(dest_register, value) => { - self.set_u16_reg_value(dest_register, value); - } - LoadTarget::CopyHLR8(source_register) => { - let value = self.get_u8_reg_value(source_register); - let address = self.registers.get_hl(); - self.bus.write_byte(address, value); - } - LoadTarget::CopyHLN8(value) => { - let address = self.registers.get_hl(); - self.bus.write_byte(address, value); - } - LoadTarget::CopyR8HL(dest_register) => { - let address = self.registers.get_hl(); - let value = self.bus.read_byte(address); - self.set_u8_reg_value(dest_register, value); - } - LoadTarget::CopyR16A(dest_register) => { - let address = self.get_u16_reg_value(dest_register); - self.bus.write_byte(address, self.registers.a); - } - LoadTarget::CopyN16A(address) => { - self.bus.write_byte(address, self.registers.a); - } - LoadTarget::CopyHN16A(address) => { - if address >= 0xFF00 { - self.bus.write_byte(address, self.registers.a) - } - } - LoadTarget::CopyHCA => { - let address = 0xFF00 + self.registers.c as u16; - self.bus.write_byte(address, self.registers.a) - } - LoadTarget::CopyAR16(source_register) => { - let address = self.get_u16_reg_value(source_register); - self.registers.a = self.bus.read_byte(address); - } - LoadTarget::CopyAN16(address) => { - self.registers.a = self.bus.read_byte(address); - } - LoadTarget::CopyHAN16(address) => { - if address >= 0xFF00 { - self.registers.a = self.bus.read_byte(address) - } - } - LoadTarget::CopyHAC => { - self.registers.a = self.bus.read_byte(0xFF00+self.registers.c as u16) - } - LoadTarget::CopyHLIA => { - let address = self.registers.get_hl(); - self.bus.write_byte(address, self.registers.a); - self.registers.set_hl(address.wrapping_add(1)); - } - LoadTarget::CopyHLDA => { - let address = self.registers.get_hl(); - self.bus.write_byte(address, self.registers.a); - self.registers.set_hl(address.wrapping_sub(1)); - } - LoadTarget::CopyAHLI => { - let address = self.registers.get_hl(); - self.registers.a = self.bus.read_byte(address); - self.registers.set_hl(address.wrapping_add(1)); - } - LoadTarget::CopyAHLD => { - let address = self.registers.get_hl(); - self.registers.a = self.bus.read_byte(address); - self.registers.set_hl(address.wrapping_sub(1)); - } - LoadTarget::CopySPN16(value) => { - self.sp = value; - } - LoadTarget::CopyN16SP(address) => { - self.bus.write_byte(address, (0xF & self.sp) as u8); - self.bus.write_byte(address + 1, (self.sp >> 8) as u8); - } - LoadTarget::CopyHLSPE8(value) => { - - let new_value = match value.is_negative() { - true => { self.sp.wrapping_sub(value.abs() as u16) } - false => { self.sp.wrapping_add(value as u16) } - }; - self.registers.set_hl(new_value); - self.registers.f.zero = false; - self.registers.f.subtract = false; - self.registers.f.carry = (new_value & 0xFF) + (self.sp & 0xFF) > 0xFF; - self.registers.f.half_carry = (new_value & 0xF) + (self.sp & 0xF) > 0xF; - - } - LoadTarget::CopySPHL => { - self.sp = self.registers.get_hl(); - } - } - } - Instruction::NOP => {} - Instruction::OR(target) => { - let value = self.get_target_value(target); - self.registers.a = value | self.registers.a; - self.registers.f.zero = self.registers.a == 0; - self.registers.f.subtract = false; - self.registers.f.carry = false; - self.registers.f.half_carry = false; - } - Instruction::POP(target) => { - let value = self.pop_stack(); - self.set_u16_reg_value(target, value); - } - Instruction::PUSH(target) => { - let value = self.get_u16_reg_value(target); - self.push_stack(value); - } - Instruction::RES(bit, target) => { - let mut value = self.get_target_value(target); - value &= !(1 << bit); - self.set_target_value(target, value); - } - Instruction::RET(condition) => { - if self.check_condition(condition) { - self.pc = self.pop_stack(); - } - } - Instruction::RETI => { - self.pc = self.pop_stack(); - } - Instruction::RL(target) => { - let old_value = self.get_target_value(target); - let old_carry = self.registers.f.carry; - self.registers.f.carry = old_value & 0x80 == 0x80; - let new_value = (self.registers.a << 1) | (if old_carry { 0x01 } else { 0 }); - self.set_target_value(target, new_value); - self.registers.f.zero = false; - self.registers.f.subtract = false; - self.registers.f.half_carry = false; - } - Instruction::RLC(target) => { - let old_value = self.get_target_value(target); - self.registers.f.carry = old_value & 0x80 == 0x80; - let new_value = (self.registers.a << 1) | (if self.registers.f.carry { 0x1 } else { 0 }); - self.set_target_value(target, new_value); - self.registers.f.zero = false; - self.registers.f.subtract = false; - self.registers.f.half_carry = false; - } - Instruction::RR(target) => { - let old_value = self.get_target_value(target); - let old_carry = self.registers.f.carry; - self.registers.f.carry = old_value & 0x1 == 0x1; - let new_value = (self.registers.a >> 1) | (if old_carry { 0x80 } else { 0 }); - self.set_target_value(target, new_value); - self.registers.f.zero = false; - self.registers.f.subtract = false; - self.registers.f.half_carry = false; - } - Instruction::RRC(target) => { - let old_value = self.get_target_value(target); - self.registers.f.carry = old_value & 0x1 == 0x1; - let new_value = (self.registers.a >> 1) | (if self.registers.f.carry { 0x80 } else { 0 }); - self.set_target_value(target, new_value); - self.registers.f.zero = false; - self.registers.f.subtract = false; - self.registers.f.half_carry = false; - } - Instruction::RST(idx) => { - self.push_stack(self.pc); - let address = self.bus.read_byte((idx as u16) * 8) as u16; - self.pc = address; - } - Instruction::SBC(target) => { - let value = self.get_target_value(target); - let (mut new_value, did_overflow) = self.registers.a.overflowing_sub(value); - new_value -= did_overflow as u8; - self.registers.a = new_value; - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = true; - self.registers.f.carry = did_overflow; - self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF; - } - Instruction::SCF => { - self.registers.f.carry = true; - self.registers.f.subtract = false; - self.registers.f.half_carry = false; - } - Instruction::SET(bit, target) => { - let mut value = self.get_target_value(target); - value |= 1 << bit; - self.set_target_value(target, value); - } - Instruction::SLA(target) => { - let value = self.get_target_value(target); - let new_value = value << 1; - self.set_target_value(target, new_value); - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = false; - self.registers.f.carry = value & 0x80 == 0x80; - self.registers.f.half_carry = false; - } - Instruction::SRA(target) => { - let value = self.get_target_value(target); - let new_value = value >> 1 | (if value & 0x80 == 0x80 { 0x80 } else { 0 }); - self.set_target_value(target, new_value); - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = false; - self.registers.f.carry = value & 0x80 == 0x80; - self.registers.f.half_carry = false; - } - Instruction::SRL(target) => { - let value = self.get_target_value(target); - let new_value = value >> 1; - self.set_target_value(target, new_value); - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = false; - self.registers.f.carry = value & 0x1 == 0x1; - self.registers.f.half_carry = false; - } - Instruction::STOP => { - - } - Instruction::SUB(target) => { - let value = self.get_target_value(target); - let (new_value, did_overflow) = self.registers.a.overflowing_sub(value); - self.registers.a = new_value; - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = true; - self.registers.f.carry = did_overflow; - self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF; - } - Instruction::SWAP(target) => { - let value = self.get_target_value(target); - let new_value = ((value & 0xF0) >> 4) | ((value & 0x0F) << 4); - self.set_target_value(target, new_value); - self.registers.f.zero = new_value == 0; - self.registers.f.subtract = false; - self.registers.f.carry = false; - self.registers.f.half_carry = false; - } - Instruction::XOR(target) => { - let value = self.get_target_value(target); - self.registers.a = value ^ self.registers.a; - self.registers.f.zero = self.registers.a == 0; - self.registers.f.subtract = false; - self.registers.f.carry = false; - self.registers.f.half_carry = false; - } - } - } -} diff --git a/src/main.rs b/src/main.rs index b2ee0a1..a7fd1df 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,1274 @@ mod registers; -mod instructions; +use crate::registers::FlagsRegister; +use crate::registers::Registers; + + + +struct CPU { + registers: Registers, + pc: u16, + bus: MemoryBus, + sp: u16, +} +const VRAM_BEGIN: usize = 0x8000; +const VRAM_END: usize = 0x9FFF; +struct GPU { vram: Vec, tile_set: [[[TilePixelValue; 8]; 8]; 384] } +#[derive(Copy, Clone)] +enum TilePixelValue { Three, Two, One, Zero } + +impl GPU { + fn read_vram(&self, address: usize) -> u8 { + self.vram[address] + } + fn write_vram(&mut self, index: usize, value: u8) { + self.vram[index] = value; + // If our index is greater than 0x1800, we're not writing to the tile set storage + // so we can just return. + if index >= 0x1800 { return } + + // Tiles rows are encoded in two bytes with the first byte always + // on an even address. Bitwise ANDing the address with 0xffe + // gives us the address of the first byte. + // For example: `12 & 0xFFFE == 12` and `13 & 0xFFFE == 12` + let normalized_index = index & 0xFFFE; + + // First we need to get the two bytes that encode the tile row. + let byte1 = self.vram[normalized_index]; + let byte2 = self.vram[normalized_index + 1]; + + // A tiles is 8 rows tall. Since each row is encoded with two bytes a tile + // is therefore 16 bytes in total. + let tile_index = index / 16; + // Every two bytes is a new row + let row_index = (index % 16) / 2; + + // Now we're going to loop 8 times to get the 8 pixels that make up a given row. + for pixel_index in 0..8 { + // To determine a pixel's value we must first find the corresponding bit that encodes + // that pixels value: + // 1111_1111 + // 0123 4567 + // + // As you can see the bit that corresponds to the nth pixel is the bit in the nth + // position *from the left*. Bits are normally indexed from the right. + // + // To find the first pixel (a.k.a pixel 0) we find the left most bit (a.k.a bit 7). For + // the second pixel (a.k.a pixel 1) we first the second most left bit (a.k.a bit 6) and + // so on. + // + // We then create a mask with a 1 at that position and 0s everywhere else. + // + // Bitwise ANDing this mask with our bytes will leave that particular bit with its + // original value and every other bit with a 0. + let mask = 1 << (7 - pixel_index); + let lsb = byte1 & mask; + let msb = byte2 & mask; + + // If the masked values are not 0 the masked bit must be 1. If they are 0, the masked + // bit must be 0. + // + // Finally we can tell which of the four tile values the pixel is. For example, if the least + // significant byte's bit is 1 and the most significant byte's bit is also 1, then we + // have tile value `Three`. + let value = match (lsb != 0, msb != 0) { + (true, true) => TilePixelValue::Three, + (false, true) => TilePixelValue::Two, + (true, false) => TilePixelValue::One, + (false, false) => TilePixelValue::Zero, + }; + + self.tile_set[tile_index][row_index][pixel_index] = value; + } + + } +} +struct MemoryBus { + memory: [u8; 0xFFFF], + gpu: GPU, +} +impl MemoryBus { + fn read_byte(&self, address: u16) -> u8 { + let address = address as usize; + match address { + VRAM_BEGIN ..= VRAM_END => { + self.gpu.read_vram(address - VRAM_BEGIN) + } + _ => self.memory[address as usize] + } + } + fn write_byte(&mut self, address: u16, value: u8) { + let address = address as usize; + match address { + VRAM_BEGIN ..= VRAM_END => { + self.gpu.write_vram(address - VRAM_BEGIN, value) + } + _ => self.memory[address as usize] = value + } + } + fn read_u16(&self, address: u16) -> u16 { + let low = self.read_byte(address) as u16; + let high = self.read_byte(address.wrapping_add(1)) as u16; + high << 8 | low + } + fn write_u16(&mut self, address: u16, value: u16) { + let low = (value & 0xFF) as u8; + let high = ((value >> 8) & 0xFF) as u8; + self.write_byte(address, low); + self.write_byte(address.wrapping_add(1), high); + } +} +#[derive(Clone, Copy)] +enum Target { + U8Register(TargetRegister), + U16Register(TargetU16Register), + Address(u16), + Immediate(u8) +} +#[derive(Clone, Copy)] +enum Condition { + NZ, // Not Zero + Z, // Zero + NC, // Not Carry + C, // Carry + None +} + +#[derive(Clone, Copy)] +enum LoadTarget{ + CopyR8R8(TargetRegister, TargetRegister), + CopyR8N8(TargetRegister, u8), + CopyR16N16(TargetU16Register, u16), + CopyHLR8(TargetRegister), + CopyHLN8(u8), + CopyR8HL(TargetRegister), + CopyR16A(TargetU16Register), + CopyN16A(u16), + CopyHN16A(u16), + CopyHCA, + CopyAR16(TargetU16Register), + CopyAN16(u16), + CopyHAN16(u16), + CopyHAC, + CopyHLIA, + CopyHLDA, + CopyAHLD, + CopyAHLI, + CopySPN16(u16), + CopyN16SP(u16), + CopyHLSPE8(i8), + CopySPHL, + CopyPortA(Target), + CopyAPort(Target) +} + + +enum Instruction { + ADC(Target), + ADD(Target), + ADDHL(TargetU16Register), + ADDSP(u8), + AND(Target), + BIT(u8, Target), + CALL(Condition, u16), + CCF, + CP(Target), + CPL, + DAA, + DEC(Target), + DECHL(TargetU16Register), + DI, + EI, + HALT, + INC(Target), + INCHL(TargetU16Register), + JP(Condition, u16), + JPHL, + JR(Condition, i8), + LD(LoadTarget), + NOP, + OR(Target), + POP(TargetU16Register), + PUSH(TargetU16Register), + RES(u8, Target), + RET(Condition), + RETI, + RL(Target), + RLC(Target), + RR(Target), + RRC(Target), + RST(u8), + SBC(Target), + SCF, + SET(u8, Target), + SLA(Target), + SRA(Target), + SRL(Target), + STOP(u8), + SUB(Target), + SWAP(Target), + XOR(Target), +} +#[derive(Clone, Copy)] +enum TargetRegister { A, B, C, D, E, H, L, } +#[derive(Clone, Copy)] +enum TargetU16Register {AF, BC, DE, HL, SP, PC} +impl CPU { + fn check_condition(&self, condition: Condition) -> bool { + match condition { + Condition::NZ => !self.registers.f.zero, + Condition::Z => self.registers.f.zero, + Condition::NC => !self.registers.f.carry, + Condition::C => self.registers.f.carry, + Condition::None => true, + } + } + + fn get_u8_reg_value(&mut self, target: TargetRegister) -> u8 { + match target { + TargetRegister::A => { self.registers.a } + TargetRegister::B => { self.registers.b } + TargetRegister::C => { self.registers.c } + TargetRegister::D => { self.registers.d } + TargetRegister::E => { self.registers.e } + TargetRegister::H => { self.registers.h } + TargetRegister::L => { self.registers.l } + } + } + fn set_u8_reg_value(&mut self, target: TargetRegister, value: u8) { + match target { + TargetRegister::A => { self.registers.a = value } + TargetRegister::B => { self.registers.b = value } + TargetRegister::C => { self.registers.c = value } + TargetRegister::D => { self.registers.d = value } + TargetRegister::E => { self.registers.e = value } + TargetRegister::H => { self.registers.h = value } + TargetRegister::L => { self.registers.l = value } + } + } + fn get_u16_reg_value(&mut self, target: TargetU16Register) -> u16 { + match target { + TargetU16Register::AF => {self.registers.get_af()} + TargetU16Register::BC => {self.registers.get_bc()} + TargetU16Register::DE => {self.registers.get_de()} + TargetU16Register::HL => {self.registers.get_hl()} + TargetU16Register::SP => {self.sp} + TargetU16Register::PC => {self.pc} + } + } + fn set_u16_reg_value(&mut self, target: TargetU16Register, value: u16) { + match target { + TargetU16Register::AF => {self.registers.set_af(value)} + TargetU16Register::BC => {self.registers.set_bc(value)} + TargetU16Register::DE => {self.registers.set_de(value)} + TargetU16Register::HL => {self.registers.set_hl(value)} + TargetU16Register::SP => {self.sp=value} + TargetU16Register::PC => {self.pc=value} + } + } + fn push_stack(&mut self, value: u16) { + let low = (value & 0xFF) as u8; + let high = (value >> 8) as u8; + self.bus.write_byte(self.sp - 1, high); + self.bus.write_byte(self.sp - 2, low); + self.sp = self.sp.wrapping_sub(2); + } + fn pop_stack(&mut self) -> u16 { + let low = (self.bus.read_byte(self.sp) as u16) << 8; + let high = self.bus.read_byte(self.sp + 1) as u16; + self.sp = self.sp.wrapping_add(2); + high | low + } + + fn get_target_value(&mut self, target: Target) -> u8 { + match target { + Target::U8Register(target_register) => { self.get_u8_reg_value(target_register) }, + Target::U16Register(target_register) => { + let address = self.get_u16_reg_value(target_register); + self.bus.read_byte(address) + }, + Target::Address(address) => { self.bus.read_byte(address) }, + Target::Immediate(value) => { value }, + } + } + fn set_target_value(&mut self, target: Target, value: u8) { + match target { + Target::U8Register(target_register) => { self.set_u8_reg_value(target_register, value) }, + Target::U16Register(target_register) => { + let address = self.get_u16_reg_value(target_register); + self.bus.write_byte(address, value) + }, + Target::Address(address) => { self.bus.write_byte(address, value) }, + Target::Immediate(_) => { }, + } + } + + fn next_instruction(&mut self) -> Instruction { + let opcode = self.bus.read_byte(self.pc); + match opcode { + 0x00 => { Instruction::NOP } + 0x01 => { Instruction::LD(LoadTarget::CopyR16N16(TargetU16Register::BC, self.bus.read_u16(self.pc.wrapping_add(1)))) } + 0x02 => { Instruction::LD(LoadTarget::CopyR16A(TargetU16Register::BC)) } + 0x03 => { Instruction::INC(Target::U16Register(TargetU16Register::BC)) } + 0x04 => { Instruction::INC(Target::U8Register(TargetRegister::B)) } + 0x05 => { Instruction::DEC(Target::U8Register(TargetRegister::B)) } + 0x06 => { Instruction::LD(LoadTarget::CopyR8N8(TargetRegister::B, self.bus.read_byte(self.pc.wrapping_add(1)))) } + 0x07 => { Instruction::RLC(Target::U8Register(TargetRegister::A)) } + 0x08 => { Instruction::LD(LoadTarget::CopyN16SP(self.bus.read_u16(self.pc.wrapping_add(1)))) } + 0x09 => { Instruction::ADDHL(TargetU16Register::BC) } + 0x0A => { Instruction::LD(LoadTarget::CopyAR16(TargetU16Register::BC)) } + 0x0B => { Instruction::DEC(Target::U16Register(TargetU16Register::BC)) } + 0x0C => { Instruction::INC(Target::U8Register(TargetRegister::C)) } + 0x0D => { Instruction::DEC(Target::U8Register(TargetRegister::C)) } + 0x0E => { Instruction::LD(LoadTarget::CopyR8N8(TargetRegister::C, self.bus.read_byte(self.pc.wrapping_add(1)))) } + 0x0F => { Instruction::RRC(Target::U8Register(TargetRegister::A)) } + 0x10 => { Instruction::STOP(self.bus.read_byte(self.pc.wrapping_add(1))) } + 0x11 => { Instruction::LD(LoadTarget::CopyR16N16(TargetU16Register::DE, self.bus.read_u16(self.pc.wrapping_add(1)))) } + 0x12 => { Instruction::LD(LoadTarget::CopyR16A(TargetU16Register::DE)) } + 0x13 => { Instruction::INC(Target::U16Register(TargetU16Register::DE)) } + 0x14 => { Instruction::INC(Target::U8Register(TargetRegister::D)) } + 0x15 => { Instruction::DEC(Target::U8Register(TargetRegister::D)) } + 0x16 => { Instruction::LD(LoadTarget::CopyR8N8(TargetRegister::D, self.bus.read_byte(self.pc.wrapping_add(1)))) } + 0x17 => { Instruction::RL(Target::U8Register(TargetRegister::A)) } + 0x18 => { Instruction::JR(Condition::NZ, self.bus.read_byte(self.pc.wrapping_add(1)) as i8) } + 0x19 => { Instruction::ADDHL(TargetU16Register::DE) } + 0x1A => { Instruction::LD(LoadTarget::CopyAR16(TargetU16Register::DE)) } + 0x1B => { Instruction::DEC(Target::U16Register(TargetU16Register::DE)) } + 0x1C => { Instruction::INC(Target::U8Register(TargetRegister::E)) } + 0x1D => { Instruction::DEC(Target::U8Register(TargetRegister::E)) } + 0x1E => { Instruction::LD(LoadTarget::CopyR8N8(TargetRegister::E, self.bus.read_byte(self.pc.wrapping_add(1)))) } + 0x1F => { Instruction::RR(Target::U8Register(TargetRegister::A)) } + 0x20 => { Instruction::JR(Condition::NZ, self.bus.read_byte(self.pc.wrapping_add(1)) as i8) } + 0x21 => { Instruction::LD(LoadTarget::CopyR16N16(TargetU16Register::HL, self.bus.read_u16(self.pc.wrapping_add(1)))) } + 0x22 => { Instruction::LD(LoadTarget::CopyHLIA) } + 0x23 => { Instruction::INC(Target::U16Register(TargetU16Register::HL)) } + 0x24 => { Instruction::INC(Target::U8Register(TargetRegister::H)) } + 0x25 => { Instruction::DEC(Target::U8Register(TargetRegister::H)) } + 0x26 => { Instruction::LD(LoadTarget::CopyR8N8(TargetRegister::H, self.bus.read_byte(self.pc.wrapping_add(1)))) } + 0x27 => { Instruction::DAA } + 0x28 => { Instruction::JR(Condition::Z, self.bus.read_byte(self.pc.wrapping_add(1)) as i8) } + 0x29 => { Instruction::ADDHL(TargetU16Register::HL) } + 0x2A => { Instruction::LD(LoadTarget::CopyAHLI) } + 0x2B => { Instruction::DEC(Target::U16Register(TargetU16Register::HL)) } + 0x2C => { Instruction::INC(Target::U8Register(TargetRegister::L)) } + 0x2D => { Instruction::DEC(Target::U8Register(TargetRegister::L)) } + 0x2E => { Instruction::LD(LoadTarget::CopyR8N8(TargetRegister::L, self.bus.read_byte(self.pc.wrapping_add(1)))) } + 0x2F => { Instruction::CPL } + 0x30 => { Instruction::JR(Condition::NC, self.bus.read_byte(self.pc.wrapping_add(1)) as i8) } + 0x31 => { Instruction::LD(LoadTarget::CopyR16N16(TargetU16Register::SP, self.bus.read_u16(self.pc.wrapping_add(1)))) } + 0x32 => { Instruction::LD(LoadTarget::CopyHLDA) } + 0x33 => { Instruction::INC(Target::U16Register(TargetU16Register::SP)) } + 0x34 => { Instruction::INC(Target::Address(self.get_u16_reg_value(TargetU16Register::HL))) } + 0x35 => { Instruction::DEC(Target::Address(self.get_u16_reg_value(TargetU16Register::HL))) } + 0x36 => { Instruction::LD(LoadTarget::CopyHLN8(self.bus.read_byte(self.pc.wrapping_add(1)))) } + 0x37 => { Instruction::SCF } + 0x38 => { Instruction::JR(Condition::C, self.bus.read_byte(self.pc.wrapping_add(1)) as i8) } + 0x39 => { Instruction::ADDHL(TargetU16Register::SP) } + 0x3A => { Instruction::LD(LoadTarget::CopyAHLD)} + 0x3B => { Instruction::DEC(Target::U16Register(TargetU16Register::SP)) } + 0x3C => { Instruction::INC(Target::U8Register(TargetRegister::A)) } + 0x3D => { Instruction::DEC(Target::U8Register(TargetRegister::A)) } + 0x3E => { Instruction::LD(LoadTarget::CopyR8N8(TargetRegister::A, self.bus.read_byte(self.pc.wrapping_add(1)))) } + 0x3F => { Instruction::CCF } + 0x40 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::B, TargetRegister::B)) } + 0x41 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::B, TargetRegister::C)) } + 0x42 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::B, TargetRegister::D)) } + 0x43 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::B, TargetRegister::E)) } + 0x44 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::B, TargetRegister::H)) } + 0x45 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::B, TargetRegister::L)) } + 0x46 => { Instruction::LD(LoadTarget::CopyR8HL(TargetRegister::B)) } + 0x47 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::B, TargetRegister::A)) } + 0x48 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::C, TargetRegister::B)) } + 0x49 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::C, TargetRegister::C)) } + 0x4A => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::C, TargetRegister::D)) } + 0x4B => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::C, TargetRegister::E)) } + 0x4C => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::C, TargetRegister::H)) } + 0x4D => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::C, TargetRegister::L)) } + 0x4E => { Instruction::LD(LoadTarget::CopyR8HL(TargetRegister::C)) } + 0x4F => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::C, TargetRegister::A)) } + 0x50 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::D, TargetRegister::B)) } + 0x51 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::D, TargetRegister::C)) } + 0x52 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::D, TargetRegister::D)) } + 0x53 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::D, TargetRegister::E)) } + 0x54 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::D, TargetRegister::H)) } + 0x55 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::D, TargetRegister::L)) } + 0x56 => { Instruction::LD(LoadTarget::CopyR8HL(TargetRegister::D)) } + 0x57 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::D, TargetRegister::A)) } + 0x58 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::E, TargetRegister::B)) } + 0x59 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::E, TargetRegister::C)) } + 0x5A => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::E, TargetRegister::D)) } + 0x5B => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::E, TargetRegister::E)) } + 0x5C => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::E, TargetRegister::H)) } + 0x5D => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::E, TargetRegister::L)) } + 0x5E => { Instruction::LD(LoadTarget::CopyR8HL(TargetRegister::E)) } + 0x5F => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::E, TargetRegister::A)) } + 0x60 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::H, TargetRegister::B)) } + 0x61 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::H, TargetRegister::C)) } + 0x62 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::H, TargetRegister::D)) } + 0x63 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::H, TargetRegister::E)) } + 0x64 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::H, TargetRegister::H)) } + 0x65 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::H, TargetRegister::L)) } + 0x66 => { Instruction::LD(LoadTarget::CopyR8HL(TargetRegister::H)) } + 0x67 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::H, TargetRegister::A)) } + 0x68 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::L, TargetRegister::B)) } + 0x69 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::L, TargetRegister::C)) } + 0x6A => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::L, TargetRegister::D)) } + 0x6B => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::L, TargetRegister::E)) } + 0x6C => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::L, TargetRegister::H)) } + 0x6D => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::L, TargetRegister::L)) } + 0x6E => { Instruction::LD(LoadTarget::CopyR8HL(TargetRegister::L)) } + 0x6F => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::L, TargetRegister::A)) } + 0x70 => { Instruction::LD(LoadTarget::CopyHLR8(TargetRegister::B)) } + 0x71 => { Instruction::LD(LoadTarget::CopyHLR8(TargetRegister::C)) } + 0x72 => { Instruction::LD(LoadTarget::CopyHLR8(TargetRegister::D)) } + 0x73 => { Instruction::LD(LoadTarget::CopyHLR8(TargetRegister::E)) } + 0x74 => { Instruction::LD(LoadTarget::CopyHLR8(TargetRegister::H)) } + 0x75 => { Instruction::LD(LoadTarget::CopyHLR8(TargetRegister::L)) } + 0x76 => { Instruction::HALT } + 0x77 => { Instruction::LD(LoadTarget::CopyHLR8(TargetRegister::A)) } + 0x78 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::A, TargetRegister::B)) } + 0x79 => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::A, TargetRegister::C)) } + 0x7A => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::A, TargetRegister::D)) } + 0x7B => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::A, TargetRegister::E)) } + 0x7C => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::A, TargetRegister::H)) } + 0x7D => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::A, TargetRegister::L)) } + 0x7E => { Instruction::LD(LoadTarget::CopyHLR8(TargetRegister::A)) } + 0x7F => { Instruction::LD(LoadTarget::CopyR8R8(TargetRegister::A, TargetRegister::A)) } + 0x80 => { Instruction::ADD(Target::U8Register(TargetRegister::B)) } + 0x81 => { Instruction::ADD(Target::U8Register(TargetRegister::C)) } + 0x82 => { Instruction::ADD(Target::U8Register(TargetRegister::D)) } + 0x83 => { Instruction::ADD(Target::U8Register(TargetRegister::E)) } + 0x84 => { Instruction::ADD(Target::U8Register(TargetRegister::H)) } + 0x85 => { Instruction::ADD(Target::U8Register(TargetRegister::L)) } + 0x86 => { Instruction::ADD(Target::U16Register(TargetU16Register::HL)) } + 0x87 => { Instruction::ADD(Target::U8Register(TargetRegister::A)) } + 0x88 => { Instruction::ADC(Target::U8Register(TargetRegister::B)) } + 0x89 => { Instruction::ADC(Target::U8Register(TargetRegister::C)) } + 0x8A => { Instruction::ADC(Target::U8Register(TargetRegister::D)) } + 0x8B => { Instruction::ADC(Target::U8Register(TargetRegister::E)) } + 0x8C => { Instruction::ADC(Target::U8Register(TargetRegister::H)) } + 0x8D => { Instruction::ADC(Target::U8Register(TargetRegister::L)) } + 0x8E => { Instruction::ADC(Target::U16Register(TargetU16Register::HL)) } + 0x8F => { Instruction::ADC(Target::U8Register(TargetRegister::A)) } + 0x90 => { Instruction::SUB(Target::U8Register(TargetRegister::B)) } + 0x91 => { Instruction::SUB(Target::U8Register(TargetRegister::C)) } + 0x92 => { Instruction::SUB(Target::U8Register(TargetRegister::D)) } + 0x93 => { Instruction::SUB(Target::U8Register(TargetRegister::E)) } + 0x94 => { Instruction::SUB(Target::U8Register(TargetRegister::H)) } + 0x95 => { Instruction::SUB(Target::U8Register(TargetRegister::L)) } + 0x96 => { Instruction::SUB(Target::U16Register(TargetU16Register::HL)) } + 0x97 => { Instruction::SUB(Target::U8Register(TargetRegister::A)) } + 0x98 => { Instruction::SBC(Target::U8Register(TargetRegister::B)) } + 0x99 => { Instruction::SBC(Target::U8Register(TargetRegister::C)) } + 0x9A => { Instruction::SBC(Target::U8Register(TargetRegister::D)) } + 0x9B => { Instruction::SBC(Target::U8Register(TargetRegister::E)) } + 0x9C => { Instruction::SBC(Target::U8Register(TargetRegister::H)) } + 0x9D => { Instruction::SBC(Target::U8Register(TargetRegister::L)) } + 0x9E => { Instruction::SBC(Target::U16Register(TargetU16Register::HL)) } + 0x9F => { Instruction::SBC(Target::U8Register(TargetRegister::A)) } + 0xA0 => { Instruction::AND(Target::U8Register(TargetRegister::B)) } + 0xA1 => { Instruction::AND(Target::U8Register(TargetRegister::C)) } + 0xA2 => { Instruction::AND(Target::U8Register(TargetRegister::D)) } + 0xA3 => { Instruction::AND(Target::U8Register(TargetRegister::E)) } + 0xA4 => { Instruction::AND(Target::U8Register(TargetRegister::H)) } + 0xA5 => { Instruction::AND(Target::U8Register(TargetRegister::L)) } + 0xA6 => { Instruction::AND(Target::U16Register(TargetU16Register::HL)) } + 0xA7 => { Instruction::AND(Target::U8Register(TargetRegister::A)) } + 0xA8 => { Instruction::XOR(Target::U8Register(TargetRegister::B)) } + 0xA9 => { Instruction::XOR(Target::U8Register(TargetRegister::C)) } + 0xAA => { Instruction::XOR(Target::U8Register(TargetRegister::D)) } + 0xAB => { Instruction::XOR(Target::U8Register(TargetRegister::E)) } + 0xAC => { Instruction::XOR(Target::U8Register(TargetRegister::H)) } + 0xAD => { Instruction::XOR(Target::U8Register(TargetRegister::L)) } + 0xAE => { Instruction::XOR(Target::U16Register(TargetU16Register::HL)) } + 0xAF => { Instruction::XOR(Target::U8Register(TargetRegister::A)) } + 0xB0 => { Instruction::OR(Target::U8Register(TargetRegister::B)) } + 0xB1 => { Instruction::OR(Target::U8Register(TargetRegister::C)) } + 0xB2 => { Instruction::OR(Target::U8Register(TargetRegister::D)) } + 0xB3 => { Instruction::OR(Target::U8Register(TargetRegister::E)) } + 0xB4 => { Instruction::OR(Target::U8Register(TargetRegister::H)) } + 0xB5 => { Instruction::OR(Target::U8Register(TargetRegister::L)) } + 0xB6 => { Instruction::OR(Target::U16Register(TargetU16Register::HL)) } + 0xB7 => { Instruction::OR(Target::U8Register(TargetRegister::A)) } + 0xB8 => { Instruction::CP(Target::U8Register(TargetRegister::B)) } + 0xB9 => { Instruction::CP(Target::U8Register(TargetRegister::C)) } + 0xBA => { Instruction::CP(Target::U8Register(TargetRegister::D)) } + 0xBB => { Instruction::CP(Target::U8Register(TargetRegister::E)) } + 0xBC => { Instruction::CP(Target::U8Register(TargetRegister::H)) } + 0xBD => { Instruction::CP(Target::U8Register(TargetRegister::L)) } + 0xBE => { Instruction::CP(Target::U16Register(TargetU16Register::HL)) } + 0xBF => { Instruction::CP(Target::U8Register(TargetRegister::A)) } + 0xC0 => { Instruction::RET(Condition::NZ) } + 0xC1 => { Instruction::POP(TargetU16Register::BC) } + 0xC2 => { Instruction::JP(Condition::NZ, self.bus.read_u16(self.pc.wrapping_add(1))) } + 0xC3 => { Instruction::JP(Condition::None, self.bus.read_u16(self.pc.wrapping_add(1))) } + 0xC4 => { Instruction::CALL(Condition::NZ, self.bus.read_u16(self.pc.wrapping_add(1))) } + 0xC5 => { Instruction::PUSH(TargetU16Register::BC) } + 0xC6 => { Instruction::ADD(Target::U8Register(TargetRegister::A)) } + 0xC7 => { Instruction::RST(0x00) } + 0xC8 => { Instruction::RET(Condition::Z) } + 0xC9 => { Instruction::RET(Condition::None) } + 0xCA => { Instruction::JP(Condition::Z, self.bus.read_u16(self.pc.wrapping_add(1))) } + 0xCB => {self.next_16bit_instruction(self.bus.read_byte(self.pc.wrapping_add(1)))}, + 0xCC => { Instruction::CALL(Condition::Z, self.bus.read_u16(self.pc.wrapping_add(1))) } + 0xCD => { Instruction::CALL(Condition::None, self.bus.read_u16(self.pc.wrapping_add(1))) } + 0xCE => { Instruction::ADC(Target::Immediate(self.bus.read_byte(self.pc.wrapping_add(1)))) } + 0xCF => { Instruction::RST(0x01) } + 0xD0 => { Instruction::RET(Condition::NC) } + 0xD1 => { Instruction::POP(TargetU16Register::DE) } + 0xD2 => { Instruction::JP(Condition::NC, self.bus.read_u16(self.pc.wrapping_add(1))) } + 0xD4 => { Instruction::CALL(Condition::NC, self.bus.read_u16(self.pc.wrapping_add(1))) } + 0xD5 => { Instruction::PUSH(TargetU16Register::DE) } + 0xD6 => { Instruction::SUB(Target::Immediate(self.bus.read_byte(self.pc.wrapping_add(1)))) } + 0xD7 => { Instruction::RST(0x02) } + 0xD8 => { Instruction::RET(Condition::C) } + 0xD9 => { Instruction::RETI } + 0xDA => { Instruction::JP(Condition::C, self.bus.read_u16(self.pc.wrapping_add(1))) } + 0xDC => { Instruction::CALL(Condition::C, self.bus.read_u16(self.pc.wrapping_add(1))) } + 0xDE => { Instruction::SBC(Target::Immediate(self.bus.read_byte(self.pc.wrapping_add(1)))) } + 0xDF => { Instruction::RST(0x03) } + 0xE0 => { Instruction::LD(LoadTarget::CopyPortA(Target::Immediate(self.bus.read_byte(self.pc.wrapping_add(1))))) } + 0xE1 => { Instruction::POP(TargetU16Register::HL) } + 0xE2 => { Instruction::LD(LoadTarget::CopyPortA(Target::U8Register(TargetRegister::C))) } + 0xE5 => { Instruction::PUSH(TargetU16Register::HL) } + 0xE6 => { Instruction::AND(Target::Immediate(self.bus.read_byte(self.pc.wrapping_add(1)))) } + 0xE7 => { Instruction::RST(0x04) } + 0xE8 => { Instruction::ADDSP(self.bus.read_byte(self.pc.wrapping_add(1))) } + 0xE9 => { Instruction::JPHL } + 0xEA => { Instruction::LD(LoadTarget::CopyN16A(self.bus.read_u16(self.pc.wrapping_add(1)))) } + 0xEE => { Instruction::XOR(Target::Immediate(self.bus.read_byte(self.pc.wrapping_add(1)))) } + 0xEF => { Instruction::RST(0x05) } + 0xF0 => { Instruction::LD(LoadTarget::CopyAPort(Target::Immediate(self.bus.read_byte(self.pc.wrapping_add(1))))) } + 0xF1 => { Instruction::POP(TargetU16Register::AF) } + 0xF2 => { Instruction::LD(LoadTarget::CopyPortA(Target::U8Register(TargetRegister::C))) } + 0xF3 => { Instruction::DI } + 0xF5 => { Instruction::PUSH(TargetU16Register::AF) } + 0xF6 => { Instruction::OR(Target::Immediate(self.bus.read_byte(self.pc.wrapping_add(1)))) } + 0xF7 => { Instruction::RST(0x06) } + 0xF8 => { Instruction::LD(LoadTarget::CopyHLSPE8(self.bus.read_byte(self.pc.wrapping_add(1)) as i8)) } + 0xF9 => { Instruction::LD(LoadTarget::CopySPHL) } + 0xFA => { Instruction::LD(LoadTarget::CopyAN16(self.bus.read_u16(self.pc.wrapping_add(1)))) } + 0xFB => { Instruction::EI } + 0xFE => { Instruction::CP(Target::Immediate(self.bus.read_byte(self.pc.wrapping_add(1)))) } + 0xFF => { Instruction::RST(0x07) } + _ => { panic!("Invalid u8 opcode: {:02X}", opcode); } + } + } + fn next_16bit_instruction(&mut self, opcode: u8) -> Instruction { + match opcode { + 0x00 => { Instruction::RLC(Target::U8Register(TargetRegister::B)) } + 0x01 => { Instruction::RLC(Target::U8Register(TargetRegister::C)) } + 0x02 => { Instruction::RLC(Target::U8Register(TargetRegister::D)) } + 0x03 => { Instruction::RLC(Target::U8Register(TargetRegister::E)) } + 0x04 => { Instruction::RLC(Target::U8Register(TargetRegister::H)) } + 0x05 => { Instruction::RLC(Target::U8Register(TargetRegister::L)) } + 0x06 => { Instruction::RLC(Target::U16Register(TargetU16Register::HL)) } + 0x07 => { Instruction::RLC(Target::U8Register(TargetRegister::A)) } + 0x08 => { Instruction::RRC(Target::U8Register(TargetRegister::B)) } + 0x09 => { Instruction::RRC(Target::U8Register(TargetRegister::C)) } + 0x0A => { Instruction::RRC(Target::U8Register(TargetRegister::D)) } + 0x0B => { Instruction::RRC(Target::U8Register(TargetRegister::E)) } + 0x0C => { Instruction::RRC(Target::U8Register(TargetRegister::H)) } + 0x0D => { Instruction::RRC(Target::U8Register(TargetRegister::L)) } + 0x0E => { Instruction::RRC(Target::U16Register(TargetU16Register::HL)) } + 0x0F => { Instruction::RRC(Target::U8Register(TargetRegister::A)) } + 0x10 => { Instruction::RL(Target::U8Register(TargetRegister::B)) } + 0x11 => { Instruction::RL(Target::U8Register(TargetRegister::C)) } + 0x12 => { Instruction::RL(Target::U8Register(TargetRegister::D)) } + 0x13 => { Instruction::RL(Target::U8Register(TargetRegister::E)) } + 0x14 => { Instruction::RL(Target::U8Register(TargetRegister::H)) } + 0x15 => { Instruction::RL(Target::U8Register(TargetRegister::L)) } + 0x16 => { Instruction::RL(Target::U16Register(TargetU16Register::HL)) } + 0x17 => { Instruction::RL(Target::U8Register(TargetRegister::A)) } + 0x18 => { Instruction::RR(Target::U8Register(TargetRegister::B)) } + 0x19 => { Instruction::RR(Target::U8Register(TargetRegister::C)) } + 0x1A => { Instruction::RR(Target::U8Register(TargetRegister::D)) } + 0x1B => { Instruction::RR(Target::U8Register(TargetRegister::E)) } + 0x1C => { Instruction::RR(Target::U8Register(TargetRegister::H)) } + 0x1D => { Instruction::RR(Target::U8Register(TargetRegister::L)) } + 0x1E => { Instruction::RR(Target::U16Register(TargetU16Register::HL)) } + 0x1F => { Instruction::RR(Target::U8Register(TargetRegister::A)) } + 0x20 => { Instruction::SLA(Target::U8Register(TargetRegister::B)) } + 0x21 => { Instruction::SLA(Target::U8Register(TargetRegister::C)) } + 0x22 => { Instruction::SLA(Target::U8Register(TargetRegister::D)) } + 0x23 => { Instruction::SLA(Target::U8Register(TargetRegister::E)) } + 0x24 => { Instruction::SLA(Target::U8Register(TargetRegister::H)) } + 0x25 => { Instruction::SLA(Target::U8Register(TargetRegister::L)) } + 0x26 => { Instruction::SLA(Target::U16Register(TargetU16Register::HL)) } + 0x27 => { Instruction::SLA(Target::U8Register(TargetRegister::A)) } + 0x28 => { Instruction::SRA(Target::U8Register(TargetRegister::B)) } + 0x29 => { Instruction::SRA(Target::U8Register(TargetRegister::C)) } + 0x2A => { Instruction::SRA(Target::U8Register(TargetRegister::D)) } + 0x2B => { Instruction::SRA(Target::U8Register(TargetRegister::E)) } + 0x2C => { Instruction::SRA(Target::U8Register(TargetRegister::H)) } + 0x2D => { Instruction::SRA(Target::U8Register(TargetRegister::L)) } + 0x2E => { Instruction::SRA(Target::U16Register(TargetU16Register::HL)) } + 0x2F => { Instruction::SRA(Target::U8Register(TargetRegister::A)) } + 0x30 => { Instruction::SWAP(Target::U8Register(TargetRegister::B)) } + 0x31 => { Instruction::SWAP(Target::U8Register(TargetRegister::C)) } + 0x32 => { Instruction::SWAP(Target::U8Register(TargetRegister::D)) } + 0x33 => { Instruction::SWAP(Target::U8Register(TargetRegister::E)) } + 0x34 => { Instruction::SWAP(Target::U8Register(TargetRegister::H)) } + 0x35 => { Instruction::SWAP(Target::U8Register(TargetRegister::L)) } + 0x36 => { Instruction::SWAP(Target::U16Register(TargetU16Register::HL)) } + 0x37 => { Instruction::SWAP(Target::U8Register(TargetRegister::A)) } + 0x38 => { Instruction::SRL(Target::U8Register(TargetRegister::B)) } + 0x39 => { Instruction::SRL(Target::U8Register(TargetRegister::C)) } + 0x3A => { Instruction::SRL(Target::U8Register(TargetRegister::D)) } + 0x3B => { Instruction::SRL(Target::U8Register(TargetRegister::E)) } + 0x3C => { Instruction::SRL(Target::U8Register(TargetRegister::H)) } + 0x3D => { Instruction::SRL(Target::U8Register(TargetRegister::L)) } + 0x3E => { Instruction::SRL(Target::U16Register(TargetU16Register::HL)) } + 0x3F => { Instruction::SRL(Target::U8Register(TargetRegister::A)) } + 0x40 => { Instruction::BIT(0, Target::U8Register(TargetRegister::B)) } + 0x41 => { Instruction::BIT(0, Target::U8Register(TargetRegister::C)) } + 0x42 => { Instruction::BIT(0, Target::U8Register(TargetRegister::D)) } + 0x43 => { Instruction::BIT(0, Target::U8Register(TargetRegister::E)) } + 0x44 => { Instruction::BIT(0, Target::U8Register(TargetRegister::H)) } + 0x45 => { Instruction::BIT(0, Target::U8Register(TargetRegister::L)) } + 0x46 => { Instruction::BIT(0, Target::U16Register(TargetU16Register::HL)) } + 0x47 => { Instruction::BIT(0, Target::U8Register(TargetRegister::A)) } + 0x48 => { Instruction::BIT(1, Target::U8Register(TargetRegister::B)) } + 0x49 => { Instruction::BIT(1, Target::U8Register(TargetRegister::C)) } + 0x4A => { Instruction::BIT(1, Target::U8Register(TargetRegister::D)) } + 0x4B => { Instruction::BIT(1, Target::U8Register(TargetRegister::E)) } + 0x4C => { Instruction::BIT(1, Target::U8Register(TargetRegister::H)) } + 0x4D => { Instruction::BIT(1, Target::U8Register(TargetRegister::L)) } + 0x4E => { Instruction::BIT(1, Target::U16Register(TargetU16Register::HL)) } + 0x4F => { Instruction::BIT(1, Target::U8Register(TargetRegister::A)) } + 0x50 => { Instruction::BIT(2, Target::U8Register(TargetRegister::B)) } + 0x51 => { Instruction::BIT(2, Target::U8Register(TargetRegister::C)) } + 0x52 => { Instruction::BIT(2, Target::U8Register(TargetRegister::D)) } + 0x53 => { Instruction::BIT(2, Target::U8Register(TargetRegister::E)) } + 0x54 => { Instruction::BIT(2, Target::U8Register(TargetRegister::H)) } + 0x55 => { Instruction::BIT(2, Target::U8Register(TargetRegister::L)) } + 0x56 => { Instruction::BIT(2, Target::U16Register(TargetU16Register::HL)) } + 0x57 => { Instruction::BIT(2, Target::U8Register(TargetRegister::A)) } + 0x58 => { Instruction::BIT(3, Target::U8Register(TargetRegister::B)) } + 0x59 => { Instruction::BIT(3, Target::U8Register(TargetRegister::C)) } + 0x5A => { Instruction::BIT(3, Target::U8Register(TargetRegister::D)) } + 0x5B => { Instruction::BIT(3, Target::U8Register(TargetRegister::E)) } + 0x5C => { Instruction::BIT(3, Target::U8Register(TargetRegister::H)) } + 0x5D => { Instruction::BIT(3, Target::U8Register(TargetRegister::L)) } + 0x5E => { Instruction::BIT(3, Target::U16Register(TargetU16Register::HL)) } + 0x5F => { Instruction::BIT(3, Target::U8Register(TargetRegister::A)) } + 0x60 => { Instruction::BIT(4, Target::U8Register(TargetRegister::B)) } + 0x61 => { Instruction::BIT(4, Target::U8Register(TargetRegister::C)) } + 0x62 => { Instruction::BIT(4, Target::U8Register(TargetRegister::D)) } + 0x63 => { Instruction::BIT(4, Target::U8Register(TargetRegister::E)) } + 0x64 => { Instruction::BIT(4, Target::U8Register(TargetRegister::H)) } + 0x65 => { Instruction::BIT(4, Target::U8Register(TargetRegister::L)) } + 0x66 => { Instruction::BIT(4, Target::U16Register(TargetU16Register::HL)) } + 0x67 => { Instruction::BIT(4, Target::U8Register(TargetRegister::A)) } + 0x68 => { Instruction::BIT(5, Target::U8Register(TargetRegister::B)) } + 0x69 => { Instruction::BIT(5, Target::U8Register(TargetRegister::C)) } + 0x6A => { Instruction::BIT(5, Target::U8Register(TargetRegister::D)) } + 0x6B => { Instruction::BIT(5, Target::U8Register(TargetRegister::E)) } + 0x6C => { Instruction::BIT(5, Target::U8Register(TargetRegister::H)) } + 0x6D => { Instruction::BIT(5, Target::U8Register(TargetRegister::L)) } + 0x6E => { Instruction::BIT(5, Target::U16Register(TargetU16Register::HL)) } + 0x6F => { Instruction::BIT(5, Target::U8Register(TargetRegister::A)) } + 0x70 => { Instruction::BIT(6, Target::U8Register(TargetRegister::B)) } + 0x71 => { Instruction::BIT(6, Target::U8Register(TargetRegister::C)) } + 0x72 => { Instruction::BIT(6, Target::U8Register(TargetRegister::D)) } + 0x73 => { Instruction::BIT(6, Target::U8Register(TargetRegister::E)) } + 0x74 => { Instruction::BIT(6, Target::U8Register(TargetRegister::H)) } + 0x75 => { Instruction::BIT(6, Target::U8Register(TargetRegister::L)) } + 0x76 => { Instruction::BIT(6, Target::U16Register(TargetU16Register::HL)) } + 0x77 => { Instruction::BIT(6, Target::U8Register(TargetRegister::A)) } + 0x78 => { Instruction::BIT(7, Target::U8Register(TargetRegister::B)) } + 0x79 => { Instruction::BIT(7, Target::U8Register(TargetRegister::C)) } + 0x7A => { Instruction::BIT(7, Target::U8Register(TargetRegister::D)) } + 0x7B => { Instruction::BIT(7, Target::U8Register(TargetRegister::E)) } + 0x7C => { Instruction::BIT(7, Target::U8Register(TargetRegister::H)) } + 0x7D => { Instruction::BIT(7, Target::U8Register(TargetRegister::L)) } + 0x7E => { Instruction::BIT(7, Target::U16Register(TargetU16Register::HL)) } + 0x7F => { Instruction::BIT(7, Target::U8Register(TargetRegister::A)) } + 0x80 => { Instruction::RES(0, Target::U8Register(TargetRegister::B)) } + 0x81 => { Instruction::RES(0, Target::U8Register(TargetRegister::C)) } + 0x82 => { Instruction::RES(0, Target::U8Register(TargetRegister::D)) } + 0x83 => { Instruction::RES(0, Target::U8Register(TargetRegister::E)) } + 0x84 => { Instruction::RES(0, Target::U8Register(TargetRegister::H)) } + 0x85 => { Instruction::RES(0, Target::U8Register(TargetRegister::L)) } + 0x86 => { Instruction::RES(0, Target::U16Register(TargetU16Register::HL)) } + 0x87 => { Instruction::RES(0, Target::U8Register(TargetRegister::A)) } + 0x88 => { Instruction::RES(1, Target::U8Register(TargetRegister::B)) } + 0x89 => { Instruction::RES(1, Target::U8Register(TargetRegister::C)) } + 0x8A => { Instruction::RES(1, Target::U8Register(TargetRegister::D)) } + 0x8B => { Instruction::RES(1, Target::U8Register(TargetRegister::E)) } + 0x8C => { Instruction::RES(1, Target::U8Register(TargetRegister::H)) } + 0x8D => { Instruction::RES(1, Target::U8Register(TargetRegister::L)) } + 0x8E => { Instruction::RES(1, Target::U16Register(TargetU16Register::HL)) } + 0x8F => { Instruction::RES(1, Target::U8Register(TargetRegister::A)) } + 0x90 => { Instruction::RES(2, Target::U8Register(TargetRegister::B)) } + 0x91 => { Instruction::RES(2, Target::U8Register(TargetRegister::C)) } + 0x92 => { Instruction::RES(2, Target::U8Register(TargetRegister::D)) } + 0x93 => { Instruction::RES(2, Target::U8Register(TargetRegister::E)) } + 0x94 => { Instruction::RES(2, Target::U8Register(TargetRegister::H)) } + 0x95 => { Instruction::RES(2, Target::U8Register(TargetRegister::L)) } + 0x96 => { Instruction::RES(2, Target::U16Register(TargetU16Register::HL)) } + 0x97 => { Instruction::RES(2, Target::U8Register(TargetRegister::A)) } + 0x98 => { Instruction::RES(3, Target::U8Register(TargetRegister::B)) } + 0x99 => { Instruction::RES(3, Target::U8Register(TargetRegister::C)) } + 0x9A => { Instruction::RES(3, Target::U8Register(TargetRegister::D)) } + 0x9B => { Instruction::RES(3, Target::U8Register(TargetRegister::E)) } + 0x9C => { Instruction::RES(3, Target::U8Register(TargetRegister::H)) } + 0x9D => { Instruction::RES(3, Target::U8Register(TargetRegister::L)) } + 0x9E => { Instruction::RES(3, Target::U16Register(TargetU16Register::HL)) } + 0x9F => { Instruction::RES(3, Target::U8Register(TargetRegister::A)) } + 0xA0 => { Instruction::RES(4, Target::U8Register(TargetRegister::B)) } + 0xA1 => { Instruction::RES(4, Target::U8Register(TargetRegister::C)) } + 0xA2 => { Instruction::RES(4, Target::U8Register(TargetRegister::D)) } + 0xA3 => { Instruction::RES(4, Target::U8Register(TargetRegister::E)) } + 0xA4 => { Instruction::RES(4, Target::U8Register(TargetRegister::H)) } + 0xA5 => { Instruction::RES(4, Target::U8Register(TargetRegister::L)) } + 0xA6 => { Instruction::RES(4, Target::U16Register(TargetU16Register::HL)) } + 0xA7 => { Instruction::RES(4, Target::U8Register(TargetRegister::A)) } + 0xA8 => { Instruction::RES(5, Target::U8Register(TargetRegister::B)) } + 0xA9 => { Instruction::RES(5, Target::U8Register(TargetRegister::C)) } + 0xAA => { Instruction::RES(5, Target::U8Register(TargetRegister::D)) } + 0xAB => { Instruction::RES(5, Target::U8Register(TargetRegister::E)) } + 0xAC => { Instruction::RES(5, Target::U8Register(TargetRegister::H)) } + 0xAD => { Instruction::RES(5, Target::U8Register(TargetRegister::L)) } + 0xAE => { Instruction::RES(5, Target::U16Register(TargetU16Register::HL)) } + 0xAF => { Instruction::RES(5, Target::U8Register(TargetRegister::A)) } + 0xB0 => { Instruction::RES(6, Target::U8Register(TargetRegister::B)) } + 0xB1 => { Instruction::RES(6, Target::U8Register(TargetRegister::C)) } + 0xB2 => { Instruction::RES(6, Target::U8Register(TargetRegister::D)) } + 0xB3 => { Instruction::RES(6, Target::U8Register(TargetRegister::E)) } + 0xB4 => { Instruction::RES(6, Target::U8Register(TargetRegister::H)) } + 0xB5 => { Instruction::RES(6, Target::U8Register(TargetRegister::L)) } + 0xB6 => { Instruction::RES(6, Target::U16Register(TargetU16Register::HL)) } + 0xB7 => { Instruction::RES(6, Target::U8Register(TargetRegister::A)) } + 0xB8 => { Instruction::RES(7, Target::U8Register(TargetRegister::B)) } + 0xB9 => { Instruction::RES(7, Target::U8Register(TargetRegister::C)) } + 0xBA => { Instruction::RES(7, Target::U8Register(TargetRegister::D)) } + 0xBB => { Instruction::RES(7, Target::U8Register(TargetRegister::E)) } + 0xBC => { Instruction::RES(7, Target::U8Register(TargetRegister::H)) } + 0xBD => { Instruction::RES(7, Target::U8Register(TargetRegister::L)) } + 0xBE => { Instruction::RES(7, Target::U16Register(TargetU16Register::HL)) } + 0xBF => { Instruction::RES(7, Target::U8Register(TargetRegister::A)) } + 0xC0 => { Instruction::SET(0, Target::U8Register(TargetRegister::B)) } + 0xC1 => { Instruction::SET(0, Target::U8Register(TargetRegister::C)) } + 0xC2 => { Instruction::SET(0, Target::U8Register(TargetRegister::D)) } + 0xC3 => { Instruction::SET(0, Target::U8Register(TargetRegister::E)) } + 0xC4 => { Instruction::SET(0, Target::U8Register(TargetRegister::H)) } + 0xC5 => { Instruction::SET(0, Target::U8Register(TargetRegister::L)) } + 0xC6 => { Instruction::SET(0, Target::U16Register(TargetU16Register::HL)) } + 0xC7 => { Instruction::SET(0, Target::U8Register(TargetRegister::A)) } + 0xC8 => { Instruction::SET(1, Target::U8Register(TargetRegister::B)) } + 0xC9 => { Instruction::SET(1, Target::U8Register(TargetRegister::C)) } + 0xCA => { Instruction::SET(1, Target::U8Register(TargetRegister::D)) } + 0xCB => { Instruction::SET(1, Target::U8Register(TargetRegister::E)) } + 0xCC => { Instruction::SET(1, Target::U8Register(TargetRegister::H)) } + 0xCD => { Instruction::SET(1, Target::U8Register(TargetRegister::L)) } + 0xCE => { Instruction::SET(1, Target::U16Register(TargetU16Register::HL)) } + 0xCF => { Instruction::SET(1, Target::U8Register(TargetRegister::A)) } + 0xD0 => { Instruction::SET(2, Target::U8Register(TargetRegister::B)) } + 0xD1 => { Instruction::SET(2, Target::U8Register(TargetRegister::C)) } + 0xD2 => { Instruction::SET(2, Target::U8Register(TargetRegister::D)) } + 0xD3 => { Instruction::SET(2, Target::U8Register(TargetRegister::E)) } + 0xD4 => { Instruction::SET(2, Target::U8Register(TargetRegister::H)) } + 0xD5 => { Instruction::SET(2, Target::U8Register(TargetRegister::L)) } + 0xD6 => { Instruction::SET(2, Target::U16Register(TargetU16Register::HL)) } + 0xD7 => { Instruction::SET(2, Target::U8Register(TargetRegister::A)) } + 0xD8 => { Instruction::SET(3, Target::U8Register(TargetRegister::B)) } + 0xD9 => { Instruction::SET(3, Target::U8Register(TargetRegister::C)) } + 0xDA => { Instruction::SET(3, Target::U8Register(TargetRegister::D)) } + 0xDB => { Instruction::SET(3, Target::U8Register(TargetRegister::E)) } + 0xDC => { Instruction::SET(3, Target::U8Register(TargetRegister::H)) } + 0xDD => { Instruction::SET(3, Target::U8Register(TargetRegister::L)) } + 0xDE => { Instruction::SET(3, Target::U16Register(TargetU16Register::HL)) } + 0xDF => { Instruction::SET(3, Target::U8Register(TargetRegister::A)) } + 0xE0 => { Instruction::SET(4, Target::U8Register(TargetRegister::B)) } + 0xE1 => { Instruction::SET(4, Target::U8Register(TargetRegister::C)) } + 0xE2 => { Instruction::SET(4, Target::U8Register(TargetRegister::D)) } + 0xE3 => { Instruction::SET(4, Target::U8Register(TargetRegister::E)) } + 0xE4 => { Instruction::SET(4, Target::U8Register(TargetRegister::H)) } + 0xE5 => { Instruction::SET(4, Target::U8Register(TargetRegister::L)) } + 0xE6 => { Instruction::SET(4, Target::U16Register(TargetU16Register::HL)) } + 0xE7 => { Instruction::SET(4, Target::U8Register(TargetRegister::A)) } + 0xE8 => { Instruction::SET(5, Target::U8Register(TargetRegister::B)) } + 0xE9 => { Instruction::SET(5, Target::U8Register(TargetRegister::C)) } + 0xEA => { Instruction::SET(5, Target::U8Register(TargetRegister::D)) } + 0xEB => { Instruction::SET(5, Target::U8Register(TargetRegister::E)) } + 0xEC => { Instruction::SET(5, Target::U8Register(TargetRegister::H)) } + 0xED => { Instruction::SET(5, Target::U8Register(TargetRegister::L)) } + 0xEE => { Instruction::SET(5, Target::U16Register(TargetU16Register::HL)) } + 0xEF => { Instruction::SET(5, Target::U8Register(TargetRegister::A)) } + 0xF0 => { Instruction::SET(6, Target::U8Register(TargetRegister::B)) } + 0xF1 => { Instruction::SET(6, Target::U8Register(TargetRegister::C)) } + 0xF2 => { Instruction::SET(6, Target::U8Register(TargetRegister::D)) } + 0xF3 => { Instruction::SET(6, Target::U8Register(TargetRegister::E)) } + 0xF4 => { Instruction::SET(6, Target::U8Register(TargetRegister::H)) } + 0xF5 => { Instruction::SET(6, Target::U8Register(TargetRegister::L)) } + 0xF6 => { Instruction::SET(6, Target::U16Register(TargetU16Register::HL)) } + 0xF7 => { Instruction::SET(6, Target::U8Register(TargetRegister::A)) } + 0xF8 => { Instruction::SET(7, Target::U8Register(TargetRegister::B)) } + 0xF9 => { Instruction::SET(7, Target::U8Register(TargetRegister::C)) } + 0xFA => { Instruction::SET(7, Target::U8Register(TargetRegister::D)) } + 0xFB => { Instruction::SET(7, Target::U8Register(TargetRegister::E)) } + 0xFC => { Instruction::SET(7, Target::U8Register(TargetRegister::H)) } + 0xFD => { Instruction::SET(7, Target::U8Register(TargetRegister::L)) } + 0xFE => { Instruction::SET(7, Target::U16Register(TargetU16Register::HL)) } + 0xFF => { Instruction::SET(7, Target::U8Register(TargetRegister::A)) } + _ => { panic!("Invalid u16 opcode: {:02X}", opcode); } + } + } + fn execute(&mut self, instruction: Instruction) { + match instruction { + Instruction::ADC(target) => { + let value = self.get_target_value(target); + let (mut new_value, did_overflow) = self.registers.a.overflowing_add(value); + new_value += did_overflow as u8; + self.registers.a = new_value; + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = false; + self.registers.f.carry = did_overflow; + self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF; + } + Instruction::ADD(target) => { + let value = self.get_target_value(target); + let (new_value, did_overflow) = self.registers.a.overflowing_add(value); + self.registers.a = new_value; + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = false; + self.registers.f.carry = did_overflow; + self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF; + } + Instruction::ADDHL(target) => { + let value = self.get_u16_reg_value(target); + let (new_value, did_overflow) = self.registers.get_hl().overflowing_add(value); + self.registers.set_hl(new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = false; + self.registers.f.carry = did_overflow; + self.registers.f.half_carry = (new_value & 0xFF) + (value & 0xFF) > 0xFF; + } + Instruction::ADDSP(value) => { + let offset = (value as i16) as u16; + let (new_value, did_overflow) = self.sp.overflowing_add(offset); + self.sp = new_value; + self.registers.f.zero = false; + self.registers.f.subtract = false; + self.registers.f.carry = did_overflow; + self.registers.f.half_carry = (new_value & 0xFF) + (offset & 0xFF) > 0xFF; + } + Instruction::AND(target) => { + let value = self.get_target_value(target); + self.registers.a = value & self.registers.a; + self.registers.f.zero = self.registers.a == 0; + self.registers.f.subtract = false; + self.registers.f.carry = false; + self.registers.f.half_carry = true; + } + Instruction::BIT(bit, target) => { + let value = self.get_target_value(target); + self.registers.f.zero = value >> bit & 0x1 == 0; + self.registers.f.subtract = false; + self.registers.f.half_carry = true; + } + Instruction::CALL(condition, address) => { + if self.check_condition(condition) { + self.sp = self.sp.wrapping_sub(2); + let pc = self.pc; + self.bus.write_byte(self.sp + 1, ((pc >> 8) & 0xFF) as u8); + self.bus.write_byte(self.sp, (pc & 0xFF) as u8); + self.pc = address; + } + } + Instruction::CCF => { + self.registers.f.subtract = false; + self.registers.f.half_carry = false; + self.registers.f.carry = !self.registers.f.carry; + } + Instruction::CP(target) => { + let value = self.get_target_value(target); + let (new_value, did_overflow) = self.registers.a.overflowing_sub(value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = true; + self.registers.f.carry = did_overflow; + self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF; + } + Instruction::CPL => { + self.registers.a = !self.registers.a; + self.registers.f.subtract = true; + self.registers.f.half_carry = true; + } + Instruction::DAA => { + let new_value; + let did_overflow; + let mut adjustment: u8 = 0; + if self.registers.f.subtract { + if self.registers.f.half_carry { + adjustment += 0x6; + } + if self.registers.f.carry { + adjustment += 0x60; + } + (new_value, did_overflow) = self.registers.a.overflowing_sub(adjustment); + } else { + if self.registers.f.half_carry || self.registers.a & 0xF > 0x9 { + adjustment += 0x6; + } + if self.registers.f.carry || self.registers.a > 0x99 { + adjustment += 0x60; + } + (new_value, did_overflow) = self.registers.a.overflowing_add(adjustment); + } + self.registers.a = new_value; + self.registers.f.carry = did_overflow; + self.registers.f.zero = new_value == 0; + self.registers.f.half_carry = false; + } + Instruction::DEC(target) => { + match target { + Target::U8Register(target) => { + let value = self.get_u8_reg_value(target); + let (new_value, _) = value.overflowing_sub(1); + self.set_u8_reg_value(target, new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = true; + self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF; + } + Target::U16Register(target) => { + let value = self.get_u16_reg_value(target); + let new_value = value.wrapping_sub(1); + self.set_u16_reg_value(target, new_value); + } + Target::Address(_) => {} + Target::Immediate(_) => {} + } + } + Instruction::DECHL(register) => { + let target = Target::U16Register(register); + let value = self.get_target_value(target); + let new_value = value.wrapping_sub(1); + self.set_target_value(target, new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = true; + self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF; + } + Instruction::DI => {} + Instruction::EI => {} + Instruction::HALT => {todo!();} + + Instruction::INC(target) => { + match target { + Target::U8Register(target) => { + let value = self.get_u8_reg_value(target); + let (new_value, _) = value.overflowing_add(1); + self.set_u8_reg_value(target, new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = false; + self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF; + } + Target::U16Register(target) => { + let value = self.get_u16_reg_value(target); + let new_value = value.wrapping_add(1); + self.set_u16_reg_value(target, new_value); + } + Target::Address(_) => {} + Target::Immediate(_) => {} + } + } + Instruction::INCHL(register) => { + let target = Target::U16Register(register); + let value = self.get_target_value(target); + let new_value = value.wrapping_add(1); + self.set_target_value(target, new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = true; + self.registers.f.half_carry = (new_value & 0xF) + (value & 0xF) > 0xF; + } + Instruction::JP(condition, address) => { + if self.check_condition(condition) { + self.pc = address; + } + } + Instruction::JPHL => { + self.pc = self.registers.get_hl(); + } + Instruction::JR(condition, offset) => { + if self.check_condition(condition) { + self.pc = if offset.is_negative() { + self.pc.wrapping_sub(offset.abs() as u16) + } else { + self.pc.wrapping_add(offset as u16) + } + } + } + Instruction::LD(target) => { + match target { + LoadTarget::CopyR8R8(dest_register, source_register) => { + let value = self.get_u8_reg_value(source_register); + self.set_u8_reg_value(dest_register, value); + } + LoadTarget::CopyR8N8(dest_register, value) => { + self.set_u8_reg_value(dest_register, value); + } + LoadTarget::CopyR16N16(dest_register, value) => { + self.set_u16_reg_value(dest_register, value); + } + LoadTarget::CopyHLR8(source_register) => { + let value = self.get_u8_reg_value(source_register); + let address = self.registers.get_hl(); + self.bus.write_byte(address, value); + } + LoadTarget::CopyHLN8(value) => { + let address = self.registers.get_hl(); + self.bus.write_byte(address, value); + } + LoadTarget::CopyR8HL(dest_register) => { + let address = self.registers.get_hl(); + let value = self.bus.read_byte(address); + self.set_u8_reg_value(dest_register, value); + } + LoadTarget::CopyR16A(dest_register) => { + let address = self.get_u16_reg_value(dest_register); + self.bus.write_byte(address, self.registers.a); + } + LoadTarget::CopyN16A(address) => { + self.bus.write_byte(address, self.registers.a); + } + LoadTarget::CopyPortA(target) => { + let offset = self.get_target_value(target); + let address = 0xFF00 | offset as u16; + self.bus.write_byte(address, self.registers.a); + } + LoadTarget::CopyAPort(target) => { + let offset = self.get_target_value(target); + let address = 0xFF00 | offset as u16; + self.registers.a = self.bus.read_byte(address); + } + LoadTarget::CopyHN16A(address) => { + if address >= 0xFF00 { + self.bus.write_byte(address, self.registers.a) + } + } + LoadTarget::CopyHCA => { + let address = 0xFF00 + self.registers.c as u16; + self.bus.write_byte(address, self.registers.a) + } + LoadTarget::CopyAR16(source_register) => { + let address = self.get_u16_reg_value(source_register); + self.registers.a = self.bus.read_byte(address); + } + LoadTarget::CopyAN16(address) => { + self.registers.a = self.bus.read_byte(address); + } + LoadTarget::CopyHAN16(address) => { + if address >= 0xFF00 { + self.registers.a = self.bus.read_byte(address) + } + } + LoadTarget::CopyHAC => { + self.registers.a = self.bus.read_byte(0xFF00+self.registers.c as u16) + } + LoadTarget::CopyHLIA => { + let address = self.registers.get_hl(); + self.bus.write_byte(address, self.registers.a); + self.registers.set_hl(address.wrapping_add(1)); + } + LoadTarget::CopyHLDA => { + let address = self.registers.get_hl(); + self.bus.write_byte(address, self.registers.a); + self.registers.set_hl(address.wrapping_sub(1)); + } + LoadTarget::CopyAHLI => { + let address = self.registers.get_hl(); + self.registers.a = self.bus.read_byte(address); + self.registers.set_hl(address.wrapping_add(1)); + } + LoadTarget::CopyAHLD => { + let address = self.registers.get_hl(); + self.registers.a = self.bus.read_byte(address); + self.registers.set_hl(address.wrapping_sub(1)); + } + LoadTarget::CopySPN16(value) => { + self.sp = value; + } + LoadTarget::CopyN16SP(address) => { + self.bus.write_byte(address, (0xF & self.sp) as u8); + self.bus.write_byte(address + 1, (self.sp >> 8) as u8); + } + LoadTarget::CopyHLSPE8(value) => { + + let new_value = match value.is_negative() { + true => { self.sp.wrapping_sub(value.abs() as u16) } + false => { self.sp.wrapping_add(value as u16) } + }; + self.registers.set_hl(new_value); + self.registers.f.zero = false; + self.registers.f.subtract = false; + self.registers.f.carry = (new_value & 0xFF) + (self.sp & 0xFF) > 0xFF; + self.registers.f.half_carry = (new_value & 0xF) + (self.sp & 0xF) > 0xF; + + } + LoadTarget::CopySPHL => { + self.sp = self.registers.get_hl(); + } + } + } + Instruction::NOP => {} + Instruction::OR(target) => { + let value = self.get_target_value(target); + self.registers.a = value | self.registers.a; + self.registers.f.zero = self.registers.a == 0; + self.registers.f.subtract = false; + self.registers.f.carry = false; + self.registers.f.half_carry = false; + } + Instruction::POP(target) => { + let value = self.pop_stack(); + self.set_u16_reg_value(target, value); + } + Instruction::PUSH(target) => { + let value = self.get_u16_reg_value(target); + self.push_stack(value); + } + Instruction::RES(bit, target) => { + let mut value = self.get_target_value(target); + value &= !(1 << bit); + self.set_target_value(target, value); + } + Instruction::RET(condition) => { + if self.check_condition(condition) { + self.pc = self.pop_stack(); + } + } + Instruction::RETI => { + self.pc = self.pop_stack(); + } + Instruction::RL(target) => { + let old_value = self.get_target_value(target); + let old_carry = self.registers.f.carry; + self.registers.f.carry = old_value & 0x80 == 0x80; + let new_value = (self.registers.a << 1) | (if old_carry { 0x01 } else { 0 }); + self.set_target_value(target, new_value); + self.registers.f.zero = false; + self.registers.f.subtract = false; + self.registers.f.half_carry = false; + } + Instruction::RLC(target) => { + let old_value = self.get_target_value(target); + self.registers.f.carry = old_value & 0x80 == 0x80; + let new_value = (self.registers.a << 1) | (if self.registers.f.carry { 0x1 } else { 0 }); + self.set_target_value(target, new_value); + self.registers.f.zero = false; + self.registers.f.subtract = false; + self.registers.f.half_carry = false; + } + Instruction::RR(target) => { + let old_value = self.get_target_value(target); + let old_carry = self.registers.f.carry; + self.registers.f.carry = old_value & 0x1 == 0x1; + let new_value = (self.registers.a >> 1) | (if old_carry { 0x80 } else { 0 }); + self.set_target_value(target, new_value); + self.registers.f.zero = false; + self.registers.f.subtract = false; + self.registers.f.half_carry = false; + } + Instruction::RRC(target) => { + let old_value = self.get_target_value(target); + self.registers.f.carry = old_value & 0x1 == 0x1; + let new_value = (self.registers.a >> 1) | (if self.registers.f.carry { 0x80 } else { 0 }); + self.set_target_value(target, new_value); + self.registers.f.zero = false; + self.registers.f.subtract = false; + self.registers.f.half_carry = false; + } + Instruction::RST(idx) => { + self.push_stack(self.pc); + let address = self.bus.read_byte((idx as u16) * 8) as u16; + self.pc = address; + } + Instruction::SBC(target) => { + let value = self.get_target_value(target); + let (mut new_value, did_overflow) = self.registers.a.overflowing_sub(value); + new_value -= did_overflow as u8; + self.registers.a = new_value; + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = true; + self.registers.f.carry = did_overflow; + self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF; + } + Instruction::SCF => { + self.registers.f.carry = true; + self.registers.f.subtract = false; + self.registers.f.half_carry = false; + } + Instruction::SET(bit, target) => { + let mut value = self.get_target_value(target); + value |= 1 << bit; + self.set_target_value(target, value); + } + Instruction::SLA(target) => { + let value = self.get_target_value(target); + let new_value = value << 1; + self.set_target_value(target, new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = false; + self.registers.f.carry = value & 0x80 == 0x80; + self.registers.f.half_carry = false; + } + Instruction::SRA(target) => { + let value = self.get_target_value(target); + let new_value = value >> 1 | (if value & 0x80 == 0x80 { 0x80 } else { 0 }); + self.set_target_value(target, new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = false; + self.registers.f.carry = value & 0x80 == 0x80; + self.registers.f.half_carry = false; + } + Instruction::SRL(target) => { + let value = self.get_target_value(target); + let new_value = value >> 1; + self.set_target_value(target, new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = false; + self.registers.f.carry = value & 0x1 == 0x1; + self.registers.f.half_carry = false; + } + Instruction::STOP(_) => { + + } + Instruction::SUB(target) => { + let value = self.get_target_value(target); + let (new_value, did_overflow) = self.registers.a.overflowing_sub(value); + self.registers.a = new_value; + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = true; + self.registers.f.carry = did_overflow; + self.registers.f.half_carry = (self.registers.a & 0xF) + (value & 0xF) > 0xF; + } + Instruction::SWAP(target) => { + let value = self.get_target_value(target); + let new_value = ((value & 0xF0) >> 4) | ((value & 0x0F) << 4); + self.set_target_value(target, new_value); + self.registers.f.zero = new_value == 0; + self.registers.f.subtract = false; + self.registers.f.carry = false; + self.registers.f.half_carry = false; + } + Instruction::XOR(target) => { + let value = self.get_target_value(target); + self.registers.a = value ^ self.registers.a; + self.registers.f.zero = self.registers.a == 0; + self.registers.f.subtract = false; + self.registers.f.carry = false; + self.registers.f.half_carry = false; + } + } + } +} + fn main() { - println!("Hello, world!"); + + let gameboy = CPU{ + registers:Registers{a:0,b:0,c:0,d:0,e:0,f:FlagsRegister::from(0),h:0,l:0}, + pc:0, + bus:MemoryBus{ memory: [0xFFu8; 0xFFFF], gpu:GPU{ vram: Vec::with_capacity(VRAM_END-VRAM_BEGIN), tile_set: [[[TilePixelValue::Zero; 8]; 8]; 384] }}, + sp: 0 + }; } diff --git a/src/registers.rs b/src/registers.rs index 479a3c9..f8b6878 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -12,7 +12,7 @@ const SUBTRACT_FLAG_BYTE_POSITION: u8 = 6; const HALF_CARRY_FLAG_BYTE_POSITION: u8 = 5; const CARRY_FLAG_BYTE_POSITION: u8 = 4; -impl std::convert::From for u8 { +impl From for u8 { fn from(flag: FlagsRegister) -> u8 { (if flag.zero { 1 } else { 0 }) << ZERO_FLAG_BYTE_POSITION | (if flag.subtract { 1 } else { 0 }) << SUBTRACT_FLAG_BYTE_POSITION | @@ -21,7 +21,7 @@ impl std::convert::From for u8 { } } -impl std::convert::From for FlagsRegister { +impl From for FlagsRegister { fn from(byte: u8) -> Self { let zero = ((byte >> ZERO_FLAG_BYTE_POSITION) & 0b1) != 0; let subtract = ((byte >> SUBTRACT_FLAG_BYTE_POSITION) & 0b1) != 0;