Honor flags more. Deny direct reg access

This commit is contained in:
Kevin Hamacher 2016-05-28 15:41:44 +02:00
parent d91fa7d75b
commit 710b057f54
3 changed files with 226 additions and 80 deletions

View File

@ -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 {

View File

@ -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) {

View File

@ -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;