diff --git a/src/cpu.rs b/src/cpu.rs index fe3607f..e3384e6 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -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.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); } diff --git a/src/display.rs b/src/display.rs index e315b74..f77f7a5 100644 --- a/src/display.rs +++ b/src/display.rs @@ -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) { diff --git a/src/interconnect.rs b/src/interconnect.rs index 992bf0c..50b9b9f 100644 --- a/src/interconnect.rs +++ b/src/interconnect.rs @@ -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 => {