cpu gets interrupts from struct rather than accessing memory directly

This commit is contained in:
Alex Janka 2023-02-24 10:50:59 +11:00
parent 710912d150
commit b95ab33ec9
3 changed files with 36 additions and 44 deletions

View file

@ -1,14 +1,11 @@
use self::mmio::{Apu, Gpu, Joypad, Serial, Timer};
pub use self::rom::Rom;
use self::{
interrupts::Interrupt,
mmio::{Apu, Gpu, Joypad, Serial, Timer},
};
use crate::{processor::SplitRegister, verbose_println, Cpu};
use gilrs::Gilrs;
use minifb::{Key, Window};
mod interrupts;
pub use interrupts::Interrupts;
pub use interrupts::{Interrupt, Interrupts};
pub mod mmio;
pub(crate) mod rom;
@ -21,7 +18,7 @@ pub struct Memory {
ram: [u8; 8192],
switchable_ram: [u8; 8192],
cpu_ram: [u8; 128],
interrupts: Interrupts,
pub(super) interrupts: Interrupts,
pub(super) ime: bool,
pub(super) ime_scheduled: u8,
dma_addr: u8,

View file

@ -74,4 +74,25 @@ impl Interrupts {
Interrupt::Joypad => self.flag_register.joypad = status,
}
}
pub fn get_next_interrupt(&mut self) -> Option<Interrupt> {
if self.enable_register.vblank && self.flag_register.vblank {
self.flag_register.vblank = false;
Some(Interrupt::Vblank)
} else if self.enable_register.lcd_stat && self.flag_register.lcd_stat {
self.flag_register.lcd_stat = false;
Some(Interrupt::LcdStat)
} else if self.enable_register.timer && self.flag_register.timer {
self.flag_register.timer = false;
Some(Interrupt::Timer)
} else if self.enable_register.serial && self.flag_register.serial {
self.flag_register.serial = false;
Some(Interrupt::Serial)
} else if self.enable_register.joypad && self.flag_register.joypad {
self.flag_register.joypad = false;
Some(Interrupt::Joypad)
} else {
None
}
}
}

View file

@ -1,11 +1,7 @@
use std::time::Instant;
use self::memory::Memory;
use crate::{
util::{clear_bit, get_bit},
verbose_println,
};
use self::memory::{Interrupt, Memory};
use crate::verbose_println;
use gilrs::Gilrs;
use std::time::Instant;
mod instructions;
pub mod memory;
@ -88,37 +84,15 @@ impl Cpu {
fn handle_interrupts(&mut self) -> u8 {
if self.memory.ime || self.halted {
let req_and_enabled = self.memory.get(0xFF0F) & self.memory.get(0xFFFF);
// all interrupts should last 5 cycles?
if get_bit(req_and_enabled, 0) {
// vblank
self.service_interrupt(0x40);
self.memory
.set(0xFF0F, clear_bit(self.memory.get(0xFF0F), 0));
5
} else if get_bit(req_and_enabled, 1) {
// lcd stat
self.service_interrupt(0x48);
self.memory
.set(0xFF0F, clear_bit(self.memory.get(0xFF0F), 1));
5
} else if get_bit(req_and_enabled, 2) {
// timer
self.service_interrupt(0x50);
self.memory
.set(0xFF0F, clear_bit(self.memory.get(0xFF0F), 2));
5
} else if get_bit(req_and_enabled, 3) {
// serial
self.service_interrupt(0x58);
self.memory
.set(0xFF0F, clear_bit(self.memory.get(0xFF0F), 3));
5
} else if get_bit(req_and_enabled, 4) {
// joypad
self.service_interrupt(0x60);
self.memory
.set(0xFF0F, clear_bit(self.memory.get(0xFF0F), 4));
if let Some(interrupt) = self.memory.interrupts.get_next_interrupt() {
let interrupt_addr = match interrupt {
Interrupt::Vblank => 0x40,
Interrupt::LcdStat => 0x48,
Interrupt::Timer => 0x50,
Interrupt::Serial => 0x58,
Interrupt::Joypad => 0x60,
};
self.service_interrupt(interrupt_addr);
5
} else {
0