chore(ppu): refactor OAM Scan implementation

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-10-20 03:14:30 -03:00
parent 293e5762c3
commit 37cf3d92e4
2 changed files with 26 additions and 79 deletions

View File

@ -45,7 +45,7 @@ pub struct Ppu {
vram: Box<[u8; VRAM_SIZE]>, vram: Box<[u8; VRAM_SIZE]>,
pub(crate) oam: ObjectAttributeTable, pub(crate) oam: ObjectAttributeTable,
pub(crate) dma: DirectMemoryAccess, pub(crate) dma: DirectMemoryAccess,
scan_state: OamScanState, scan_cycle: Cycle,
fetch: PixelFetcher, fetch: PixelFetcher,
fifo: PixelFifo, fifo: PixelFifo,
obj_buffer: ObjectBuffer, obj_buffer: ObjectBuffer,
@ -159,7 +159,7 @@ impl Ppu {
self.int.set_lcd_stat(true); self.int.set_lcd_stat(true);
} }
self.scan_state.reset(); self.scan_cycle = Default::default();
PpuMode::OamScan PpuMode::OamScan
}; };
@ -188,8 +188,7 @@ impl Ppu {
self.int.set_lcd_stat(true); self.int.set_lcd_stat(true);
} }
self.scan_state.reset(); self.scan_cycle = Default::default();
self.stat.set_mode(PpuMode::OamScan); self.stat.set_mode(PpuMode::OamScan);
} }
} }
@ -198,34 +197,29 @@ impl Ppu {
} }
fn scan_oam(&mut self) { fn scan_oam(&mut self) {
match self.scan_state.mode() { if self.scan_cycle % 2 == 0 {
OamScanMode::Scan if !self.dma.is_active() => { if self.dma.is_active() {
if !self.window_stat.coincidence() && self.scan_state.count() == 0 { return;
// Determine whether we should draw the window next frame }
if !self.window_stat.coincidence() && self.scan_cycle == 0 {
self.window_stat self.window_stat
.set_coincidence(self.pos.line_y == self.pos.window_y); .set_coincidence(self.pos.line_y == self.pos.window_y);
} }
let sprite_height = self.ctrl.obj_size().as_u8(); let obj_height = self.ctrl.obj_size().size();
let index = self.scan_state.count(); let attr = self.oam.attribute(self.scan_cycle as usize / 2);
let attr = self.oam.attribute(index as usize);
let line_y = self.pos.line_y + 16; let line_y = self.pos.line_y + 16;
if attr.x > 0 if attr.x > 0
&& line_y >= attr.y && line_y >= attr.y
&& line_y < (attr.y + sprite_height) && line_y < (attr.y + obj_height)
&& !self.obj_buffer.is_full() && !self.obj_buffer.is_full()
{ {
self.obj_buffer.add(attr); self.obj_buffer.add(attr);
} }
self.scan_state.increase();
} }
_ => {} self.scan_cycle += 1;
}
self.scan_state.next();
} }
fn draw(&mut self, _cycle: Cycle) { fn draw(&mut self, _cycle: Cycle) {
@ -478,7 +472,7 @@ impl Default for Ppu {
pos: Default::default(), pos: Default::default(),
stat: Default::default(), stat: Default::default(),
oam: Default::default(), oam: Default::default(),
scan_state: Default::default(), scan_cycle: Default::default(),
fetch: Default::default(), fetch: Default::default(),
fifo: Default::default(), fifo: Default::default(),
obj_buffer: Default::default(), obj_buffer: Default::default(),
@ -958,53 +952,6 @@ impl TileBuilder {
} }
} }
#[derive(Debug, Default)]
struct OamScanState {
count: u8,
mode: OamScanMode,
}
impl OamScanState {
fn increase(&mut self) {
self.count += 1;
self.count %= 40;
}
fn reset(&mut self) {
self.count = Default::default();
self.mode = Default::default();
}
fn count(&self) -> u8 {
self.count
}
fn mode(&self) -> &OamScanMode {
&self.mode
}
fn next(&mut self) {
use OamScanMode::*;
self.mode = match self.mode {
Scan => Sleep,
Sleep => Scan,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
enum OamScanMode {
Scan,
Sleep,
}
impl Default for OamScanMode {
fn default() -> Self {
Self::Scan
}
}
#[derive(Debug, Default)] #[derive(Debug, Default)]
struct WindowStatus { struct WindowStatus {
/// This will be true if WY == LY at any point in the frame thus far /// This will be true if WY == LY at any point in the frame thus far

View File

@ -183,7 +183,7 @@ pub enum ObjectSize {
} }
impl ObjectSize { impl ObjectSize {
pub(crate) fn as_u8(&self) -> u8 { pub(crate) fn size(&self) -> u8 {
use ObjectSize::*; use ObjectSize::*;
match self { match self {