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

feat: better interrupt handling

parent 40a3f4c8
No related branches found
No related tags found
No related merge requests found
Pipeline #916 passed
...@@ -84,21 +84,21 @@ fn main() { ...@@ -84,21 +84,21 @@ 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.load_rom_file("../../res/roms.prop/tetris.gb"); //game_boy.load_rom_file("../../res/roms.prop/tetris.gb");
//game_boy.load_rom_file("../../res/roms.prop/alleyway.gb"); //game_boy.load_rom_file("../../res/roms.prop/alleyway.gb");
//game_boy.load_rom_file("../../res/roms/firstwhite.gb"); //game_boy.load_rom_file("../../res/roms/firstwhite.gb");
//game_boy.load_rom_file("../../res/roms/opus5.gb"); //game_boy.load_rom_file("../../res/roms/opus5.gb");
//game_boy.load_rom_file("../../res/roms/paradius/cpu/01-special.gb"); // PASSED //game_boy.load_rom_file("../../res/roms/paradius/cpu/01-special.gb"); // PASSED
//game_boy.load_rom_file("../../res/roms/paradius/cpu/02-interrupts.gb"); // NO FINISH //game_boy.load_rom_file("../../res/roms/paradius/cpu/02-interrupts.gb"); // FAILED #2
//game_boy.load_rom_file("../../res/roms/paradius/cpu/03-op sp,hl.gb"); // PASSED //game_boy.load_rom_file("../../res/roms/paradius/cpu/03-op sp,hl.gb"); // PASSED
//game_boy.load_rom_file("../../res/roms/paradius/cpu/04-op r,imm.gb"); // PASSED //game_boy.load_rom_file("../../res/roms/paradius/cpu/04-op r,imm.gb"); // PASSED
//game_boy.load_rom_file("../../res/roms/paradius/cpu/05-op rp.gb"); // PASSED //game_boy.load_rom_file("../../res/roms/paradius/cpu/05-op rp.gb"); // PASSED
//game_boy.load_rom_file("../../res/roms/paradius/cpu/06-ld r,r.gb"); // PASSED //game_boy.load_rom_file("../../res/roms/paradius/cpu/06-ld r,r.gb"); // PASSED
//game_boy.load_rom_file("../../res/roms/paradius/cpu/07-jr,jp,call,ret,rst.gb"); // PASSED //game_boy.load_rom_file("../../res/roms/paradius/cpu/07-jr,jp,call,ret,rst.gb"); // PASSED
//game_boy.load_rom_file("../../res/roms/paradius/cpu/08-misc instrs.gb"); // PASSED //game_boy.load_rom_file("../../res/roms/paradius/cpu/08-misc instrs.gb"); // PASSED
//game_boy.load_rom_file("../../res/roms/paradius/cpu/09-op r,r.gb"); // NO FINISH game_boy.load_rom_file("../../res/roms/paradius/cpu/09-op r,r.gb"); // NO FINISH
//game_boy.load_rom_file("../../res/roms/paradius/cpu/11-op a,(hl).gb"); // NO FINISH //game_boy.load_rom_file("../../res/roms/paradius/cpu/11-op a,(hl).gb"); // NO FINISH
let mut counter = 0u32; let mut counter = 0u32;
......
...@@ -98,10 +98,6 @@ impl Cpu { ...@@ -98,10 +98,6 @@ impl Cpu {
} }
pub fn clock(&mut self) -> u8 { pub fn clock(&mut self) -> u8 {
if self.halted {
return 4;
}
// gathers the PC (program counter) reference that // gathers the PC (program counter) reference that
// is going to be used in the fetching phase // is going to be used in the fetching phase
let pc = self.pc; let pc = self.pc;
...@@ -115,11 +111,14 @@ impl Cpu { ...@@ -115,11 +111,14 @@ impl Cpu {
if self.ime { if self.ime {
// @todo aggregate all of this interrupts in the MMU // @todo aggregate all of this interrupts in the MMU
if (self.mmu.ie & 0x01 == 0x01) && self.mmu.ppu().int_vblank() { if (self.mmu.ie & 0x01 == 0x01) && self.mmu.ppu().int_vblank() {
println!("Going to run V-Blank interrupt handler"); println!("Going to run V-Blank interrupt handler (0x40)");
let pc = self.pc;
self.disable_int(); self.disable_int();
self.push_word(pc); self.push_word(pc);
self.pc = 0x40; self.pc = 0x40;
// acknowledges that the V-Blank interrupt has been
// properly handled
self.mmu.ppu().ack_vblank(); self.mmu.ppu().ack_vblank();
// in case the CPU is currently halted waiting // in case the CPU is currently halted waiting
...@@ -132,6 +131,13 @@ impl Cpu { ...@@ -132,6 +131,13 @@ impl Cpu {
} }
} }
// in case the CPU is currently in the halted state
// returns the control flow immediately with the associated
// number of cycles estimated for the halted execution
if self.halted {
return 4;
}
// fetches the current instruction and increments // fetches the current instruction and increments
// the PC (program counter) accordingly // the PC (program counter) accordingly
let mut opcode = self.mmu.read(self.pc); let mut opcode = self.mmu.read(self.pc);
...@@ -151,6 +157,9 @@ impl Cpu { ...@@ -151,6 +157,9 @@ impl Cpu {
let (instruction_fn, instruction_time, instruction_str) = instruction; let (instruction_fn, instruction_time, instruction_str) = instruction;
if *instruction_str == "! UNIMP !" || *instruction_str == "HALT" { if *instruction_str == "! UNIMP !" || *instruction_str == "HALT" {
if *instruction_str == "HALT" {
println!("Waiting for {:x} in HALT", self.mmu.ie);
}
println!( println!(
"{}\t(0x{:02x})\t${:04x} {}", "{}\t(0x{:02x})\t${:04x} {}",
instruction_str, opcode, pc, is_prefix instruction_str, opcode, pc, is_prefix
......
...@@ -322,14 +322,14 @@ pub const EXTENDED: [(fn(&mut Cpu), u8, &'static str); 256] = [ ...@@ -322,14 +322,14 @@ pub const EXTENDED: [(fn(&mut Cpu), u8, &'static str); 256] = [
(sla_l, 8, "SLA L"), (sla_l, 8, "SLA L"),
(sla_mhl, 16, "SLA [HL]"), (sla_mhl, 16, "SLA [HL]"),
(sla_a, 8, "SLA A"), (sla_a, 8, "SLA A"),
(noimpl, 4, "! UNIMP !"), (sra_b, 8, "SRA B"),
(noimpl, 4, "! UNIMP !"), (sra_c, 8, "SRA C"),
(noimpl, 4, "! UNIMP !"), (sra_d, 8, "SRA D"),
(noimpl, 4, "! UNIMP !"), (sra_e, 8, "SRA E"),
(noimpl, 4, "! UNIMP !"), (sra_h, 8, "SRA H"),
(noimpl, 4, "! UNIMP !"), (sra_l, 8, "SRA L"),
(noimpl, 4, "! UNIMP !"), (sra_mhl, 16, "SRA [HL]"),
(noimpl, 4, "! UNIMP !"), (sra_a, 8, "SRA A"),
// 0x3 opcodes // 0x3 opcodes
(noimpl, 4, "! UNIMP !"), (noimpl, 4, "! UNIMP !"),
(noimpl, 4, "! UNIMP !"), (noimpl, 4, "! UNIMP !"),
...@@ -2218,6 +2218,41 @@ fn sla_a(cpu: &mut Cpu) { ...@@ -2218,6 +2218,41 @@ fn sla_a(cpu: &mut Cpu) {
cpu.a = sla(cpu, cpu.a); cpu.a = sla(cpu, cpu.a);
} }
fn sra_b(cpu: &mut Cpu) {
cpu.b = sra(cpu, cpu.b);
}
fn sra_c(cpu: &mut Cpu) {
cpu.c = sra(cpu, cpu.c);
}
fn sra_d(cpu: &mut Cpu) {
cpu.d = sra(cpu, cpu.d);
}
fn sra_e(cpu: &mut Cpu) {
cpu.e = sra(cpu, cpu.e);
}
fn sra_h(cpu: &mut Cpu) {
cpu.h = sra(cpu, cpu.h);
}
fn sra_l(cpu: &mut Cpu) {
cpu.l = sra(cpu, cpu.l);
}
fn sra_mhl(cpu: &mut Cpu) {
let hl = cpu.hl();
let byte = cpu.mmu.read(hl);
let result = sra(cpu, byte);
cpu.mmu.write(hl, result);
}
fn sra_a(cpu: &mut Cpu) {
cpu.a = sra(cpu, cpu.a);
}
fn swap_a(cpu: &mut Cpu) { fn swap_a(cpu: &mut Cpu) {
cpu.a = swap(cpu, cpu.a) cpu.a = swap(cpu, cpu.a)
} }
...@@ -2777,7 +2812,18 @@ fn sla(cpu: &mut Cpu, value: u8) -> u8 { ...@@ -2777,7 +2812,18 @@ fn sla(cpu: &mut Cpu, value: u8) -> u8 {
cpu.set_sub(false); cpu.set_sub(false);
cpu.set_zero(result == 0); cpu.set_zero(result == 0);
cpu.set_half_carry(false); cpu.set_half_carry(false);
cpu.set_carry(value & 0x80 != 0); cpu.set_carry(value & 0x80 == 0x80);
result
}
fn sra(cpu: &mut Cpu, value: u8) -> u8 {
let result = (value >> 1) | (value & 0x80);
cpu.set_sub(false);
cpu.set_zero(result == 0);
cpu.set_half_carry(false);
cpu.set_carry(value & 0x01 == 0x01);
result result
} }
......
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