-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented
STAT LYC == LY
interrupt
- Loading branch information
Showing
3 changed files
with
59 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,62 @@ | ||
use crate::{common::Bit, GameBoy}; | ||
|
||
struct Interrupts { | ||
vblank: bool, | ||
lcd: bool, | ||
timer: bool, | ||
serial: bool, | ||
joypad: bool, | ||
use crate::{ | ||
common::Bit, | ||
consts::gpu::{IE, IF, LY, LYC, STAT}, | ||
GameBoy, | ||
}; | ||
|
||
#[derive(Debug, PartialEq)] | ||
pub enum Interrupt { | ||
/// https://gbdev.io/pandocs/STAT.html?highlight=ff41#ff41--stat-lcd-status | ||
/// This will get triggered if: | ||
/// - STAT.3: Just entered PPU mode 0 (TODO) | ||
/// - STAT.4: Just entered PPU mode 1 (TODO) | ||
/// - STAT.5: Just entered PPU mode 2 (TODO) | ||
/// - STAT.6: LYC == LY | ||
Stat, | ||
} | ||
|
||
impl From<u8> for Interrupts { | ||
fn from(value: u8) -> Self { | ||
Self { | ||
vblank: value.get_bit(0), | ||
lcd: value.get_bit(1), | ||
timer: value.get_bit(2), | ||
serial: value.get_bit(3), | ||
joypad: value.get_bit(4), | ||
impl GameBoy { | ||
pub(crate) fn execute_interrupts(&mut self) { | ||
if !self.flags.ime { | ||
return; | ||
} | ||
} | ||
} | ||
|
||
impl From<Interrupts> for u8 { | ||
fn from(value: Interrupts) -> Self { | ||
let mut result: u8 = 0; | ||
let stat = self.bus[STAT]; | ||
if stat.get_bit(6) && self.bus[LYC] == self.bus[LY] { | ||
self.execute_interrupt(Interrupt::Stat); | ||
} | ||
} | ||
|
||
result.set_bit(0, value.vblank); | ||
result.set_bit(1, value.lcd); | ||
result.set_bit(2, value.timer); | ||
result.set_bit(3, value.serial); | ||
result.set_bit(4, value.joypad); | ||
fn execute_interrupt(&mut self, interrupt: Interrupt) { | ||
// We don't want to call the same interrupt twice | ||
if let Some(previous_interrupt) = &self.previous_interrupt { | ||
if *previous_interrupt == interrupt { | ||
return; | ||
} | ||
} | ||
|
||
result | ||
} | ||
} | ||
// The bit corresponding to the correct interrupt, both in Interrupt Enable, and | ||
// Interrupt Flag bytes | ||
let if_bit: u8 = match interrupt { | ||
Interrupt::Stat => 1, | ||
}; | ||
|
||
impl GameBoy { | ||
pub(crate) fn execute_interrupts(&mut self) { | ||
if !self.flags.ime { | ||
// We can only execute an interrupt if it's turned on in the Interrupt Enable and | ||
// Interrupt Flag bytes | ||
if self.bus[IE].get_bit(if_bit) && self.bus[IF].get_bit(if_bit) { | ||
return; | ||
} | ||
|
||
let is_enabled: Interrupts = self.bus[0xFFFF].into(); | ||
let mut value: Interrupts = self.bus[0xFF0F].into(); | ||
let return_address: u16 = match interrupt { | ||
Interrupt::Stat => 0x48, | ||
}; | ||
|
||
// TODO: Make code DRYer | ||
if is_enabled.vblank && value.vblank { | ||
self.call(0x40); | ||
self.call(return_address); | ||
|
||
value.vblank = false; | ||
self.bus[0xFF0F] = value.into(); | ||
} | ||
let mut input_flags = self.bus[IF]; | ||
input_flags.set_bit(if_bit, false); | ||
self.bus[IF] = input_flags; | ||
|
||
self.previous_interrupt = Some(interrupt); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters