fix(ppu): reimplement the pixel fifo shifter

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-04-30 17:44:02 -05:00
parent 11398303b5
commit b251efcc7d
2 changed files with 43 additions and 38 deletions

View File

@ -190,8 +190,6 @@ impl Ppu {
fn draw(&mut self, _cycle: u32) { fn draw(&mut self, _cycle: u32) {
use FetcherState::*; use FetcherState::*;
let control = &self.control;
let pos = &self.pos;
let iter = &mut self.obj_buffer.iter(); let iter = &mut self.obj_buffer.iter();
@ -298,8 +296,8 @@ impl Ppu {
let x_pos = self.fetcher.x_pos; let x_pos = self.fetcher.x_pos;
let addr = self.fetcher.bg_tile_num_addr( let addr = self.fetcher.bg_tile_num_addr(
control, &self.control,
pos, &self.pos,
x_pos, x_pos,
self.window_stat.should_draw(), self.window_stat.should_draw(),
); );
@ -312,9 +310,11 @@ impl Ppu {
} }
ToLowByteSleep => self.fetcher.bg.next(TileLowByte), ToLowByteSleep => self.fetcher.bg.next(TileLowByte),
TileLowByte => { TileLowByte => {
let addr = let addr = self.fetcher.bg_byte_low_addr(
self.fetcher &self.control,
.bg_byte_low_addr(control, pos, self.window_stat.should_draw()); &self.pos,
self.window_stat.should_draw(),
);
let low = self.read_byte(addr); let low = self.read_byte(addr);
self.fetcher.bg.tile.with_low_byte(low); self.fetcher.bg.tile.with_low_byte(low);
@ -323,9 +323,11 @@ impl Ppu {
} }
ToHighByteSleep => self.fetcher.bg.next(TileHighByte), ToHighByteSleep => self.fetcher.bg.next(TileHighByte),
TileHighByte => { TileHighByte => {
let addr = let addr = self.fetcher.bg_byte_low_addr(
self.fetcher &self.control,
.bg_byte_low_addr(control, pos, self.window_stat.should_draw()); &self.pos,
self.window_stat.should_draw(),
);
let high = self.read_byte(addr + 1); let high = self.read_byte(addr + 1);
self.fetcher.bg.tile.with_high_byte(high); self.fetcher.bg.tile.with_high_byte(high);
@ -348,36 +350,43 @@ impl Ppu {
if self.fifo.is_enabled() { if self.fifo.is_enabled() {
// Handle Background Pixel and Sprite FIFO // Handle Background Pixel and Sprite FIFO
if let Some(bg_pixel) = self.fifo.background.pop_front() { let bg_enabled = self.control.bg_win_enabled();
let rgba = match self.fifo.object.pop_front() { // FIXME: Is this the correct behaviour
Some(obj_pixel) => match obj_pixel.shade { let bg_zero_colour = self.monochrome.bg_palette.i0_colour();
Some(obj_shade) => {
if let RenderPriority::BackgroundAndWindow = obj_pixel.priority {
match bg_pixel.shade {
GrayShade::White => obj_shade.into_rgba(),
_ => bg_pixel.shade.into_rgba(),
}
} else {
obj_shade.into_rgba()
}
}
None => bg_pixel.shade.into_rgba(),
},
None => {
// Only Background Pixels will be rendered
bg_pixel.shade.into_rgba()
}
};
let maybe_rgba = self.fifo.background.pop_front().map(|bg_info| {
match self.fifo.object.pop_front() {
Some(obj_info) => match obj_info.shade {
Some(obj_shade) => match obj_info.priority {
RenderPriority::BackgroundAndWindow => match bg_info.shade {
GrayShade::White => obj_shade.into_rgba(),
_ if bg_enabled => bg_info.shade.into_rgba(),
_ => bg_zero_colour.into_rgba(),
},
RenderPriority::Object => obj_shade.into_rgba(),
},
None if bg_enabled => bg_info.shade.into_rgba(),
None => bg_zero_colour.into_rgba(),
},
None if bg_enabled => bg_info.shade.into_rgba(),
None => bg_zero_colour.into_rgba(),
}
});
if let Some(rgba) = maybe_rgba.as_ref() {
let y = self.pos.line_y as usize; let y = self.pos.line_y as usize;
let x = self.x_pos as usize; let x = self.x_pos as usize;
let i = (GB_WIDTH * 4) * y + (x * 4); let i = (GB_WIDTH * 4) * y + (x * 4);
self.frame_buf[i..(i + rgba.len())].copy_from_slice(&rgba); self.frame_buf[i..(i + rgba.len())].copy_from_slice(rgba);
self.x_pos += 1; self.x_pos += 1;
// Determine whether we should draw the window next frame // Determine whether we should draw the window next frame
if self.pos.line_y == self.pos.window_y {
self.window_stat.set_coincidence(true);
}
if self.window_stat.coincidence() if self.window_stat.coincidence()
&& self.control.window_enabled() && self.control.window_enabled()
&& self.x_pos >= self.pos.window_x - 7 && self.x_pos >= self.pos.window_x - 7
@ -387,10 +396,6 @@ impl Ppu {
self.fifo.background.clear(); self.fifo.background.clear();
self.fetcher.x_pos = 0; self.fetcher.x_pos = 0;
} else { } else {
if self.pos.line_y == self.pos.window_y {
self.window_stat.set_coincidence(true);
}
self.window_stat.set_should_draw(false); self.window_stat.set_should_draw(false);
} }
} }

View File

@ -79,8 +79,8 @@ bitfield! {
pub from into TileDataAddress, tile_data_addr, set_tile_data_addr: 4, 4; pub from into TileDataAddress, tile_data_addr, set_tile_data_addr: 4, 4;
pub from into TileMapAddress, bg_tile_map_addr, set_bg_tile_map_addr: 3, 3; pub from into TileMapAddress, bg_tile_map_addr, set_bg_tile_map_addr: 3, 3;
pub from into ObjectSize, obj_size, set_obj_size: 2, 2; pub from into ObjectSize, obj_size, set_obj_size: 2, 2;
obj_enabled, set_obj_enabled: 1; pub obj_enabled, set_obj_enabled: 1;
bg_win_enabled, set_bg_win_enabled: 0; pub bg_win_enabled, set_bg_win_enabled: 0;
} }
impl Copy for LCDControl {} impl Copy for LCDControl {}
@ -384,7 +384,7 @@ impl From<ObjectPaletteId> for u8 {
} }
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum RenderPriority { pub enum RenderPriority {
Object = 0, Object = 0,
BackgroundAndWindow = 1, BackgroundAndWindow = 1,