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;