chore(ppu): improve accuracy of pixel fifo
This commit is contained in:
parent
d68257bb29
commit
c2f2e2194b
77
src/ppu.rs
77
src/ppu.rs
|
@ -231,20 +231,23 @@ impl Ppu {
|
|||
fn draw(&mut self, _cycle: u32) {
|
||||
use FetcherState::*;
|
||||
|
||||
let iter = &mut self.obj_buffer.iter();
|
||||
let mut iter = self.obj_buffer.iter_mut();
|
||||
let default = &mut None;
|
||||
|
||||
let obj_attr = loop {
|
||||
match iter.flatten().next() {
|
||||
Some(attr) => {
|
||||
if attr.x <= (self.x_pos + 8) {
|
||||
self.fetch.back.reset();
|
||||
self.fetch.back.pause();
|
||||
self.fifo.pause();
|
||||
match iter.next() {
|
||||
Some(attr_opt) => {
|
||||
if let Some(attr) = attr_opt {
|
||||
if attr.x <= (self.x_pos + 8) {
|
||||
self.fetch.back.reset();
|
||||
self.fetch.back.pause();
|
||||
self.fifo.pause();
|
||||
|
||||
break Some(*attr);
|
||||
break attr_opt;
|
||||
}
|
||||
}
|
||||
}
|
||||
None => break None,
|
||||
None => break default,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -289,13 +292,12 @@ impl Ppu {
|
|||
let tbpp = Pixels::from_bytes(high, low);
|
||||
|
||||
let palette_kind = attr.flags.palette();
|
||||
|
||||
let end = Pixels::PIXEL_COUNT - self.fifo.obj.len();
|
||||
let start = Pixels::PIXEL_COUNT - end;
|
||||
|
||||
let x_flip = attr.flags.x_flip();
|
||||
|
||||
for i in start..Pixels::PIXEL_COUNT {
|
||||
let pixel_count = (attr.x - self.x_pos) as usize;
|
||||
let start = self.fifo.obj.len();
|
||||
|
||||
for i in start..pixel_count {
|
||||
let x = if x_flip { 7 - i } else { i };
|
||||
|
||||
let priority = attr.flags.priority();
|
||||
|
@ -312,7 +314,7 @@ impl Ppu {
|
|||
|
||||
self.fetch.back.resume();
|
||||
self.fifo.resume();
|
||||
self.obj_buffer.remove(&attr);
|
||||
let _ = std::mem::take(obj_attr);
|
||||
|
||||
self.fetch.obj.next(ToFifoTwo);
|
||||
}
|
||||
|
@ -608,67 +610,34 @@ impl<'a> From<&'a [u8; 4]> for ObjectAttribute {
|
|||
|
||||
#[derive(Debug)]
|
||||
struct ObjectBuffer {
|
||||
buf: [Option<ObjectAttribute>; OBJECT_LIMIT],
|
||||
inner: [Option<ObjectAttribute>; OBJECT_LIMIT],
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl ObjectBuffer {
|
||||
fn iter(&self) -> std::slice::Iter<'_, Option<ObjectAttribute>> {
|
||||
self.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a ObjectBuffer {
|
||||
type Item = &'a Option<ObjectAttribute>;
|
||||
|
||||
type IntoIter = std::slice::Iter<'a, Option<ObjectAttribute>>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.buf.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a mut ObjectBuffer {
|
||||
type Item = &'a Option<ObjectAttribute>;
|
||||
|
||||
type IntoIter = std::slice::Iter<'a, Option<ObjectAttribute>>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.buf.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectBuffer {
|
||||
fn is_full(&self) -> bool {
|
||||
self.len == OBJECT_LIMIT
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.buf = [Default::default(); 10];
|
||||
self.inner = [Default::default(); 10];
|
||||
self.len = 0;
|
||||
}
|
||||
|
||||
fn add(&mut self, attr: ObjectAttribute) {
|
||||
self.buf[self.len] = Some(attr);
|
||||
self.inner[self.len] = Some(attr);
|
||||
self.len += 1;
|
||||
}
|
||||
|
||||
fn remove(&mut self, attr: &ObjectAttribute) {
|
||||
let maybe_index = self.buf.iter().position(|maybe_attr| match maybe_attr {
|
||||
Some(other_attr) => attr == other_attr,
|
||||
None => false,
|
||||
});
|
||||
|
||||
if let Some(i) = maybe_index {
|
||||
self.buf[i] = None;
|
||||
}
|
||||
fn iter_mut(&mut self) -> std::slice::IterMut<'_, Option<ObjectAttribute>> {
|
||||
self.inner.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ObjectBuffer {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
buf: [Default::default(); OBJECT_LIMIT],
|
||||
inner: [Default::default(); OBJECT_LIMIT],
|
||||
len: Default::default(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue