Even more cleanup

This commit is contained in:
Kevin Hamacher 2016-05-26 20:25:44 +02:00
parent 79d2c99c06
commit 0fdfa9ae63
3 changed files with 151 additions and 244 deletions

View File

@ -8,6 +8,14 @@ const REG_H: usize = 4;
const REG_L: usize = 5;
const REG_A: usize = 6;
const REG_N_B: usize = 0;
const REG_N_C: usize = 1;
const REG_N_D: usize = 2;
const REG_N_E: usize = 3;
const REG_N_H: usize = 4;
const REG_N_L: usize = 5;
const REG_N_HL: usize = 6;
const REG_N_A: usize = 7;
const REG_NAMES: [&'static str; 8] = ["B", "C", "D", "E", "H", "L", "(HL)", "A"];
const FLAG_Z: u8 = 1 << 7;
@ -35,8 +43,6 @@ fn to_u16(bytes: Box<[u8]>) -> u16 {
impl CPU {
pub fn new(interconnect: interconnect::Interconnect) -> CPU {
// Ugly patch ^.^
// interconnect.write_byte(0xFF44 as u16, 0x90);
CPU {
flags: 0,
regs: [0, 0, 0, 0, 0, 0, 0],
@ -223,15 +229,49 @@ impl CPU {
}
}
fn reg_inc(&mut self, reg_id: usize) {
fn push_rr(&mut self, r1: usize, r2: usize) -> u8 {
if self.debug {
println!("PUSH {}{}", REG_NAMES[r1], REG_NAMES[r2]);
}
let val: u16 = self.get_pair_value(r1, r2);
self.push(val);
16
}
fn push(&mut self, val: u16) {
self.interconnect.write_word(self.sp - 2, val);
self.sp -= 2;
}
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])
}
let sv = self.get_8bit_reg(reg_src);
self.set_8bit_reg(reg_dst, sv);
if reg_dst == REG_N_HL || reg_src == REG_N_HL {
8
} else {
4
}
}
fn reg_inc(&mut self, reg_id: usize) -> u8 {
if self.debug {
println!("INC {}", REG_NAMES[reg_id]);
}
self.regs[reg_id] = self.regs[reg_id].wrapping_add(1);
if self.regs[reg_id] == 0 {
self.flags |= FLAG_Z;
}
self.flags &= !FLAG_N;
4
}
fn reg_dec(&mut self, reg_id: usize) {
fn reg_dec(&mut self, reg_id: usize) -> u8 {
if self.debug {
println!("DEC {}", REG_NAMES[reg_id]);
}
self.regs[reg_id] = self.regs[reg_id].wrapping_sub(1);
if self.regs[reg_id] == 0 {
self.flags |= FLAG_Z;
@ -239,6 +279,7 @@ impl CPU {
self.flags &= !FLAG_Z;
}
self.flags |= FLAG_N;
4
}
fn set_flag(&mut self, flag: u8) {
@ -268,14 +309,12 @@ impl CPU {
}
self.ip += 1;
let cycles: u16;
match instruction {
let cycles: u8 = match instruction {
0x00 => {
if self.debug {
println!("NOP");
}
cycles = 4;
4
},
0x01 => {
if self.debug {
@ -284,7 +323,7 @@ impl CPU {
let addr: u16 = self.get_pair_value(REG_B, REG_C);
let val: u8 = self.regs[REG_A];
self.interconnect.write_byte(addr, val);
cycles = 12;
12
},
0x02 => {
if self.debug {
@ -293,51 +332,27 @@ impl CPU {
let addr: u16 = self.get_pair_value(REG_B, REG_C);
let val: u8 = self.regs[REG_A];
self.interconnect.write_byte(addr, val);
cycles = 8;
},
0x04 => {
if self.debug{
println!("INC B");
}
self.reg_inc(REG_B);
cycles = 4;
},
0x05 => {
if self.debug {
println!("DEC B");
}
self.reg_dec(REG_B);
cycles = 4;
8
},
0x04 => self.reg_inc(REG_B),
0x05 => self.reg_dec(REG_B),
0x06 => {
let args = self.load_args(1);
if self.debug {
println!("LD B, {:02x}", args[0]);
}
self.regs[REG_B] = args[0];
cycles = 8;
},
0x0C => {
if self.debug {
println!("INC C");
}
self.reg_inc(REG_C);
cycles = 4;
},
0x0D => {
if self.debug {
println!("DEC C");
}
self.reg_dec(REG_C);
cycles = 4;
8
},
0x0C => self.reg_inc(REG_C),
0x0D => self.reg_dec(REG_C),
0x0E => {
let args = self.load_args(1);
if self.debug {
println!("LD C, {:02x}", args[0]);
}
self.regs[REG_C] = args[0];
cycles = 8;
8
},
0x11 => {
let args = self.load_args(2);
@ -346,7 +361,7 @@ impl CPU {
println!("LD DE, {:04x}", val);
}
self.set_pair_value(REG_D, REG_E, val);
cycles = 12;
12
},
0x12 => {
if self.debug {
@ -355,7 +370,7 @@ impl CPU {
let addr: u16 = self.get_pair_value(REG_D, REG_E);
let val: u8 = self.regs[REG_A];
self.interconnect.write_byte(addr, val);
cycles = 12;
12
},
0x13 => {
if self.debug {
@ -363,29 +378,17 @@ impl CPU {
}
let old_value = self.get_pair_value(REG_D, REG_E);
self.set_pair_value(REG_D, REG_E, old_value + 1);
cycles = 8;
},
0x14 => {
if self.debug {
println!("INC D");
}
self.reg_inc(REG_D);
cycles = 4;
},
0x15 => {
if self.debug {
println!("DEC D");
}
self.reg_dec(REG_D);
cycles = 4;
8
},
0x14 => self.reg_inc(REG_D),
0x15 => self.reg_dec(REG_D),
0x16 => {
let args = self.load_args(1);
if self.debug {
println!("LD D, {:02x}", args[0]);
}
self.regs[REG_D] = args[0];
cycles = 8;
8
},
0x17 => {
if self.debug {
@ -404,7 +407,7 @@ impl CPU {
}
self.regs[REG_A] = self.regs[REG_A] << 1 | 1;
}
cycles = 4;
4
},
0x18 => {
let args = self.load_args(1);
@ -417,36 +420,24 @@ impl CPU {
} else {
self.ip += off as u16;
}
cycles = 12;
12
},
0x1A => {
if self.debug {
println!("LD A, (DE)");
}
self.regs[REG_A] = self.interconnect.read_byte(self.get_pair_value(REG_D, REG_E));
cycles = 8;
},
0x1C => {
if self.debug {
println!("INC E");
}
self.reg_inc(REG_E);
cycles = 4;
},
0x1D => {
if self.debug {
println!("DEC E");
}
self.reg_dec(REG_E);
cycles = 4;
8
},
0x1C => self.reg_inc(REG_E),
0x1D => self.reg_dec(REG_E),
0x1E => {
let args = self.load_args(1);
if self.debug {
println!("LD E, {:02x}", args[0]);
}
self.regs[REG_E] = args[0];
cycles = 8;
8
},
0x20 => {
let args = self.load_args(1);
@ -460,9 +451,9 @@ impl CPU {
} else {
self.ip += offset as u16;
}
cycles = 12;
12
} else {
cycles = 8;
8
}
}
0x21 => {
@ -471,7 +462,7 @@ impl CPU {
println!("LD HL, {:04x}", value);
}
self.set_pair_value(REG_H, REG_L, value);
cycles = 12;
12
},
0x22 => {
if self.debug {
@ -480,7 +471,7 @@ impl CPU {
let addr: u16 = self.get_pair_value(REG_H, REG_L);
self.interconnect.write_byte(addr, self.regs[REG_A]);
self.set_pair_value(REG_H, REG_L, addr + 1);
cycles = 8;
8
},
0x23 => {
if self.debug {
@ -488,29 +479,17 @@ impl CPU {
}
let old_value = self.get_pair_value(REG_H, REG_L);
self.set_pair_value(REG_H, REG_L, old_value + 1);
cycles = 8;
},
0x24 => {
if self.debug {
println!("INC H");
}
self.reg_inc(REG_H);
cycles = 4;
},
0x25 => {
if self.debug {
println!("DEC H");
}
self.reg_dec(REG_H);
cycles = 4;
8
},
0x24 => self.reg_inc(REG_H),
0x25 => self.reg_dec(REG_H),
0x26 => {
let args = self.load_args(1);
if self.debug {
println!("LD H, {:02x}", args[0]);
}
self.regs[REG_H] = args[0];
cycles = 8;
8
},
0x28 => {
let args = self.load_args(1);
@ -525,9 +504,9 @@ impl CPU {
}
if self.flags & FLAG_Z > 0 {
self.ip = target;
cycles = 12;
12
} else {
cycles = 8;
8
}
},
0x2A => {
@ -536,29 +515,17 @@ impl CPU {
}
let addr: u16 = self.get_pair_value(REG_H, REG_L);
self.regs[REG_A] = self.interconnect.read_byte(addr);
cycles = 8;
},
0x2C => {
if self.debug {
println!("INC L");
}
self.reg_inc(REG_L);
cycles = 4;
},
0x2D => {
if self.debug {
println!("DEC L");
}
self.reg_dec(REG_L);
cycles = 4;
8
},
0x2C => self.reg_inc(REG_L),
0x2D => self.reg_dec(REG_L),
0x2E => {
let args = self.load_args(1);
if self.debug {
println!("LD L, {:02x}", args[0]);
}
self.regs[REG_L] = args[0];
cycles = 8;
8
},
0x31 => {
let args = self.load_args(2);
@ -566,7 +533,7 @@ impl CPU {
if self.debug {
println!("LD SP, {:02x}", self.sp);
}
cycles = 12;
12
},
0x32 => {
if self.debug {
@ -577,7 +544,7 @@ impl CPU {
addr -= 1;
self.set_pair_value(REG_H, REG_L, addr);
cycles = 8;
8
},
0x36 => {
let args = self.load_args(1);
@ -586,99 +553,28 @@ impl CPU {
}
let addr = self.get_pair_value(REG_H, REG_L);
self.interconnect.write_byte(addr, args[0]);
cycles = 12;
12
},
0x3C => {
if self.debug {
println!("INC A");
}
self.reg_inc(REG_A);
cycles = 4;
}
0x3D => {
if self.debug {
println!("DEC A");
}
self.reg_dec(REG_A);
cycles = 4;
}
0x3C => self.reg_inc(REG_A),
0x3D => self.reg_dec(REG_A),
0x3E => {
let args = self.load_args(1);
if self.debug {
println!("LD A, {:02x}", args[0]);
}
self.regs[REG_A] = args[0];
cycles = 8;
8
},
// LDs
0x40 ... 0x47 => {
let reg_id = (instruction - 0x40) as usize;
if self.debug {
println!("LD B, {}", REG_NAMES[reg_id]);
}
self.regs[REG_B] = self.get_8bit_reg(reg_id);
cycles = 4;
},
0x48 ... 0x4F => {
let reg_id = (instruction - 0x48) as usize;
if self.debug {
println!("LD C, {}", REG_NAMES[reg_id]);
}
self.regs[REG_C] = self.get_8bit_reg(reg_id);
cycles = 4;
},
0x50 ... 0x57 => {
let reg_id = (instruction - 0x50) as usize;
if self.debug {
println!("LD D, {}", REG_NAMES[reg_id]);
}
self.regs[REG_D] = self.get_8bit_reg(reg_id);
cycles = 4;
},
0x58 ... 0x5F => {
let reg_id = (instruction - 0x58) as usize;
if self.debug {
println!("LD E, {}", REG_NAMES[reg_id]);
}
self.regs[REG_E] = self.get_8bit_reg(reg_id);
cycles = 4;
},
0x60 ... 0x67 => {
let reg_id = (instruction - 0x60) as usize;
if self.debug {
println!("LD H, {}", REG_NAMES[reg_id]);
}
self.regs[REG_H] = self.get_8bit_reg(reg_id);
cycles = 4;
},
0x68 ... 0x6F => {
let reg_id = (instruction - 0x68) as usize;
if self.debug {
println!("LD L, {}", REG_NAMES[reg_id]);
}
self.regs[REG_L] = self.get_8bit_reg(reg_id);
cycles = 4;
},
0x70 ... 0x75 | 0x77 => {
let reg_id = (instruction - 0x70) as usize;
if self.debug {
println!("LD (HL), {}", REG_NAMES[reg_id]);
}
let reg_value: u8 = self.get_8bit_reg(reg_id);
let addr: u16 = self.get_pair_value(REG_H, REG_L);
cycles = 8;
self.interconnect.write_byte(addr, reg_value);
},
0x78 ... 0x7F => {
let reg_id = (instruction - 0x78) as usize;
if self.debug {
println!("LD A, {}", REG_NAMES[reg_id]);
}
self.regs[REG_A] = self.get_8bit_reg(reg_id);
cycles = 4;
},
0x40 ... 0x47 => self.ld_r_r(REG_N_B, (instruction - 0x40) as usize),
0x48 ... 0x4F => self.ld_r_r(REG_N_C, (instruction - 0x48) as usize),
0x50 ... 0x57 => self.ld_r_r(REG_N_D, (instruction - 0x50) as usize),
0x58 ... 0x5F => self.ld_r_r(REG_N_E, (instruction - 0x58) as usize),
0x60 ... 0x67 => self.ld_r_r(REG_N_H, (instruction - 0x60) as usize),
0x68 ... 0x6F => self.ld_r_r(REG_N_L, (instruction - 0x68) as usize),
0x70 ... 0x75 | 0x77 => self.ld_r_r(REG_N_HL, (instruction - 0x70) as usize),
0x78 ... 0x7F => self.ld_r_r(REG_N_A, (instruction - 0x78) as usize),
// ADD
0x80 ... 0x87 => {
@ -689,7 +585,7 @@ impl CPU {
self.regs[REG_A] = self.regs[REG_A].wrapping_add(self.get_8bit_reg(reg_id));
self.clear_flag(FLAG_N);
cycles = 4;
4
}
// ADC
@ -702,7 +598,7 @@ impl CPU {
}
self.set_flag(FLAG_N);
cycles = 4;
4
}
// SUBs
@ -719,7 +615,7 @@ impl CPU {
self.clear_flag(FLAG_Z);
}
// TODO: H, C
cycles = 4;
4
}
// SBC
@ -738,7 +634,7 @@ impl CPU {
} else {
self.clear_flag(FLAG_Z);
}
cycles = 4;
4
}
// XOR
@ -757,7 +653,7 @@ impl CPU {
self.clear_flag(FLAG_C);
self.clear_flag(FLAG_N);
self.clear_flag(FLAG_H);
cycles = 4;
4
},
// CP
@ -779,7 +675,7 @@ impl CPU {
self.clear_flag(FLAG_C);
self.clear_flag(FLAG_Z);
}
cycles = 4;
4
},
0xC1 => {
if self.debug {
@ -788,7 +684,7 @@ impl CPU {
let val: u16 = self.interconnect.read_word(self.sp);
self.sp += 2;
self.set_pair_value(REG_B, REG_C, val);
cycles = 12;
12
},
0xC2 => {
let addr: u16 = to_u16(self.load_args(2));
@ -797,9 +693,9 @@ impl CPU {
}
if self.flags & FLAG_Z == 0 {
self.ip = addr;
cycles = 16;
16
} else {
cycles = 12;
12
}
},
0xC3 => {
@ -808,7 +704,7 @@ impl CPU {
println!("JP {:04X}", addr);
}
self.ip = addr;
cycles = 16;
16
}
0xC4 => {
let target = to_u16(self.load_args(2));
@ -817,36 +713,28 @@ impl CPU {
}
if self.flags & FLAG_Z == 0 {
// Push current IP to the stack
self.interconnect.write_word(self.sp - 1, self.ip);
self.sp -= 2;
let ip = self.ip;
self.push(ip);
self.ip = target;
cycles = 24;
24
} else {
cycles = 12;
12
}
},
0xC5 => {
if self.debug {
println!("PUSH BC");
}
let val: u16 = self.get_pair_value(REG_B, REG_C);
self.interconnect.write_word(self.sp - 2, val);
self.sp -= 2;
cycles = 16;
},
0xC5 => self.push_rr(REG_B, REG_C),
0xC9 => {
if self.debug {
println!("RET");
}
self.dump_stack();
}
self.ip = self.interconnect.read_word(self.sp+1);
self.sp += 2;
cycles = 16;
16
},
0xCB => {
// Prefix CB. This is annoying.
self.run_prefix_instruction();
cycles = 12; // TODO: Verify that this is the case for all prefix instructions.
12 // TODO: Verify that this is the case for all prefix instructions.
},
0xCC => {
let target = to_u16(self.load_args(2));
@ -858,9 +746,9 @@ impl CPU {
self.interconnect.write_word(self.sp - 1, self.ip);
self.sp -= 2;
self.ip = target;
cycles = 24;
24
} else {
cycles = 12;
12
}
},
0xCD => {
@ -872,7 +760,7 @@ impl CPU {
self.interconnect.write_word(self.sp - 1, self.ip);
self.sp -= 2;
self.ip = target;
cycles = 24;
24
},
0xE0 => {
let args = self.load_args(1);
@ -880,7 +768,7 @@ impl CPU {
println!("LDH {:02X}, A", args[0]);
}
self.interconnect.write_byte(0xFF00 + args[0] as u16, self.regs[REG_A]);
cycles = 12;
12
},
0xE2 => {
if self.debug {
@ -888,7 +776,7 @@ impl CPU {
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]);
cycles = 8;
8
},
0xEA => {
let addr = to_u16(self.load_args(2));
@ -896,7 +784,7 @@ impl CPU {
println!("LD ({:04X}), A", addr);
}
self.interconnect.write_byte(addr, self.regs[REG_A]);
cycles = 16;
16
}
0xF0 => {
let args = self.load_args(1);
@ -904,21 +792,21 @@ impl CPU {
println!("LDH A, {:02X}", args[0]);
}
self.regs[REG_A] = self.interconnect.read_byte(0xFF00 + args[0] as u16);
cycles = 12;
12
},
0xF2 => {
if self.debug{
println!("LD A, (C)");
}
self.regs[REG_A] = self.interconnect.read_byte(0xFF00 + self.regs[REG_C] as u16);
cycles = 8;
8
},
0xF3 => {
if self.debug {
println!("DI");
}
self.interrupts_enabled = false;
cycles = 4;
4
}
0xFB => {
// Enable interrupts - TODO
@ -926,8 +814,8 @@ impl CPU {
println!("EI");
}
self.interrupts_enabled = true;
cycles = 4;
panic!("ENABLING INTERRUPTS - TODO");
4
},
0xFE => {
let args = self.load_args(1);
@ -947,10 +835,10 @@ impl CPU {
}
// TODO H
cycles = 8;
8
}
_ => panic!("Unknown instruction: {:02x}", instruction)
}
};
// self.dump_stack();
self.interconnect.tick(cycles);
}

View File

@ -70,7 +70,7 @@ impl Display {
let sdl_ctx = sdl2::init().unwrap();
let video_ctx = sdl_ctx.video().unwrap();
let wnd = video_ctx.window("RustBoy", (GB_PIXELS_X * SCALE) as u32, (GB_PIXELS_Y * SCALE) as u32).position_centered().build().expect("Failed to create window :<");
let mut renderer = wnd.renderer().build().expect("Could not build renderer");
let renderer = wnd.renderer().build().expect("Could not build renderer");
Display {
control: 0,
@ -199,7 +199,25 @@ impl Display {
// Render background
if self.control & CTRL_BG_DISPLAY > 0 {
print!("Drawing tiles: ");
// Draw borders first.
for t_x in 0 .. 160/8 {
self.renderer.set_draw_color(sdl2::pixels::Color::RGB(0xFF, 10, 0xFF));
// Awesome effects:
/*
let RX: i32 = (t_x as i32)*8 + map_offset_x as i32;
let RY: i32 = (render_y as i32) & 0xFFFFFFF8 + map_offset_y as i32;
let TS: u32 = 8u32 * (SCALE as u32);
*/
let RX: i32 = (t_x as i32)*8 + map_offset_x as i32;
let RY: i32 = ((render_y as u32) & 0xFFFFFFF8) as i32 - map_offset_y as i32;
let TS: u32 = 8u32 * (SCALE as u32);
self.renderer.draw_rect(
sdl2::rect::Rect::new(RX * SCALE as i32, RY * SCALE as i32, TS, TS)
);
}
// Render pixels (20 tiles)
for render_x in 0 .. 160 {
// Absolute render coordinates
@ -219,7 +237,7 @@ impl Display {
// println!("vram offset: {:04X}", vram_offset);
if tile_id != 0 {
// println!("Drawing tile {:02X}", tile_id);
print!("{:02X} ", tile_id);
// print!("{:02X} ", tile_id);
}
// Obtain tile information
@ -230,7 +248,7 @@ impl Display {
tile_base_addr = 0x0800;
// This set goes from -127 to 127.
let s_tid: i8 = tile_id as i8;
tile_id = (128 + s_tid) as u8;
tile_id = (128u8 as i8 + s_tid) as u8;
panic!("OH MY GOD, this wasn't tested yet");
}
@ -252,9 +270,9 @@ impl Display {
// Draw stuff. We're currently only in monochrome mode
self.set_pixel(render_x, render_y, sdl2::pixels::Color::RGB(factor, factor, factor));
}
}
println!("");
}
pub fn vblank_interrupt(&mut self) {

View File

@ -44,8 +44,8 @@ impl Interconnect {
}
// Somehow we need different timers for this.
pub fn tick(&mut self, cycles: u16) {
self.display.tick(cycles * 4);
pub fn tick(&mut self, cycles: u8) {
self.display.tick(cycles as u16 * 4);
}
pub fn display_blank_interrupt(&mut self) {
@ -138,6 +138,7 @@ impl Interconnect {
self.display.write_byte(addr, val);
},
0xFF50 => {
println!("Disabling boot rom.");
self.disable_bootrom = val;
},
0xFF56 => {