Skip to content

Commit

Permalink
Fixed STAT interrupt not triggering
Browse files Browse the repository at this point in the history
  • Loading branch information
velllu committed Sep 29, 2024
1 parent d97ee4c commit 37b3f6c
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 26 deletions.
54 changes: 31 additions & 23 deletions src/gpu/blanks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
common::Bit,
consts::{
cpu::IF,
gpu::{LY, LYC, STAT},
gpu::{LYC, STAT},
},
GameBoy,
};
Expand All @@ -11,24 +11,32 @@ use super::GpuState;

impl GameBoy {
pub(super) fn hblank(&mut self) {
if self.gpu.ticks == 0 {
self.gpu.x = 0;
self.gpu.y += 1;
self.gpu.fifo.clear();

self.layers
.iter_mut()
.for_each(|layer| layer.at_hblank(&self.bus, &self.gpu));
}

// Setting interrupts
if self.gpu.ticks == 0 {
let interrupt_flag = self.bus.read(IF);
let mut interrupt_flag = self.bus.read(IF);
let stat = self.bus.read(STAT);

// Stat interrupt. Stat.3 indicates HBlank
if stat.get_bit(3) {
self.bus.write(IF, interrupt_flag | 0b00000010);
interrupt_flag |= 0b00000010;
}
}

if self.gpu.ticks == 0 {
self.gpu.x = 0;
self.gpu.fifo.clear();
// Stat interrupt. We need to check for LYC == LY
if stat.get_bit(6) && self.gpu.y == self.bus.read(LYC) {
interrupt_flag |= 0b00000010;
}

self.layers
.iter_mut()
.for_each(|layer| layer.at_hblank(&self.bus, &self.gpu));
self.bus.write(IF, interrupt_flag);
}

self.switch_when_ticks(
Expand All @@ -47,6 +55,17 @@ impl GameBoy {
/// Amount of ticks needed to render a vblank line
const VBLANK_LINE_TICKS: u16 = 456;

if self.gpu.ticks == 0 {
self.layers
.iter_mut()
.for_each(|layer| layer.at_vblank(&self.bus, &self.gpu));
}

// After every line
if self.gpu.ticks % VBLANK_LINE_TICKS == 0 {
self.gpu.y += 1;
}

// Setting interrupts
if self.gpu.ticks == 0 {
let mut interrupt_flag = self.bus.read(IF);
Expand All @@ -60,25 +79,14 @@ impl GameBoy {
interrupt_flag |= 0b00000010;
}

// Stat interrupt. We also need to check for LYC == LY
if stat.get_bit(6) && self.bus.read(LY) == self.bus.read(LYC) {
// Stat interrupt. We need to check for LYC == LY
if stat.get_bit(6) && self.gpu.y == self.bus.read(LYC) {
interrupt_flag |= 0b00000010;
}

self.bus.write(IF, interrupt_flag);
}

if self.gpu.ticks == 0 {
self.layers
.iter_mut()
.for_each(|layer| layer.at_vblank(&self.bus, &self.gpu));
}

// After every line
if self.gpu.ticks % VBLANK_LINE_TICKS == 0 {
self.gpu.y += 1;
}

// There are 10 lines of vblank
self.switch_when_ticks(VBLANK_LINE_TICKS * 10, GpuState::OamSearch);
}
Expand Down
3 changes: 0 additions & 3 deletions src/gpu/pixel_transfer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@ impl GameBoy {
self.gpu.state = GpuState::HBlank;
self.gpu.ticks = 0;
self.gpu.number_of_slices_pushed = 0;
self.gpu.x = 0;
self.gpu.y += 1;

return;
}
Expand All @@ -102,7 +100,6 @@ impl GameBoy {
.for_each(|layer| layer.get_tile_step_1(&self.gpu, &self.bus)),

false => {
// TODO: Figure out why this is needed, it's driving me crazy
// This is where the X pointer would be if we always pushed 8 pixels at a
// time (which happens when SCX is not a multiple of 8)
self.gpu.virtual_x = (self.gpu.number_of_slices_pushed - 1) * 8;
Expand Down

0 comments on commit 37b3f6c

Please sign in to comment.