chore(ppu): refactor behaviour w.r.t window enabling

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-10-20 04:48:20 -03:00
parent da83032e24
commit d9f1d661ae
1 changed files with 33 additions and 89 deletions

View File

@ -81,6 +81,12 @@ impl Ppu {
PpuMode::OamScan => { PpuMode::OamScan => {
// Cycles 1 -> 80 // Cycles 1 -> 80
if self.dot >= 80 { if self.dot >= 80 {
self.x_pos = 0;
self.scanline_start = true;
self.to_discard = 0;
self.fifo.back.clear();
self.fifo.obj.clear();
self.stat.set_mode(PpuMode::Drawing); self.stat.set_mode(PpuMode::Drawing);
} }
@ -105,21 +111,14 @@ impl Ppu {
// Increment Window line counter if scanline had any window pixels on it // Increment Window line counter if scanline had any window pixels on it
// only increment once per scanline though // only increment once per scanline though
if self.win_stat.should_draw() { if self.win_stat.enabled {
self.fetch.back.window_line.increment(); self.fetch.back.wl_count += 1;
} }
self.x_pos = 0;
self.scanline_start = true;
self.to_discard = 0;
self.fetch.hblank_reset(); self.fetch.hblank_reset();
self.win_stat.hblank_reset(); self.win_stat.enabled = false;
self.obj_buffer.clear(); self.obj_buffer.clear();
self.fifo.back.clear();
self.fifo.obj.clear();
self.stat.set_mode(PpuMode::HBlank); self.stat.set_mode(PpuMode::HBlank);
} }
} }
@ -144,9 +143,10 @@ impl Ppu {
self.int.set_vblank(true); self.int.set_vblank(true);
// Reset Window Line Counter in Fetcher // Reset Window Line Counter in Fetcher
self.fetch.vblank_reset(); self.fetch.back.wl_count = 0;
// Reset WY=LY coincidence flag // Reset WY=LY coincidence flag
self.win_stat.vblank_reset(); self.win_stat.coincidence = false;
if self.stat.vblank_int() { if self.stat.vblank_int() {
// Enable Vblank LCDStat Interrupt // Enable Vblank LCDStat Interrupt
@ -203,9 +203,8 @@ impl Ppu {
return; return;
} }
if !self.win_stat.coincidence() && self.scan_dot == 0 { if !self.win_stat.coincidence && self.scan_dot == 0 {
self.win_stat self.win_stat.coincidence = self.pos.line_y == self.pos.window_y;
.set_coincidence(self.pos.line_y == self.pos.window_y);
} }
let obj_height = self.ctrl.obj_size().size(); let obj_height = self.ctrl.obj_size().size();
@ -317,25 +316,12 @@ impl Ppu {
} }
} }
if self.ctrl.window_enabled()
&& !self.win_stat.should_draw()
&& self.win_stat.coincidence()
&& self.x_pos as i16 >= self.pos.window_x as i16 - 7
{
self.win_stat.set_should_draw(true);
self.fetch.back.reset();
self.fetch.x_pos = 0;
self.fifo.back.clear();
}
if self.fetch.back.is_enabled() { if self.fetch.back.is_enabled() {
match self.fetch.back.state { match self.fetch.back.state {
TileNumber => { TileNumber => {
let x_pos = self.fetch.x_pos; let x_pos = self.fetch.x_pos;
self.fetch self.fetch.back.should_render_window(self.win_stat.enabled);
.back
.should_render_window(self.win_stat.should_draw());
let addr = self.fetch.bg_tile_num_addr(&self.ctrl, &self.pos, x_pos); let addr = self.fetch.bg_tile_num_addr(&self.ctrl, &self.pos, x_pos);
@ -383,7 +369,7 @@ impl Ppu {
self.scanline_start = false; self.scanline_start = false;
} }
if self.to_discard > 0 && !self.fifo.back.is_empty() { if !self.win_stat.enabled && self.to_discard > 0 && !self.fifo.back.is_empty() {
let _ = self.fifo.back.pop_front(); let _ = self.fifo.back.pop_front();
self.to_discard -= 1; self.to_discard -= 1;
@ -401,6 +387,17 @@ impl Ppu {
self.x_pos += 1; self.x_pos += 1;
} }
if self.ctrl.window_enabled()
&& !self.win_stat.enabled
&& self.win_stat.coincidence
&& self.x_pos as i16 >= self.pos.window_x as i16 - 7
{
self.win_stat.enabled = true;
self.fetch.back.reset();
self.fetch.x_pos = 0;
self.fifo.back.clear();
}
} }
} }
@ -653,10 +650,6 @@ impl PixelFetcher {
self.x_pos = 0; self.x_pos = 0;
} }
fn vblank_reset(&mut self) {
self.back.vblank_reset();
}
fn bg_tile_num_addr(&self, control: &LCDControl, pos: &ScreenPosition, x_pos: u8) -> u16 { fn bg_tile_num_addr(&self, control: &LCDControl, pos: &ScreenPosition, x_pos: u8) -> u16 {
let line_y = pos.line_y; let line_y = pos.line_y;
let scroll_y = pos.scroll_y; let scroll_y = pos.scroll_y;
@ -676,7 +669,7 @@ impl PixelFetcher {
let scx_offset = if is_window { 0 } else { scroll_x / 8 }; let scx_offset = if is_window { 0 } else { scroll_x / 8 };
let y_offset = if is_window { let y_offset = if is_window {
self.back.window_line.count() as u16 / 8 self.back.wl_count as u16 / 8
} else { } else {
((line_y as u16 + scroll_y as u16) & 0xFF) / 8 ((line_y as u16 + scroll_y as u16) & 0xFF) / 8
}; };
@ -700,7 +693,7 @@ impl PixelFetcher {
}; };
let offset = if is_window { let offset = if is_window {
self.back.window_line.count() as u16 % 8 self.back.wl_count as u16 % 8
} else { } else {
(line_y as u16 + scroll_y as u16) % 8 (line_y as u16 + scroll_y as u16) % 8
}; };
@ -762,7 +755,7 @@ trait Fetcher {
struct BackgroundFetcher { struct BackgroundFetcher {
state: FetcherState, state: FetcherState,
tile: TileBuilder, tile: TileBuilder,
window_line: WindowLineCounter, wl_count: u8,
is_window_tile: bool, is_window_tile: bool,
enabled: bool, enabled: bool,
} }
@ -787,10 +780,6 @@ impl BackgroundFetcher {
fn is_enabled(&self) -> bool { fn is_enabled(&self) -> bool {
self.enabled self.enabled
} }
fn vblank_reset(&mut self) {
self.window_line.vblank_reset();
}
} }
impl Fetcher for BackgroundFetcher { impl Fetcher for BackgroundFetcher {
@ -818,7 +807,7 @@ impl Default for BackgroundFetcher {
state: Default::default(), state: Default::default(),
tile: Default::default(), tile: Default::default(),
is_window_tile: Default::default(), is_window_tile: Default::default(),
window_line: Default::default(), wl_count: Default::default(),
enabled: true, enabled: true,
} }
} }
@ -846,25 +835,6 @@ impl Fetcher for ObjectFetcher {
} }
} }
#[derive(Debug, Default)]
struct WindowLineCounter {
count: u8,
}
impl WindowLineCounter {
fn increment(&mut self) {
self.count += 1;
}
fn vblank_reset(&mut self) {
self.count = 0;
}
fn count(&self) -> u8 {
self.count
}
}
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
enum FetcherState { enum FetcherState {
TileNumber, TileNumber,
@ -959,31 +929,5 @@ struct WindowStatus {
coincidence: bool, coincidence: bool,
/// This will be true if the conditions which tell the PPU to start /// This will be true if the conditions which tell the PPU to start
/// drawing from the window tile map is true /// drawing from the window tile map is true
should_draw: bool, enabled: bool,
}
impl WindowStatus {
fn should_draw(&self) -> bool {
self.should_draw
}
fn coincidence(&self) -> bool {
self.coincidence
}
fn set_should_draw(&mut self, value: bool) {
self.should_draw = value;
}
fn set_coincidence(&mut self, value: bool) {
self.coincidence = value;
}
fn hblank_reset(&mut self) {
self.should_draw = false;
}
fn vblank_reset(&mut self) {
self.coincidence = false;
}
} }