#![deny(missing_docs)]
mod frame_event;
mod oam;
mod palette;
mod ppu_cycle;
mod ppu_impl;
mod ppu_registers;
mod ppu_render_pixel;
mod prepare_scanline;
mod registers;
mod scanline_pos;
mod sprite;
#[cfg(test)]
mod tests;
mod vram_read_buffer;
use crate::ppu::oam::OamArray;
use arrayvec::ArrayVec;
use registers::Registers;
pub use palette::Color;
use ppu_render_pixel::BgTileToShow;
use prepare_scanline::SpriteStartForScanline;
pub use registers::Register;
use scanline_pos::ScanlinePos;
use sprite::SpriteData;
const SCREEN_WIDTH: u16 = 256;
const SCREEN_HEIGHT: u16 = 240;
const SCREEN_PIXEL_COUNT: usize = (SCREEN_WIDTH * SCREEN_HEIGHT) as usize;
#[allow(dead_code)]
const RIGHTMOST_PIXEL_X: u8 = (SCREEN_WIDTH - 1) as u8;
#[allow(dead_code)]
const BOTTOMMOST_PIXEL_Y: u8 = (SCREEN_HEIGHT - 1) as u8;
const MAX_SPRITES_IN_SCANLINE: usize = 8;
const TILE_DIM: u8 = 8;
const SMALL_SPRITE_HEIGHT: u8 = TILE_DIM;
const LARGE_SPRITE_HEIGHT: u8 = 16;
type SpriteDataArray = ArrayVec<SpriteData, MAX_SPRITES_IN_SCANLINE>;
type SpriteStartArray = ArrayVec<SpriteStartForScanline, { MAX_SPRITES_IN_SCANLINE * 2 }>;
type ScreenColors = ArrayVec<Color, SCREEN_PIXEL_COUNT>;
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum FrameEvent {
None,
EndOfScanline,
ReadyToPresent,
EndOfFrame,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum VramReadEvent {
None,
TileAddrSet,
TileDataRead,
AttrAddrSet,
AttrDataRead,
BackgroundLowAddrSet,
BackgroundLowDataRead,
BackgroundHighAddrSet,
BackgroundHighDataRead,
SpriteAddrSet {
sprite_index: u8,
is_high_byte: bool,
},
SpriteDataRead {
sprite_index: u8,
is_high_byte: bool,
},
}
#[cfg(feature = "show_name_table_change")]
#[derive(PartialEq, Eq, Default)]
enum ScanlineEvent {
#[default]
None,
ShowBg,
DontShowBg,
}
pub struct Ppu {
regs: Registers,
oam: OamArray,
palette: palette::Ram,
sprites_for_scanline: SpriteDataArray,
sprites_for_next_scanline: SpriteDataArray,
sprites_start_col: SpriteStartArray,
sprites_at_current_pixel: SpriteDataArray,
read_buffer: u8,
scanline_pos: ScanlinePos,
bg_tile: Option<BgTileToShow>,
screen_colors: ScreenColors,
vram_read_buffer: vram_read_buffer::VramReadBuffer,
pub cycle_accurate_sprites_enabled: bool,
sprite_addr: u16,
sprite_zero_pos: u8,
#[cfg(test)]
cycles_since_reset: usize,
nmi_signal: bool,
#[cfg(feature = "show_name_table_change")]
last_event: ScanlineEvent,
}
pub trait PpuCartMemorySpace {
fn read(&mut self, addr: u16) -> u8;
fn write(&mut self, data: u8, addr: u16);
fn notify_addr_change(&mut self, _old_addr: u16, _new_addr: u16) {}
}