cpu gets interrupts from struct rather than accessing memory directly
This commit is contained in:
parent
710912d150
commit
b95ab33ec9
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue