Skip to content
Snippets Groups Projects
Verified Commit 6193dfa7 authored by João Magalhães's avatar João Magalhães :rocket:
Browse files

feat: more clock operations support

parent fd93c068
No related branches found
No related tags found
No related merge requests found
...@@ -4,9 +4,7 @@ fn main() { ...@@ -4,9 +4,7 @@ fn main() {
let mut game_boy = GameBoy::new(); let mut game_boy = GameBoy::new();
game_boy.load_boot_default(); game_boy.load_boot_default();
game_boy.clock(); for _ in 0..40000 {
game_boy.clock(); game_boy.clock();
game_boy.clock(); }
game_boy.clock();
game_boy.clock();
} }
use crate::mmu::Mmu; use crate::mmu::Mmu;
pub const PREFIX: u8 = 0xcb;
pub const INSTRUCTIONS: [(fn(&mut Cpu), u8, &'static str); 208] = [ pub const INSTRUCTIONS: [(fn(&mut Cpu), u8, &'static str); 208] = [
// 0x0 opcodes // 0x0 opcodes
(nop, 4, "NOP"), (nop, 4, "NOP"),
...@@ -36,7 +38,7 @@ pub const INSTRUCTIONS: [(fn(&mut Cpu), u8, &'static str); 208] = [ ...@@ -36,7 +38,7 @@ pub const INSTRUCTIONS: [(fn(&mut Cpu), u8, &'static str); 208] = [
(nop, 4, "NOP"), (nop, 4, "NOP"),
(nop, 4, "NOP"), (nop, 4, "NOP"),
// 0x2 opcodes // 0x2 opcodes
(nop, 4, "NOP"), (jr_nz_i8, 8, "JR NZ, i8"),
(ld_hl_u16, 12, "LD HL, u16"), (ld_hl_u16, 12, "LD HL, u16"),
(nop, 4, "NOP"), (nop, 4, "NOP"),
(nop, 4, "NOP"), (nop, 4, "NOP"),
...@@ -224,6 +226,196 @@ pub const INSTRUCTIONS: [(fn(&mut Cpu), u8, &'static str); 208] = [ ...@@ -224,6 +226,196 @@ pub const INSTRUCTIONS: [(fn(&mut Cpu), u8, &'static str); 208] = [
(nop, 4, "NOP"), (nop, 4, "NOP"),
]; ];
pub const BITWISE: [(fn(&mut Cpu), u8, &'static str); 176] = [
// 0x0 opcodes
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
// 0x1 opcodes
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
// 0x2 opcodes
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
// 0x3 opcodes
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
// 0x4 opcodes
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
// 0x5 opcodes
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
// 0x6 opcodes
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
// 0x7 opcodes
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(bit_7_h, 8, "BIT 7, H"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
// 0x8 opcodes
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
// 0x9 opcodes
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
// 0xa opcodes
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
(nop, 4, "NOP"),
];
pub struct Cpu { pub struct Cpu {
pc: u16, pc: u16,
sp: u16, sp: u16,
...@@ -264,18 +456,29 @@ impl Cpu { ...@@ -264,18 +456,29 @@ impl Cpu {
} }
pub fn clock(&mut self) { pub fn clock(&mut self) {
let pc = self.pc;
// fetches the current instruction and increments // fetches the current instruction and increments
// the PC (program counter) accordingly // the PC (program counter) accordingly
let opcode = self.mmu.read(self.pc); let mut opcode = self.mmu.read(self.pc);
self.pc += 1; self.pc = self.pc.wrapping_add(1);
let instruction: &(fn(&mut Cpu), u8, &str);
if opcode == PREFIX {
opcode = self.mmu.read(self.pc);
self.pc = self.pc.wrapping_add(1);
instruction = &BITWISE[opcode as usize];
} else {
instruction = &INSTRUCTIONS[opcode as usize];
}
let instruction = INSTRUCTIONS[opcode as usize];
let (instruction_fn, instruction_size, instruction_str) = instruction; let (instruction_fn, instruction_size, instruction_str) = instruction;
println!("{} ({:#x})", instruction_str, opcode); println!("{}\t({:#x})\t${:04x}", instruction_str, opcode, pc);
instruction_fn(self); instruction_fn(self);
self.clocks = self.clocks.wrapping_add(instruction_size as u32); self.clocks = self.clocks.wrapping_add(*instruction_size as u32);
} }
#[inline(always)] #[inline(always)]
...@@ -457,6 +660,17 @@ fn add_hl_bc(cpu: &mut Cpu) { ...@@ -457,6 +660,17 @@ fn add_hl_bc(cpu: &mut Cpu) {
cpu.set_hl(value); cpu.set_hl(value);
} }
fn jr_nz_i8(cpu: &mut Cpu) {
let byte = cpu.read_u8() as i8;
if cpu.get_zero() {
return;
}
cpu.pc = (cpu.pc as i16).wrapping_add(byte as i16) as u16;
cpu.clocks += 4;
}
fn ld_hl_u16(cpu: &mut Cpu) { fn ld_hl_u16(cpu: &mut Cpu) {
let word = cpu.read_u16(); let word = cpu.read_u16();
cpu.set_hl(word); cpu.set_hl(word);
...@@ -480,6 +694,23 @@ fn xor_a_a(cpu: &mut Cpu) { ...@@ -480,6 +694,23 @@ fn xor_a_a(cpu: &mut Cpu) {
cpu.set_carry(false); cpu.set_carry(false);
} }
fn bit_7_h(cpu: &mut Cpu) {
bit_h(cpu, 7);
}
/// Helper function to test one bit in a u8.
/// Returns true if bit is 0.
fn bit_zero(val: u8, bit: u8) -> bool {
(val & (1u8 << (bit as usize))) == 0
}
fn bit_h(cpu: &mut Cpu, bit: u8) {
println!("{}", cpu.h);
cpu.set_sub(false);
cpu.set_zero(bit_zero(cpu.h, bit));
cpu.set_half_carry(true);
}
fn add_u16_u16(cpu: &mut Cpu, first: u16, second: u16) -> u16 { fn add_u16_u16(cpu: &mut Cpu, first: u16, second: u16) -> u16 {
let first = first as u32; let first = first as u32;
let second = second as u32; let second = second as u32;
......
...@@ -47,7 +47,7 @@ impl Mmu { ...@@ -47,7 +47,7 @@ impl Mmu {
println!("WRITING TO RAM"); println!("WRITING TO RAM");
self.ram[(addr & 0x1fff) as usize] = value; self.ram[(addr & 0x1fff) as usize] = value;
} }
_ => panic!("asdad"), addr => panic!("Writing in unknown location 0x{:04x}", addr),
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment