diff --git a/Readme.md b/Readme.md index f094807..8b5837b 100644 --- a/Readme.md +++ b/Readme.md @@ -11,8 +11,8 @@ Display is able to render tiles + sprites, 8x16 sprites are implemented but unte - Test 01 fails because of DAA - Test 02 fails because interrupts are not fully implemented. - - Test 03 fails - - Test 04 fails + - Test 03 fails, probably because of flags. + - Test 04 passes - Test 05 fails - Test 06 passes (LD R, R) - Test 07 fails diff --git a/src/cpu.rs b/src/cpu.rs index 8d064bb..186746c 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -103,6 +103,90 @@ impl CPU { } } + #[inline] + fn adc_r(&mut self, val: u8) { + // Passes the test + let old: u8 = self.regs[REG_A]; + let mut new: u8 = old; + let c: u8; + if self.flags & FLAG_C == FLAG_C { + c = 1; + } else { + c = 0; + } + new = new.wrapping_add(val); + new = new.wrapping_add(c); + self.regs[REG_A] = new; + + self.clear_flag(FLAG_N); + self.set_clear_flag(FLAG_Z, new == 0); + self.set_clear_flag(FLAG_C, ((val + c) > 0 && new < old) || (c == 1 && new == old)); + self.set_clear_flag(FLAG_H, ((old & 0x0F) + (val & 0x0F) + c) > 0x0F); + } + + #[inline] + fn add_r(&mut self, val: u8) { + // Passes the test + let old: u8 = self.regs[REG_A]; + let new: u8 = old.wrapping_add(val); + let carry: u16 = (old as u16) ^ (val as u16) ^ (new as u16); + self.regs[REG_A] = new; + + self.clear_flag(FLAG_N); + self.set_clear_flag(FLAG_Z, new == 0); + self.set_clear_flag(FLAG_C, val > 0 && new < old); + self.set_clear_flag(FLAG_H, carry & 0x10 == 0x10); + } + + #[inline] + fn sbc_r(&mut self, val: u8) { + // Passes the test + let old: u8 = self.regs[REG_A]; + let mut new: u8 = old as u8; + let c: u8; + if self.flags & FLAG_C == FLAG_C { + c = 1; + } else { + c = 0; + } + new = new.wrapping_sub(val); + new = new.wrapping_sub(c); + + self.regs[REG_A] = new; + + self.set_flag(FLAG_N); + self.set_clear_flag(FLAG_Z, new == 0); + self.set_clear_flag(FLAG_C, new > old || (new == old && c == 1)); + self.set_clear_flag(FLAG_H, ((old & 0x0F) - (val & 0x0F) - c) > 0x0F); + } + + #[inline] + fn sub_r(&mut self, val: u8) { + // Passes the test + let old: u8 = self.regs[REG_A]; + let new: u8 = old.wrapping_sub(val); + let carry: u16 = (old as u16) ^ (val as u16) ^ (new as u16); + self.regs[REG_A] = new; + + self.set_flag(FLAG_N); + self.set_clear_flag(FLAG_Z, new == 0); + self.set_clear_flag(FLAG_C, new > old); + self.set_clear_flag(FLAG_H, carry & 0x10 == 0x10); + } + + #[inline] + fn cp_r(&mut self, val: u8) { + // Passes the test + let old: u8 = self.regs[REG_A]; + let new: u8 = old.wrapping_sub(val); + let carry: u16 = (old as u16) ^ (val as u16) ^ (new as u16); + + self.set_flag(FLAG_N); + self.set_clear_flag(FLAG_Z, new == 0); + self.set_clear_flag(FLAG_C, new > old); + self.set_clear_flag(FLAG_H, carry & 0x10 == 0x10); + } + #[inline] fn run_prefix_instruction(&mut self) { let instruction = self.read_byte(self.ip); @@ -561,7 +645,7 @@ impl CPU { #[inline] fn rst(&mut self, val: u8) -> u8 { // Make sure this is correct. - if self.debug { + if self.debug || true { println!("RST {:02X}", val); } self.call(val as u16); @@ -626,7 +710,7 @@ impl CPU { #[inline] fn ld_r_r(&mut self, reg_dst: usize, reg_src: usize) -> u8 { if self.debug { - // println!("LD {}, {}", REG_NAMES[reg_dst], REG_NAMES[reg_src]) + println!("LD {}, {}", REG_NAMES[reg_dst], REG_NAMES[reg_src]) } let sv = self.get_8bit_reg(reg_src); self.set_8bit_reg(reg_dst, sv); @@ -641,7 +725,7 @@ impl CPU { fn ld_r_v(&mut self, r: usize) -> u8 { let val: u8 = self.load_args(1)[0]; if self.debug { - // println!("LD {}, {:02X}", REG_NAMES[r], val); + println!("LD {}, {:02X}", REG_NAMES[r], val); } self.set_8bit_reg(r, val); if r == REG_N_HL { @@ -655,7 +739,7 @@ impl CPU { fn ld_rr_vv(&mut self, r1: usize, r2: usize) -> u8 { let val: u16 = to_u16(self.load_args(2)); if self.debug { - // println!("LD {}{}, {:04X}", REG_NAMES[r1], REG_NAMES[r2], val); + println!("LD {}{}, {:04X}", REG_NAMES[r1], REG_NAMES[r2], val); } self.set_pair_value(r1, r2, val); 12 @@ -676,9 +760,21 @@ impl CPU { #[inline] fn add_rr_rr(&mut self, r1: usize, r2: usize, r3: usize, r4: usize) -> u8 { + if self.debug { + println!("ADD {}{}, {}{}", REG_NAMES[r1], REG_NAMES[r2], REG_NAMES[r3], REG_NAMES[r4]); + } + let val1 = self.get_pair_value(r1, r2); let val2 = self.get_pair_value(r3, r4); - self.set_pair_value(r1, r2, val1.wrapping_add(val2)); + let res = val1.wrapping_add(val2); + self.set_pair_value(r1, r2, res); + + // We need to update the flags + self.clear_flag(FLAG_N); + + // Some magic formula + self.set_clear_flag(FLAG_C, val1 as usize + val2 as usize & 0x10000 == 0x10000); + self.set_clear_flag(FLAG_H, (val1 ^ val2 ^ res) & 0x1000 == 0x1000); 8 } @@ -961,22 +1057,22 @@ impl CPU { if self.flags & FLAG_N == 0 { // Lower nibble - if self.flags & FLAG_H > 0 || (v & 0xF) > 9 { + if self.flags & FLAG_H == FLAG_H || (v & 0xF) > 9 { v += 0x06; } // Higher nibble - if self.flags & FLAG_C > 0 || v > 0x9F { + if self.flags & FLAG_C == FLAG_C || v > 0x9F { v += 0x60; } } else { // Lower nibble - if self.flags & FLAG_H > 0 { + if self.flags & FLAG_H == FLAG_H { v = v.wrapping_sub(6) & 0xFF; } // Higher nibble - if self.flags & FLAG_C > 0 { + if self.flags & FLAG_C == FLAG_C { v = v.wrapping_sub(0x60); } } @@ -989,7 +1085,7 @@ impl CPU { 4 }, 0x28 => { - let c = self.flags & FLAG_Z > 0; + let c = self.flags & FLAG_Z == FLAG_Z; self.jmp_r_condition("Z".to_owned(), c) }, 0x29 => self.add_rr_rr(REG_N_H, REG_N_L, REG_N_H, REG_N_L), @@ -1033,7 +1129,7 @@ impl CPU { if self.debug { println!("LD (HL-), A"); } - let mut addr = self.get_pair_value(REG_N_H, REG_N_L); + let addr = self.get_pair_value(REG_N_H, REG_N_L); self.interconnect.write_byte(addr, self.regs[REG_A]); self.set_pair_value(REG_N_H, REG_N_L, addr.wrapping_sub(1)); 8 @@ -1059,7 +1155,7 @@ impl CPU { 4 }, 0x38 => { - let c = self.flags & FLAG_C > 0; + let c = self.flags & FLAG_C == FLAG_C; self.jmp_r_condition("C".to_owned(), c) }, 0x39 => { @@ -1073,8 +1169,8 @@ impl CPU { self.clear_flag(FLAG_N); self.set_clear_flag(FLAG_C, old > v); - // TODO: H-carry flag - + // Is this correct? I don't know: + self.set_clear_flag(FLAG_H, (old & 0x8 | sp & 0x8) == 1 && v & 0x8 == 0); 8 }, 0x3A => { @@ -1131,14 +1227,8 @@ impl CPU { if self.debug { println!("ADD {}", REG_NAMES[reg_id]); } - let old = self.regs[REG_A]; - let new = old.wrapping_add(self.get_8bit_reg(reg_id)); - self.regs[REG_A] = new; - - self.clear_flag(FLAG_N); - self.set_clear_flag(FLAG_Z, new == 0); - self.set_clear_flag(FLAG_C, new < old); - // TODO: H + let v = self.get_8bit_reg(reg_id); + self.add_r(v); 4 } @@ -1149,17 +1239,8 @@ impl CPU { println!("ADC {}", REG_NAMES[reg_id]); } - let old = self.regs[REG_A]; - let mut new = old.wrapping_add(self.get_8bit_reg(reg_id)); - if self.flags & FLAG_C > 0 { - new = new.wrapping_add(1); - } - self.regs[REG_A] = new; - - self.clear_flag(FLAG_N); - self.set_clear_flag(FLAG_Z, new == 0); - self.set_clear_flag(FLAG_C, new < old); - // TODO: H + let v = self.get_8bit_reg(reg_id); + self.adc_r(v); 4 } @@ -1169,13 +1250,8 @@ impl CPU { if self.debug { println!("SUB {}", REG_NAMES[reg_id]); } - let old = self.regs[REG_A]; - let new = old.wrapping_sub(self.get_8bit_reg(reg_id)); - self.regs[REG_A] = new; - self.set_flag(FLAG_N); - self.set_clear_flag(FLAG_Z, new == 0); - self.set_clear_flag(FLAG_C, new > old); - // TODO: H + let r = self.get_8bit_reg(reg_id); + self.sub_r(r); 4 } @@ -1185,16 +1261,8 @@ impl CPU { if self.debug { println!("SBC {}", REG_NAMES[reg_id]); } - let old = self.regs[REG_A]; - let mut new = old.wrapping_sub(self.get_8bit_reg(reg_id)); - if self.flags & FLAG_C > 0 { - new = new.wrapping_sub(1); - } - self.regs[REG_A] = new; - - self.set_flag(FLAG_N); - self.set_clear_flag(FLAG_Z, new == 0); - self.set_clear_flag(FLAG_C, new > old); + let r = self.get_8bit_reg(reg_id); + self.sbc_r(r); 4 } @@ -1252,13 +1320,9 @@ impl CPU { if self.debug { println!("CP {}", REG_NAMES[reg_id]); } - let val = self.get_8bit_reg(reg_id); - let rval = self.regs[REG_A]; - self.set_flag(FLAG_N); - self.set_clear_flag(FLAG_C, rval < val); - self.set_clear_flag(FLAG_Z, rval == val); - // TODO H + let v = self.get_8bit_reg(reg_id); + self.cp_r(v); 4 }, @@ -1286,24 +1350,19 @@ impl CPU { if self.debug { println!("ADD A, {:02X}", val); } - let o = self.regs[REG_A]; - let v = self.regs[REG_A].wrapping_add(val); - self.regs[REG_A] = v; - self.set_clear_flag(FLAG_Z, v == 0); - self.set_clear_flag(FLAG_C, v < o); - self.clear_flag(FLAG_N); - // TOOD H + + self.add_r(val); 8 }, 0xC7 => self.rst(0x00), 0xC8 => { - let c = self.flags & FLAG_Z > 0; + let c = self.flags & FLAG_Z == FLAG_Z; self.ret_condition("Z".to_owned(), c) }, 0xC9 => {self.ret(); 16}, 0xCA => { - let c = self.flags & FLAG_Z > 0; + let c = self.flags & FLAG_Z == FLAG_Z; self.jmp_p_condition("Z".to_owned(), c) } 0xCB => { @@ -1312,7 +1371,7 @@ impl CPU { 12 // TODO: Verify that this is the case for all prefix instructions. }, 0xCC => { - let c = self.flags & FLAG_Z > 0; + let c = self.flags & FLAG_Z == FLAG_Z; self.call_condition("Z".to_owned(), c) }, 0xCD => self.call_condition("".to_owned(), true), @@ -1321,19 +1380,7 @@ impl CPU { if self.debug { println!("ADC A, {:02X}", arg); } - let o = self.regs[REG_A]; - let mut v = self.regs[REG_A].wrapping_add(arg); - - if self.flags & FLAG_C > 0 { - v = v.wrapping_add(1); - } - - self.regs[REG_A] = v; - - self.set_clear_flag(FLAG_Z, v == 0); - self.clear_flag(FLAG_N); - self.set_clear_flag(FLAG_C, v < o); - // TODO: FLAG_H + self.adc_r(arg); 8 }, 0xCF => self.rst(0x08), @@ -1360,29 +1407,22 @@ impl CPU { println!("SUB {:02X}", val); } - let rval = self.regs[REG_A]; - self.set_clear_flag(FLAG_C, val > rval); - self.set_clear_flag(FLAG_Z, val == rval); - self.set_flag(FLAG_N); - - self.regs[REG_A] = rval.wrapping_sub(val); - - // TODO: FLAG_H + self.sub_r(val); 8 }, 0xD7 => self.rst(0x10), 0xD8 => { - let c = self.flags & FLAG_C > 0; + let c = self.flags & FLAG_C == FLAG_C; self.ret_condition("C".to_owned(), c) }, 0xD9 => self.reti(), 0xDA => { - let c = self.flags & FLAG_C > 0; + let c = self.flags & FLAG_C == FLAG_C; self.jmp_p_condition("C".to_owned(), c) }, 0xDB => panic!("NON-EXISTING OPCODE"), 0xDC => { - let c = self.flags & FLAG_C > 0; + let c = self.flags & FLAG_C == FLAG_C; self.call_condition("C".to_owned(), c) } 0xDD => panic!("NON-EXISTING OPCODE"), @@ -1391,17 +1431,7 @@ impl CPU { if self.debug { println!("SBC {:02X}", arg); } - let o = self.regs[REG_A]; - let mut v = self.regs[REG_A].wrapping_sub(arg); - - if self.flags & FLAG_C > 0 { - v = v.wrapping_sub(1); - } - self.regs[REG_A] = v; - self.set_clear_flag(FLAG_Z, v == 0); - self.set_clear_flag(FLAG_C, v > o); - self.set_flag(FLAG_N); - // TODO: FLAG_H + self.sbc_r(arg); 8 }, 0xDF => self.rst(0x18), @@ -1441,16 +1471,21 @@ impl CPU { }, 0xE7 => self.rst(0x20), 0xE8 => { - let arg = self.load_args(1)[0]; + let arg = self.load_args(1)[0] as i8; if self.debug { println!("ADD SP, {:02X}", arg); } - let t = self.sp.wrapping_add(arg as u16); + let t: u16; + if arg > 0 { + t = self.sp.wrapping_add(arg as u16); + } else { + t = self.sp.wrapping_sub((-arg) as u16); + } let sp = self.sp; self.clear_flag(FLAG_N); self.clear_flag(FLAG_Z); - self.set_clear_flag(FLAG_C, t < sp); - // TODO FLAG_H + self.set_clear_flag(FLAG_C, (sp ^ arg as u16 ^ t) & 0x100 == 0x100); + self.set_clear_flag(FLAG_H, (sp ^ arg as u16 ^ t) & 0x10 == 0x10); self.sp = t; 16 } @@ -1526,21 +1561,26 @@ impl CPU { }, 0xF7 => self.rst(0x30), 0xF8 => { - let arg = self.load_args(1)[0] as i16; + let arg = self.load_args(1)[0] as i8; if self.debug { println!("LD HL, SP+{:02X}", arg); } + self.clear_flag(FLAG_N); + self.clear_flag(FLAG_Z); + let sp = self.sp; + if arg < 0 { let v: u16 = self.sp.wrapping_sub((-arg) as u16); self.set_pair_value(REG_N_H, REG_N_L, v); + self.set_clear_flag(FLAG_C, (sp ^ arg as u16 ^ v) & 0x100 == 0x100); + self.set_clear_flag(FLAG_H, (sp ^ arg as u16 ^ v) & 0x10 == 0x10); } else { let v: u16 = self.sp.wrapping_add(arg as u16); self.set_pair_value(REG_N_H, REG_N_L, v); + self.set_clear_flag(FLAG_C, (sp ^ arg as u16 ^ v) & 0x100 == 0x100); + self.set_clear_flag(FLAG_H, (sp ^ arg as u16 ^ v) & 0x10 == 0x10); } - self.clear_flag(FLAG_N); - self.clear_flag(FLAG_Z); - // TODO: FLAG_H FLAG_C 12 }, 0xF9 => { @@ -1570,15 +1610,11 @@ impl CPU { 0xFE => { let args = self.load_args(1); - let rval = self.regs[REG_A]; if self.debug { println!("CP {:02X}", args[0]); } - self.set_flag(FLAG_N); - self.set_clear_flag(FLAG_C, args[0] > rval); - self.set_clear_flag(FLAG_Z, args[0] == rval); - // TODO H + self.cp_r(args[0]); 8 }, 0xFF => self.rst(0x38),