use crate::ppu::clock::MAX_SCANLINE;
#[derive(Clone, Copy)]
pub struct PpuIoBus {
value: u8,
scanlines_until_decay: Option<u16>,
scanlines_until_unused_status_bits_decay: Option<u16>,
}
impl PpuIoBus {
pub fn new() -> PpuIoBus {
PpuIoBus {
value: 0,
scanlines_until_decay: None,
scanlines_until_unused_status_bits_decay: None,
}
}
pub fn value(&self) -> u8 {
self.value
}
pub fn update_from_read(&mut self, value: u8) {
self.value = value;
self.scanlines_until_unused_status_bits_decay = None;
self.scanlines_until_decay = Some(MAX_SCANLINE);
}
pub fn update_from_status_read(&mut self, value: u8) {
self.value = value;
self.scanlines_until_unused_status_bits_decay = self.scanlines_until_decay;
self.scanlines_until_decay = Some(MAX_SCANLINE);
}
pub fn update_from_write(&mut self, value: u8) {
self.value = value;
self.scanlines_until_decay = Some(MAX_SCANLINE);
self.scanlines_until_unused_status_bits_decay = None;
}
pub fn maybe_decay(&mut self) {
let v = &mut self.value;
maybe_decay_internal(v, &mut self.scanlines_until_decay, 0b0000_0000);
maybe_decay_internal(
v,
&mut self.scanlines_until_unused_status_bits_decay,
0b1110_0000,
);
}
}
#[inline]
fn maybe_decay_internal(latch: &mut u8, scanlines_remaining: &mut Option<u16>, mask: u8) {
match *scanlines_remaining {
None => { }
Some(0) => {
*latch &= mask;
*scanlines_remaining = None;
}
Some(scanlines) => *scanlines_remaining = Some(scanlines - 1),
}
}