From 710b057f54e133e52102b16f8431dc8a842aba0f Mon Sep 17 00:00:00 2001 From: Kevin Hamacher Date: Sat, 28 May 2016 15:41:44 +0200 Subject: [PATCH] Honor flags more. Deny direct reg access --- src/cpu.rs | 272 ++++++++++++++++++++++++++++++++------------ src/display.rs | 22 +++- src/interconnect.rs | 12 +- 3 files changed, 226 insertions(+), 80 deletions(-) diff --git a/src/cpu.rs b/src/cpu.rs index d816933..422c860 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -1,11 +1,11 @@ use super::interconnect; -const REG_B: usize = 0; -const REG_C: usize = 1; -const REG_D: usize = 2; -const REG_E: usize = 3; -const REG_H: usize = 4; -const REG_L: usize = 5; +//const REG_B: usize = 0; +//const REG_C: usize = 1; +//const REG_D: usize = 2; +//const REG_E: usize = 3; +//const REG_H: usize = 4; +//const REG_L: usize = 5; const REG_A: usize = 6; const REG_N_B: usize = 0; @@ -78,7 +78,7 @@ impl CPU { } else if reg_id == REG_N_F { self.flags = value; } else if reg_id == REG_N_HL { - let addr: u16 = self.get_pair_value(REG_H, REG_L); + let addr: u16 = self.get_pair_value(REG_N_H, REG_N_L); self.interconnect.write_byte(addr, value); } else { self.regs[reg_id] = value; @@ -92,7 +92,7 @@ impl CPU { } else if reg_id == REG_N_F { self.flags } else if reg_id == REG_N_HL { - let addr: u16 = self.get_pair_value(REG_H, REG_L); + let addr: u16 = self.get_pair_value(REG_N_H, REG_N_L); self.interconnect.read_byte(addr) } else { self.regs[reg_id] @@ -104,6 +104,42 @@ impl CPU { self.ip += 1; match instruction { + 0x00 ... 0x07 => { + let reg_id = (instruction - 0x00) as usize; + let val = self.get_8bit_reg(reg_id); + if self.debug { + println!("RLC {}", REG_NAMES[reg_id]); + } + + if val & 0x80 == 0x80 { + self.set_flag(FLAG_C); + self.set_8bit_reg(reg_id, val << 1 | 1); + } else { + self.set_8bit_reg(reg_id, val << 1); + } + + self.set_clear_flag(FLAG_Z, val == 0); + self.clear_flag(FLAG_N); + self.clear_flag(FLAG_H); + }, + 0x08 ... 0x0F => { + let reg_id = (instruction - 0x08) as usize; + let val = self.get_8bit_reg(reg_id); + if self.debug { + println!("RRC {}", REG_NAMES[reg_id]); + } + + if val & 1 > 0 { + self.set_flag(FLAG_C); + self.set_8bit_reg(reg_id, val >> 1 | 0x80); + } else { + self.set_8bit_reg(reg_id, val >> 1); + } + + self.set_clear_flag(FLAG_Z, val == 0); + self.clear_flag(FLAG_N); + self.clear_flag(FLAG_H); + }, 0x10 ... 0x17 => { let reg_id = (instruction - 0x10) as usize; let val = self.get_8bit_reg(reg_id); @@ -152,6 +188,24 @@ impl CPU { self.clear_flag(FLAG_N); self.clear_flag(FLAG_H); }, + 0x20 ... 0x27 => { + let reg_id = (instruction - 0x20) as usize; + if self.debug { + println!("SLA {}", REG_NAMES[reg_id]); + } + let v: u8 = self.get_8bit_reg(reg_id); + self.set_clear_flag(FLAG_C, v & 0x80 > 0); + self.set_8bit_reg(reg_id, v << 1); + }, + 0x28 ... 0x2F => { + let reg_id = (instruction - 0x20) as usize; + if self.debug { + println!("SRA {}", REG_NAMES[reg_id]); + } + let v: u8 = self.get_8bit_reg(reg_id); + self.set_clear_flag(FLAG_C, v & 1 > 0); + self.set_8bit_reg(reg_id, v >> 1); + }, 0x30 ... 0x37 => { let reg_id = (instruction - 0x30) as usize; if self.debug { @@ -296,6 +350,7 @@ impl CPU { fn call(&mut self, dst: u16) { let ip = self.ip; self.push(ip); + self.dump_stack(); self.ip = dst; } @@ -398,7 +453,7 @@ impl CPU { let val = self.get_8bit_reg(reg_id).wrapping_add(1); self.set_8bit_reg(reg_id, val); self.set_clear_flag(FLAG_Z, val == 0); - self.set_clear_flag(FLAG_C, val == 0); + // self.set_clear_flag(FLAG_C, val == 0); self.clear_flag(FLAG_N); 4 } @@ -418,7 +473,7 @@ impl CPU { self.set_8bit_reg(reg_id, val); self.set_clear_flag(FLAG_Z, val == 0); - self.set_clear_flag(FLAG_C, val == 255); + // self.set_clear_flag(FLAG_C, val == 255); self.set_flag(FLAG_N); 4 } @@ -460,6 +515,7 @@ impl CPU { fn ret(&mut self) { let new_ip: u16 = self.pop(); + self.dump_stack(); self.ip = new_ip; } @@ -544,13 +600,20 @@ impl CPU { 20 } 0x09 => self.add_rr_rr(REG_N_H, REG_N_L, REG_N_B, REG_N_C), + 0x0A => { + if self.debug { + println!("LD A, (BC)"); + } + self.regs[REG_A] = self.interconnect.read_byte(self.get_pair_value(REG_N_B, REG_N_C)); + 8 + }, 0x0B => self.dec_rr(REG_N_B, REG_N_C), 0x0C => self.reg_inc(REG_N_C), 0x0D => self.reg_dec(REG_N_C), 0x0E => self.ld_r_v(REG_N_C), 0x11 => self.ld_rr_vv(REG_N_D, REG_N_E), - 0x12 => self.ld_dref_rr_a(REG_D, REG_E), - 0x13 => self.inc_rr(REG_D, REG_E), + 0x12 => self.ld_dref_rr_a(REG_N_D, REG_N_E), + 0x13 => self.inc_rr(REG_N_D, REG_N_E), 0x14 => self.reg_inc(REG_N_D), 0x15 => self.reg_dec(REG_N_D), 0x16 => self.ld_r_v(REG_N_D), @@ -559,16 +622,11 @@ impl CPU { println!("RLA"); } let carry = self.flags & FLAG_C > 0; + let val = self.regs[REG_A]; + self.set_clear_flag(FLAG_C, val & 0x80 == 0x80); if !carry { - // No carry before, now we got a carry => set it - if self.regs[REG_A] & 0x80 == 0x80 { - self.set_flag(FLAG_C); - } self.regs[REG_A] = self.regs[REG_A] << 1; } else { - if self.regs[REG_A] & 0x80 == 0 { - self.clear_flag(FLAG_C); - } self.regs[REG_A] = self.regs[REG_A] << 1 | 1; } self.clear_flag(FLAG_Z); @@ -594,28 +652,23 @@ impl CPU { if self.debug { println!("LD A, (DE)"); } - self.regs[REG_A] = self.interconnect.read_byte(self.get_pair_value(REG_D, REG_E)); + self.regs[REG_A] = self.interconnect.read_byte(self.get_pair_value(REG_N_D, REG_N_E)); 8 }, 0x1B => self.dec_rr(REG_N_D, REG_N_E), 0x1C => self.reg_inc(REG_N_E), 0x1D => self.reg_dec(REG_N_E), 0x1E => self.ld_r_v(REG_N_E), - 0x1F => { // UNTESTED + 0x1F => { if self.debug { println!("RRA"); } let carry = self.flags & FLAG_C > 0; + let val = self.regs[REG_A]; + self.set_clear_flag(FLAG_C, val & 1 == 1); if !carry { - // No carry before, now we got a carry => set it - if self.regs[REG_A] & 1 == 1 { - self.set_flag(FLAG_C); - } self.regs[REG_A] = self.regs[REG_A] >> 1; } else { - if self.regs[REG_A] & 1 == 0 { - self.clear_flag(FLAG_C); - } self.regs[REG_A] = self.regs[REG_A] >> 1 | 0x80; } self.clear_flag(FLAG_Z); @@ -645,12 +698,12 @@ impl CPU { if self.debug { println!("LD (HL+), A"); } - let addr: u16 = self.get_pair_value(REG_H, REG_L); + let addr: u16 = self.get_pair_value(REG_N_H, REG_N_L); self.interconnect.write_byte(addr, self.regs[REG_A]); - self.set_pair_value(REG_H, REG_L, addr.wrapping_add(1)); + self.set_pair_value(REG_N_H, REG_N_L, addr.wrapping_add(1)); 8 }, - 0x23 => self.inc_rr(REG_H, REG_L), + 0x23 => self.inc_rr(REG_N_H, REG_N_L), 0x24 => self.reg_inc(REG_N_H), 0x25 => self.reg_dec(REG_N_H), 0x26 => self.ld_r_v(REG_N_H), @@ -677,9 +730,9 @@ impl CPU { if self.debug { println!("LD A, (HL+)"); } - let addr: u16 = self.get_pair_value(REG_H, REG_L); + let addr: u16 = self.get_pair_value(REG_N_H, REG_N_L); self.regs[REG_A] = self.interconnect.read_byte(addr); - self.set_pair_value(REG_H, REG_L, addr+1); + self.set_pair_value(REG_N_H, REG_N_L, addr.wrapping_add(1)); 8 }, 0x2B => self.dec_rr(REG_N_H, REG_N_L), @@ -691,6 +744,8 @@ impl CPU { println!("CPL"); } self.regs[REG_A] = !self.regs[REG_A]; + self.set_flag(FLAG_N); + self.set_flag(FLAG_H); 4 }, 0x30 => { @@ -722,20 +777,30 @@ impl CPU { if self.debug { println!("LD (HL-), A"); } - let mut addr = self.get_pair_value(REG_H, REG_L); + let mut addr = self.get_pair_value(REG_N_H, REG_N_L); self.interconnect.write_byte(addr, self.regs[REG_A]); - - addr -= 1; - self.set_pair_value(REG_H, REG_L, addr); + self.set_pair_value(REG_N_H, REG_N_L, addr.wrapping_sub(1)); 8 }, + 0x33 => { + if self.debug { + println!("INC SP"); + } + let sp = self.sp.wrapping_add(1); + self.sp = sp; + self.set_clear_flag(FLAG_Z, sp == 0); + self.set_clear_flag(FLAG_C, sp == 0); + self.clear_flag(FLAG_N); + 8 + } + 0x34 => self.reg_inc(REG_N_HL), 0x35 => self.reg_dec(REG_N_HL), 0x36 => { let args = self.load_args(1); if self.debug { println!("LD (HL), {:02x}", args[0]); } - let addr = self.get_pair_value(REG_H, REG_L); + let addr = self.get_pair_value(REG_N_H, REG_N_L); self.interconnect.write_byte(addr, args[0]); 12 }, @@ -744,6 +809,8 @@ impl CPU { println!("SCF"); } self.set_flag(FLAG_C); + self.clear_flag(FLAG_N); + self.clear_flag(FLAG_H); 4 }, 0x38 => { @@ -768,8 +835,24 @@ impl CPU { println!("ADD HL, SP"); } let sp = self.sp; - let v = self.get_pair_value(REG_N_H, REG_N_L).wrapping_add(sp); + let old = self.get_pair_value(REG_N_H, REG_N_L); + let v = old.wrapping_add(sp); self.set_pair_value(REG_N_H, REG_N_L, v); + + self.clear_flag(FLAG_N); + self.set_clear_flag(FLAG_C, old > v); + + 8 + }, + 0x3B => { + if self.debug { + println!("DEC SP"); + } + let sp = self.sp.wrapping_sub(1); + self.sp = sp; + self.set_clear_flag(FLAG_Z, sp == 0); + self.set_clear_flag(FLAG_C, sp == 0xFFFF); + self.set_flag(FLAG_N); 8 } 0x3C => self.reg_inc(REG_N_A), @@ -780,6 +863,7 @@ impl CPU { println!("CCF"); } self.flags ^= FLAG_C; + self.clear_flag(FLAG_N); 4 } @@ -808,9 +892,14 @@ impl CPU { if self.debug { println!("ADD {}", REG_NAMES[reg_id]); } - self.regs[REG_A] = self.regs[REG_A].wrapping_add(self.get_8bit_reg(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 4 } @@ -818,12 +907,18 @@ impl CPU { 0x88 ... 0x8F => { let reg_id = (instruction - 0x88) as usize; println!("ADC {}", REG_NAMES[reg_id]); - self.regs[REG_A] = self.regs[REG_A].wrapping_add(self.get_8bit_reg(reg_id)); - if self.flags & FLAG_C == FLAG_C { - self.regs[REG_A] = self.regs[REG_A].wrapping_add(1); - } - self.set_flag(FLAG_N); + 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 4 } @@ -833,14 +928,13 @@ impl CPU { if self.debug { println!("SUB {}", REG_NAMES[reg_id]); } - self.regs[REG_A] = self.regs[REG_A].wrapping_sub(self.get_8bit_reg(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); - if self.regs[REG_A] == 0 { - self.set_flag(FLAG_Z); - } else { - self.clear_flag(FLAG_Z); - } - // TODO: H, C + self.set_clear_flag(FLAG_Z, new == 0); + self.set_clear_flag(FLAG_C, new > old); + // TODO: H 4 } @@ -850,16 +944,16 @@ impl CPU { if self.debug { println!("SBC {}", REG_NAMES[reg_id]); } - self.regs[REG_A] = self.regs[REG_A].wrapping_sub(self.get_8bit_reg(reg_id)); - if self.flags & FLAG_C == FLAG_C { - self.regs[REG_A] = self.regs[REG_A].wrapping_sub(1); + 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); - if self.regs[REG_A] == 0 { - self.set_flag(FLAG_Z); - } else { - self.clear_flag(FLAG_Z); - } + self.set_clear_flag(FLAG_Z, new == 0); + self.set_clear_flag(FLAG_C, new > old); 4 } @@ -876,6 +970,9 @@ impl CPU { } else { self.clear_flag(FLAG_Z); } + self.clear_flag(FLAG_N); + self.set_flag(FLAG_H); + self.clear_flag(FLAG_C); 4 } @@ -905,12 +1002,12 @@ impl CPU { println!("OR {}", REG_NAMES[reg_id]); } self.regs[REG_A] |= self.get_8bit_reg(reg_id); + let v = self.regs[REG_A]; + + self.set_clear_flag(FLAG_Z, v == 0); + self.clear_flag(FLAG_C); self.clear_flag(FLAG_N); - if self.regs[REG_A] == 0 { - self.set_flag(FLAG_Z); - } else { - self.clear_flag(FLAG_Z); - } + self.clear_flag(FLAG_H); 4 } @@ -939,7 +1036,7 @@ impl CPU { 8 } }, - 0xC1 => self.pop_rr(REG_B, REG_C), + 0xC1 => self.pop_rr(REG_N_B, REG_N_C), 0xC2 => { let addr: u16 = to_u16(self.load_args(2)); if self.debug { @@ -972,7 +1069,7 @@ impl CPU { 12 } }, - 0xC5 => self.push_rr(REG_B, REG_C), + 0xC5 => self.push_rr(REG_N_B, REG_N_C), 0xC6 => { let val = self.load_args(1)[0]; if self.debug { @@ -1056,8 +1153,8 @@ impl CPU { 8 } }, - 0xD1 => self.pop_rr(REG_D, REG_E), - 0xD5 => self.push_rr(REG_D, REG_E), + 0xD1 => self.pop_rr(REG_N_D, REG_N_E), + 0xD5 => self.push_rr(REG_N_D, REG_N_E), 0xD6 => { let val = self.load_args(1)[0]; if self.debug { @@ -1083,7 +1180,8 @@ impl CPU { } else { 8 } - } + }, + 0xD9 => self.reti(), 0xDE => { let arg = self.load_args(1)[0]; if self.debug { @@ -1115,12 +1213,12 @@ impl CPU { 0xE2 => { if self.debug { println!("LD (C), A"); - println!("[{:04X}] = {:02X}", 0xFF00 + self.regs[REG_C] as u16, self.regs[REG_A]); } - self.interconnect.write_byte(0xFF00 + self.regs[REG_C] as u16, self.regs[REG_A]); + let addr = 0xFF00 + self.get_8bit_reg(REG_N_C); + self.interconnect.write_byte(0xFF00 + addr as u16, self.regs[REG_A]); 8 }, - 0xE5 => self.push_rr(REG_H, REG_L), + 0xE5 => self.push_rr(REG_N_H, REG_N_L), 0xE6 => { let val = self.load_args(1)[0]; if self.debug { @@ -1130,6 +1228,19 @@ impl CPU { 8 }, 0xE7 => self.rst(0x20), + 0xE8 => { + let arg = self.load_args(1)[0]; + if self.debug { + println!("ADD SP, {:02X}", arg); + } + let t = self.sp.wrapping_add(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); + self.sp = t; + 16 + } 0xE9 => { if self.debug { println!("JP (HL)"); @@ -1176,7 +1287,8 @@ impl CPU { if self.debug{ println!("LD A, (C)"); } - self.regs[REG_A] = self.interconnect.read_byte(0xFF00 + self.regs[REG_C] as u16); + let addr = 0xFF00 + self.get_8bit_reg(REG_N_C) as u16; + self.regs[REG_A] = self.interconnect.read_byte(addr); 8 }, 0xF3 => { @@ -1196,6 +1308,18 @@ impl CPU { 8 }, 0xF7 => self.rst(0x30), + 0xF8 => { + let arg = self.load_args(1)[0]; + if self.debug { + println!("LD HL, SP+{:02X}", arg); + } + + let v = self.sp.wrapping_add(arg as u16); + self.clear_flag(FLAG_N); + self.clear_flag(FLAG_Z); + self.set_pair_value(REG_N_H, REG_N_L, v); + 12 + } 0xFB => { // Enable interrupts - TODO if self.debug { diff --git a/src/display.rs b/src/display.rs index 3002992..1092925 100644 --- a/src/display.rs +++ b/src/display.rs @@ -88,7 +88,7 @@ impl Display { windowx: 0, windowy: 0, curline: 0, - lyc: 255, + lyc: 0, current_ticks: 0, current_mode: DisplayMode::default(), @@ -175,10 +175,8 @@ impl Display { // Do we want to have a time delta here? pub fn tick(&mut self, ticks: u16) { self.current_ticks += ticks; - if self.curline == self.lyc { - self.stat_fired = true; - self.stat_interrupt = true; - } + self.status &= 0xFC; + match self.current_mode { DisplayMode::Scanline => { if self.current_ticks > TICKS_END_SCANLINE { @@ -187,6 +185,7 @@ impl Display { self.current_ticks = 0; self.current_mode = DisplayMode::Readmode; } + self.status |= 3; }, DisplayMode::Readmode => { if self.current_ticks > TICKS_END_READMODE { @@ -194,6 +193,7 @@ impl Display { self.current_mode = DisplayMode::HBlank; self.renderscan(); } + self.status |= 2; }, DisplayMode::HBlank => { if self.current_ticks > TICKS_END_HBLANK { @@ -207,6 +207,8 @@ impl Display { self.current_mode = DisplayMode::Scanline; } } + self.status &= 0xFC; + self.status |= 0; }, DisplayMode::VBlank => { if self.current_ticks > TICKS_END_VBLANK { @@ -220,8 +222,18 @@ impl Display { self.curline = 0; } } + self.status |= 1; } } + + // Update the status register + if self.curline == self.lyc { + self.status |= 1 << 2; + self.stat_fired = true; + self.stat_interrupt = true; + } else { + self.status &= !(1 << 2); + } } fn renderscan(&mut self) { diff --git a/src/interconnect.rs b/src/interconnect.rs index 4b4aa0c..4eec04c 100644 --- a/src/interconnect.rs +++ b/src/interconnect.rs @@ -142,9 +142,19 @@ impl Interconnect { 0xFF10 ... 0xFF26 => { self.sound.write_byte(addr, val); }, - 0xFF40 ... 0xFF4B => { + // Exclude DMA transfer, we will do this below + 0xFF40 ... 0xFF45 | 0xFF47 ... 0xFF4B => { self.display.write_byte(addr, val); }, + 0xFF46 => { + println!("DMA transfer: "); + for x in 0x00 .. 0x9F { + let dma_b = self.read_byte(((val as u16) << 8) | x); + self.write_byte(0xFE00 | x, dma_b); + print!("{:02X} ", val); + } + println!(""); + } 0xFF50 => { println!("Disabling boot rom."); self.disable_bootrom = val;