cge_nes 0.1.2

Cycle-accurate NES (Nintendo Entertainment System) emulator library: CPU, PPU, cartridge, input, and iNES ROM loading.
Documentation
//! PPU status register flags and utilities.
//!
//! Bitflags representing the PPU status register ($2002) and helpers to
//! manipulate status bits such as VBlank, Sprite Zero Hit and overflow.
use crate::ppu::registers::Registers;
use bitflags::bitflags;

bitflags! {
    /// PPU Status Register ($2002) - Read Only
    ///
    /// Contains information about the current state of the PPU:
    /// - Bit 7: VBlank indicator
    /// - Bit 6: Sprite 0 Hit indicator
    /// - Bit 5: Sprite overflow indicator
    /// - Bits 0-4: Open bus (unused)
    #[derive(Default, PartialEq, Eq, Copy, Clone, Debug)]
    pub struct PpuStatus: u8 {
        const OPEN_BUS_0 =          0b00000001;
        const OPEN_BUS_1 =          0b00000010;
        const OPEN_BUS_2 =          0b00000100;
        const OPEN_BUS_3 =          0b00001000;
        const OPEN_BUS_4 =          0b00010000;
        const SPRITE_OVERFLOW =     0b00100000;
        const SPRITE_ZERO_HIT =     0b01000000;
        const VBLANK_STARTED =      0b10000000;
        const BEGIN_FRAME_CLEAR =   Self::VBLANK_STARTED.bits() | Self::SPRITE_ZERO_HIT.bits() | PpuStatus::SPRITE_OVERFLOW.bits();
    }
}

impl Registers {
    /// Clears the VBlank, Sprite Zero Hit, and Sprite Overflow flags at the beginning of a new frame
    pub fn frame_begin_clear_flags(&mut self) {
        self.ppu_status.remove(PpuStatus::BEGIN_FRAME_CLEAR);
    }

    /// Sets the VBlank flag when entering the vertical blanking period
    pub fn start_vblank(&mut self) {
        self.ppu_status.insert(PpuStatus::VBLANK_STARTED);
    }

    /// Returns true if the PPU is currently in VBlank period
    pub fn vblank_started(&self) -> bool {
        self.ppu_status.contains(PpuStatus::VBLANK_STARTED)
    }

    /// Sets the Sprite Zero Hit flag when sprite 0 collides with background
    pub fn set_sprite_zero_hit(&mut self) {
        self.ppu_status.insert(PpuStatus::SPRITE_ZERO_HIT);
    }

    /// Sets the Sprite Overflow flag when more than 8 sprites are found
    /// in range for the current scanline.
    pub fn set_sprite_overflow(&mut self) {
        self.ppu_status.insert(PpuStatus::SPRITE_OVERFLOW);
    }
}