fix(ppu): fix sprite buffer bug

Now, the background renders like it should and some sprites do load,
though they aren't where they're supposed to be
This commit is contained in:
Rekai Nyangadzayi Musuka 2021-04-20 04:26:28 -05:00
parent 4f4c867a63
commit c90b9ab024
1 changed files with 111 additions and 67 deletions

View File

@ -186,7 +186,7 @@ impl Ppu {
self.fetcher.bg.pause(); self.fetcher.bg.pause();
self.fifo.pause(); self.fifo.pause();
obj_attr = Some(attr); obj_attr = Some(*attr);
} }
} }
} }
@ -207,7 +207,7 @@ impl Ppu {
ObjectSize::EightBySixteen => 16, ObjectSize::EightBySixteen => 16,
}; };
let addr = PixelFetcher::get_obj_low_addr(attr, &self.pos, obj_size); let addr = PixelFetcher::get_obj_low_addr(&attr, &self.pos, obj_size);
let byte = self.read_byte(addr); let byte = self.read_byte(addr);
self.fetcher.obj.tile.with_low_byte(byte); self.fetcher.obj.tile.with_low_byte(byte);
@ -222,7 +222,7 @@ impl Ppu {
ObjectSize::EightBySixteen => 16, ObjectSize::EightBySixteen => 16,
}; };
let addr = PixelFetcher::get_obj_low_addr(attr, &self.pos, obj_size); let addr = PixelFetcher::get_obj_low_addr(&attr, &self.pos, obj_size);
let byte = self.read_byte(addr + 1); let byte = self.read_byte(addr + 1);
self.fetcher.obj.tile.with_high_byte(byte); self.fetcher.obj.tile.with_high_byte(byte);
@ -268,6 +268,10 @@ impl Ppu {
self.fetcher.bg.resume(); self.fetcher.bg.resume();
self.fifo.resume(); self.fifo.resume();
self.obj_buffer
.remove(&attr)
.expect("Failed to remove Sprite Attribute from Buffer");
} }
} else if self.fetcher.obj.fifo_count == 2 { } else if self.fetcher.obj.fifo_count == 2 {
self.fetcher.obj.reset(); self.fetcher.obj.reset();
@ -279,8 +283,7 @@ impl Ppu {
} }
// By only running on odd cycles, we can ensure that we draw every two T cycles // By only running on odd cycles, we can ensure that we draw every two T cycles
if cycle % 2 != 0 { if cycle % 2 != 0 && self.fetcher.bg.is_enabled() {
if self.fetcher.bg.is_enabled() {
match self.fetcher.bg.state { match self.fetcher.bg.state {
TileNumber => { TileNumber => {
// Increment Window line counter if scanline had any window pixels on it // Increment Window line counter if scanline had any window pixels on it
@ -326,23 +329,35 @@ 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() { if let Some(bg_pixel) = self.fifo.background.pop_front() {
if let Some(_object_pixel) = self.fifo.object.pop_front() { let rgba = match self.fifo.object.pop_front() {
todo!("Mix the pixels or whatever I'm supposed todo here"); Some(obj_pixel) => match obj_pixel.shade {
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 { } else {
obj_shade.into_rgba()
}
}
None => bg_pixel.shade.into_rgba(),
},
None => {
// Only Background Pixels will be rendered // Only Background Pixels will be rendered
bg_pixel.shade.into_rgba()
}
};
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 rgba = bg_pixel.0.into_rgba();
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;
} }
@ -816,7 +831,7 @@ impl Default for ObjectAttributeTable {
} }
} }
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct ObjectAttribute { pub struct ObjectAttribute {
y: u8, y: u8,
x: u8, x: u8,
@ -856,6 +871,13 @@ bitfield! {
from into ObjectPaletteId, palette, set_palette: 4, 4; from into ObjectPaletteId, palette, set_palette: 4, 4;
} }
impl Eq for ObjectFlags {}
impl PartialEq for ObjectFlags {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl Copy for ObjectFlags {} impl Copy for ObjectFlags {}
impl Clone for ObjectFlags { impl Clone for ObjectFlags {
fn clone(&self) -> Self { fn clone(&self) -> Self {
@ -963,6 +985,38 @@ impl ObjectBuffer {
None None
} }
} }
pub fn position(&self, attr: &ObjectAttribute) -> Option<usize> {
let mut index = None;
for i in 0..self.len {
if self.buf[i] == *attr {
index = Some(i);
}
}
index
}
pub fn remove(&mut self, attr: &ObjectAttribute) -> Result<(), Box<dyn std::error::Error>> {
// TODO: Make this not bad code
let mut copy: ObjectBuffer = Default::default();
let i = self
.position(attr)
.ok_or_else(|| format!("Could not find {:?} in Sprite Buffer", attr))?;
for j in 0..self.len {
if j != i {
copy.add(self.buf[j])
}
}
self.buf = copy.buf;
self.len = copy.len;
Ok(())
}
} }
impl Default for ObjectBuffer { impl Default for ObjectBuffer {
@ -1073,7 +1127,7 @@ impl PixelFetcher {
let shade = palette.colour(pixel.pixel(bit)); let shade = palette.colour(pixel.pixel(bit));
let fifo_pixel = BackgroundFifoPixel(shade); let fifo_pixel = BackgroundFifoPixel { shade };
fifo.background.push_back(fifo_pixel); fifo.background.push_back(fifo_pixel);
} }
} }
@ -1222,20 +1276,10 @@ impl Default for FetcherState {
} }
} }
#[derive(Debug, Clone, Copy)]
enum FifoPixelKind {
Background,
Object,
}
impl Default for FifoPixelKind {
fn default() -> Self {
Self::Background
}
}
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
struct BackgroundFifoPixel(GrayShade); struct BackgroundFifoPixel {
shade: GrayShade,
}
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
struct ObjectFifoPixel { struct ObjectFifoPixel {