Skip to content

Commit

Permalink
Implemented window internal line counter
Browse files Browse the repository at this point in the history
  • Loading branch information
velllu committed Jul 26, 2024
1 parent 91bf37e commit d98ae94
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 2 deletions.
10 changes: 10 additions & 0 deletions src/gpu/blanks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ impl GameBoy {
if self.gpu.ticks == 0 {
self.gpu.x = 0;
self.gpu.fifo.clear();

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

self.switch_when_ticks(
Expand All @@ -25,6 +29,12 @@ 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;
Expand Down
5 changes: 5 additions & 0 deletions src/gpu/pixel_transfer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,18 @@ use crate::{bus::Bus, common::Bit, consts::display::DISPLAY_SIZE_X, GameBoy};
/// The GameBoy's GPU works by having three "layers", the background layer, the window
/// layer and the sprite layer, this trait defines the parts that differ for every layer,
/// the common parts are defined in this file.
#[allow(unused_variables)]
pub(crate) trait Layer: Send {
fn is_layer_enabled(&self, bus: &Bus) -> bool;
fn mix_with_layer_below(&self) -> Priority;
fn get_tile_step_1(&mut self, gpu: &Gpu, bus: &Bus);
fn get_tile_step_2(&mut self, gpu: &Gpu, bus: &Bus);
fn get_tile_data(&mut self, is_high_part: bool, gpu: &Gpu, bus: &Bus);
fn push_pixels(&mut self, gpu: &Gpu, bus: &Bus) -> Vec<PixelData>;

// Events
fn at_hblank(&mut self, bus: &Bus, gpu: &Gpu) {}
fn at_vblank(&mut self, bus: &Bus, gpu: &Gpu) {}
}

#[derive(PartialEq, Debug)]
Expand Down
36 changes: 34 additions & 2 deletions src/gpu/pixel_transfer/window.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use crate::{
bus::Bus,
common::Bit,
consts::gpu::{LCDC, WX, WY},
consts::{
display::{DISPLAY_SIZE_X, DISPLAY_SIZE_Y},
gpu::{LCDC, WX, WY},
},
gpu::{Color, Gpu, PixelData, Priority},
};

Expand All @@ -12,6 +15,11 @@ pub(crate) struct WindowLayer {
tile_id: u8,
tile_data_low: u8,
tile_data_high: u8,

/// The window has an internal line counter, when the window is turned off and then
/// turned on later, it will continue as if there was no interruption, contrary to the
/// background
window_ly: u8,
}

impl WindowLayer {
Expand All @@ -21,6 +29,7 @@ impl WindowLayer {
tile_id: 0,
tile_data_low: 0,
tile_data_high: 0,
window_ly: 0,
}
}
}
Expand All @@ -46,7 +55,7 @@ impl Layer for WindowLayer {
// This is `-7` because WX as an offset of 7, anything below that will not be
// rendered
let window_x: i32 = gpu.virtual_x as i32 - (bus[WX] as i32 - 7);
let window_y: i32 = gpu.y as i32 - bus[WY] as i32;
let window_y: i32 = self.window_ly as i32 - bus[WY] as i32;

if window_x.is_negative() || window_y.is_negative() {
self.tile_id = 0;
Expand Down Expand Up @@ -97,4 +106,27 @@ impl Layer for WindowLayer {

bytes_to_slice(self.tile_data_low, self.tile_data_high)
}

fn at_hblank(&mut self, bus: &Bus, _gpu: &Gpu) {
if is_window_showing(bus) {
self.window_ly = self.window_ly.wrapping_add(1);
}
}

fn at_vblank(&mut self, _bus: &Bus, _gpu: &Gpu) {
self.window_ly = 0;
}
}

/// If WX and WY are inside the screen bounds
fn is_window_showing(bus: &Bus) -> bool {
if (bus[WX] as usize) >= DISPLAY_SIZE_X + 7 {
return false;
}

if (bus[WY] as usize) >= DISPLAY_SIZE_Y {
return false;
}

true
}

0 comments on commit d98ae94

Please sign in to comment.