chore(ppu): rename types and improve code quality

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-04-18 01:45:09 -05:00
parent b43c8ac7c9
commit 2acdaaeec2
1 changed files with 85 additions and 75 deletions

View File

@ -10,7 +10,7 @@ const OAM_SIZE: usize = 0xA0;
const PPU_START_ADDRESS: usize = 0x8000; const PPU_START_ADDRESS: usize = 0x8000;
// OAM Scan // OAM Scan
const SPRITE_BUFFER_LIMIT: usize = 10; const OBJECT_LIMIT: usize = 10;
const WHITE: [u8; 4] = [0xFF, 0xFF, 0xFF, 0xFF]; const WHITE: [u8; 4] = [0xFF, 0xFF, 0xFF, 0xFF];
const LIGHT_GRAY: [u8; 4] = [0xCC, 0xCC, 0xCC, 0xFF]; const LIGHT_GRAY: [u8; 4] = [0xCC, 0xCC, 0xCC, 0xFF];
@ -25,10 +25,10 @@ pub struct Ppu {
pub pos: ScreenPosition, pub pos: ScreenPosition,
pub vram: Box<[u8; VRAM_SIZE]>, pub vram: Box<[u8; VRAM_SIZE]>,
pub stat: LCDStatus, pub stat: LCDStatus,
pub oam: SpriteAttributeTable, pub oam: ObjectAttributeTable,
fetcher: PixelFetcher, fetcher: PixelFetcher,
fifo: FifoRenderer, fifo: FifoRenderer,
sprite_buffer: SpriteBuffer, obj_buffer: ObjectBuffer,
frame_buf: Box<[u8; GB_WIDTH * GB_HEIGHT * 4]>, frame_buf: Box<[u8; GB_WIDTH * GB_HEIGHT * 4]>,
x_pos: u8, x_pos: u8,
cycles: Cycle, cycles: Cycle,
@ -158,9 +158,9 @@ impl Ppu {
if attr.x > 0 if attr.x > 0
&& line_y >= attr.y && line_y >= attr.y
&& line_y < (attr.y + sprite_height) && line_y < (attr.y + sprite_height)
&& !self.sprite_buffer.full() && !self.obj_buffer.full()
{ {
self.sprite_buffer.add(attr); self.obj_buffer.add(attr);
} }
} }
} }
@ -181,7 +181,7 @@ impl Ppu {
// Increment Window line counter if scanline had any window pixels on it // Increment Window line counter if scanline had any window pixels on it
// only increment once per scanline though // only increment once per scanline though
if window_present && !self.fetcher.window_line.already_checked() { if window_present && !self.fetcher.window_line.checked() {
self.fetcher.window_line.increment(); self.fetcher.window_line.increment();
} }
@ -203,7 +203,7 @@ impl Ppu {
let scx_offset = if window_present { 0 } else { scroll_x / 8 } & 0x1F; let scx_offset = if window_present { 0 } else { scroll_x / 8 } & 0x1F;
let offset = if window_present { let offset = if window_present {
32 * (self.fetcher.window_line.value() as u16 / 8) 32 * (self.fetcher.window_line.count() as u16 / 8)
} else { } else {
32 * (((y_offset) & 0x00FF) / 8) 32 * (((y_offset) & 0x00FF) / 8)
}; };
@ -211,7 +211,7 @@ impl Ppu {
let addr = tile_map_addr + offset + x_offset + scx_offset as u16; let addr = tile_map_addr + offset + x_offset + scx_offset as u16;
let id = self.read_byte(addr); let id = self.read_byte(addr);
self.fetcher.builder.with_id(id); self.fetcher.tile.with_id(id);
// Move on to the Next state in 2 T-cycles // Move on to the Next state in 2 T-cycles
self.fetcher.state = TileDataLow; self.fetcher.state = TileDataLow;
@ -219,7 +219,7 @@ impl Ppu {
TileDataLow => { TileDataLow => {
let id = self let id = self
.fetcher .fetcher
.builder .tile
.id .id
.expect("Tile Number unexpectedly missing"); .expect("Tile Number unexpectedly missing");
@ -229,21 +229,21 @@ impl Ppu {
}; };
let offset = if window_present { let offset = if window_present {
2 * (self.fetcher.window_line.value() % 8) 2 * (self.fetcher.window_line.count() % 8)
} else { } else {
2 * ((line_y + scroll_y) % 8) 2 * ((line_y + scroll_y) % 8)
}; };
let addr = tile_data_addr + offset as u16; let addr = tile_data_addr + offset as u16;
let low = self.read_byte(addr); let low = self.read_byte(addr);
self.fetcher.builder.with_data_low(low); self.fetcher.tile.with_low_byte(low);
self.fetcher.state = TileDataHigh; self.fetcher.state = TileDataHigh;
} }
TileDataHigh => { TileDataHigh => {
let id = self let id = self
.fetcher .fetcher
.builder .tile
.id .id
.expect("Tile Number unexpectedly missing"); .expect("Tile Number unexpectedly missing");
@ -253,21 +253,21 @@ impl Ppu {
}; };
let offset = if window_present { let offset = if window_present {
2 * (self.fetcher.window_line.value() % 8) 2 * (self.fetcher.window_line.count() % 8)
} else { } else {
2 * ((line_y + scroll_y) % 8) 2 * ((line_y + scroll_y) % 8)
}; };
let addr = tile_data_addr + offset as u16; let addr = tile_data_addr + offset as u16;
let high = self.read_byte(addr + 1); let high = self.read_byte(addr + 1);
self.fetcher.builder.with_data_high(high); self.fetcher.tile.with_high_byte(high);
self.fetcher.state = SendToFifo; self.fetcher.state = SendToFifo;
} }
SendToFifo => { SendToFifo => {
if let Some(low) = self.fetcher.builder.low { if let Some(low) = self.fetcher.tile.low {
if let Some(high) = self.fetcher.builder.high { if let Some(high) = self.fetcher.tile.high {
let pixel = Pixels::from_bytes(high, low); let pixel = TwoBitsPerPixel::from_bytes(high, low);
let palette = self.monochrome.bg_palette; let palette = self.monochrome.bg_palette;
if self.fifo.background.is_empty() { if self.fifo.background.is_empty() {
@ -296,9 +296,9 @@ impl Ppu {
} }
} }
// Handle 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(_sprite_pixel) = self.fifo.sprite.pop_front() { if let Some(_object_pixel) = self.fifo.object.pop_front() {
todo!("Mix the pixels or whatever I'm supposed todo here"); todo!("Mix the pixels or whatever I'm supposed todo here");
} else { } else {
// Only Background Pixels will be rendered // Only Background Pixels will be rendered
@ -334,7 +334,7 @@ impl Default for Ppu {
oam: Default::default(), oam: Default::default(),
fetcher: Default::default(), fetcher: Default::default(),
fifo: Default::default(), fifo: Default::default(),
sprite_buffer: Default::default(), obj_buffer: Default::default(),
x_pos: Default::default(), x_pos: Default::default(),
} }
} }
@ -734,9 +734,9 @@ impl From<ObjectPalette> for u8 {
} }
} }
struct Pixels(u8, u8); struct TwoBitsPerPixel(u8, u8);
impl Pixels { impl TwoBitsPerPixel {
pub fn from_bytes(higher: u8, lower: u8) -> Self { pub fn from_bytes(higher: u8, lower: u8) -> Self {
Self(higher, lower) Self(higher, lower)
} }
@ -750,11 +750,11 @@ impl Pixels {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct SpriteAttributeTable { pub struct ObjectAttributeTable {
buf: Box<[u8; OAM_SIZE]>, buf: Box<[u8; OAM_SIZE]>,
} }
impl SpriteAttributeTable { impl ObjectAttributeTable {
pub fn read_byte(&self, addr: u16) -> u8 { pub fn read_byte(&self, addr: u16) -> u8 {
let index = (addr - 0xFE00) as usize; let index = (addr - 0xFE00) as usize;
self.buf[index] self.buf[index]
@ -765,7 +765,7 @@ impl SpriteAttributeTable {
self.buf[index] = byte; self.buf[index] = byte;
} }
pub fn attribute(&self, index: usize) -> SpriteAttribute { pub fn attribute(&self, index: usize) -> ObjectAttribute {
let slice: &[u8; 4] = self.buf[index..(index + 4)] let slice: &[u8; 4] = self.buf[index..(index + 4)]
.try_into() .try_into()
.expect("Could not interpret &[u8] as a &[u8; 4]"); .expect("Could not interpret &[u8] as a &[u8; 4]");
@ -774,7 +774,7 @@ impl SpriteAttributeTable {
} }
} }
impl Default for SpriteAttributeTable { impl Default for ObjectAttributeTable {
fn default() -> Self { fn default() -> Self {
Self { Self {
buf: Box::new([0; OAM_SIZE]), buf: Box::new([0; OAM_SIZE]),
@ -783,14 +783,14 @@ impl Default for SpriteAttributeTable {
} }
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
pub struct SpriteAttribute { pub struct ObjectAttribute {
y: u8, y: u8,
x: u8, x: u8,
tile_index: u8, tile_index: u8,
flags: SpriteFlag, flags: ObjectFlags,
} }
impl From<[u8; 4]> for SpriteAttribute { impl From<[u8; 4]> for ObjectAttribute {
fn from(bytes: [u8; 4]) -> Self { fn from(bytes: [u8; 4]) -> Self {
Self { Self {
y: bytes[0], y: bytes[0],
@ -801,7 +801,7 @@ impl From<[u8; 4]> for SpriteAttribute {
} }
} }
impl<'a> From<&'a [u8; 4]> for SpriteAttribute { impl<'a> From<&'a [u8; 4]> for ObjectAttribute {
fn from(bytes: &'a [u8; 4]) -> Self { fn from(bytes: &'a [u8; 4]) -> Self {
Self { Self {
y: bytes[0], y: bytes[0],
@ -813,35 +813,35 @@ impl<'a> From<&'a [u8; 4]> for SpriteAttribute {
} }
bitfield! { bitfield! {
pub struct SpriteFlag(u8); pub struct ObjectFlags(u8);
impl Debug; impl Debug;
from into RenderPriority, priority, set_priority: 7, 7; from into RenderPriority, priority, set_priority: 7, 7;
y_flip, set_y_flip: 6; y_flip, set_y_flip: 6;
x_flip, set_x_flip: 5; x_flip, set_x_flip: 5;
from into SpritePaletteNumber, palette, set_palette: 4, 4; from into ObjectPaletteId, palette, set_palette: 4, 4;
} }
impl Copy for SpriteFlag {} impl Copy for ObjectFlags {}
impl Clone for SpriteFlag { impl Clone for ObjectFlags {
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
} }
impl From<u8> for SpriteFlag { impl From<u8> for ObjectFlags {
fn from(byte: u8) -> Self { fn from(byte: u8) -> Self {
Self(byte) Self(byte)
} }
} }
impl From<SpriteFlag> for u8 { impl From<ObjectFlags> for u8 {
fn from(flags: SpriteFlag) -> Self { fn from(flags: ObjectFlags) -> Self {
flags.0 flags.0
} }
} }
impl Default for SpriteFlag { impl Default for ObjectFlags {
fn default() -> Self { fn default() -> Self {
Self(0) Self(0)
} }
@ -849,14 +849,14 @@ impl Default for SpriteFlag {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum RenderPriority { pub enum RenderPriority {
Sprite = 0, Object = 0,
BackgroundAndWindow = 1, BackgroundAndWindow = 1,
} }
impl From<u8> for RenderPriority { impl From<u8> for RenderPriority {
fn from(byte: u8) -> Self { fn from(byte: u8) -> Self {
match byte { match byte {
0b00 => Self::Sprite, 0b00 => Self::Object,
0b01 => Self::BackgroundAndWindow, 0b01 => Self::BackgroundAndWindow,
_ => unreachable!("{:#04X} is not a valid value for RenderPriority", byte), _ => unreachable!("{:#04X} is not a valid value for RenderPriority", byte),
} }
@ -871,39 +871,39 @@ impl From<RenderPriority> for u8 {
impl Default for RenderPriority { impl Default for RenderPriority {
fn default() -> Self { fn default() -> Self {
Self::Sprite Self::Object
} }
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum SpritePaletteNumber { pub enum ObjectPaletteId {
SpritePalette0 = 0, Palette0 = 0,
SpritePalette1 = 1, Palette1 = 1,
} }
impl From<u8> for SpritePaletteNumber { impl From<u8> for ObjectPaletteId {
fn from(byte: u8) -> Self { fn from(byte: u8) -> Self {
match byte { match byte {
0b00 => SpritePaletteNumber::SpritePalette0, 0b00 => ObjectPaletteId::Palette0,
0b01 => SpritePaletteNumber::SpritePalette1, 0b01 => ObjectPaletteId::Palette1,
_ => unreachable!("{:#04X} is not a valid value for BgPaletteNumber", byte), _ => unreachable!("{:#04X} is not a valid value for BgPaletteNumber", byte),
} }
} }
} }
impl From<SpritePaletteNumber> for u8 { impl From<ObjectPaletteId> for u8 {
fn from(flip: SpritePaletteNumber) -> Self { fn from(palette_num: ObjectPaletteId) -> Self {
flip as u8 palette_num as u8
} }
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
struct SpriteBuffer { struct ObjectBuffer {
buf: [SpriteAttribute; 10], buf: [ObjectAttribute; 10],
len: usize, len: usize,
} }
impl SpriteBuffer { impl ObjectBuffer {
pub fn full(&self) -> bool { pub fn full(&self) -> bool {
self.len == self.buf.len() self.len == self.buf.len()
} }
@ -913,16 +913,16 @@ impl SpriteBuffer {
self.len = 0; self.len = 0;
} }
pub fn add(&mut self, attr: SpriteAttribute) { pub fn add(&mut self, attr: ObjectAttribute) {
self.buf[self.len] = attr; self.buf[self.len] = attr;
self.len += 1; self.len += 1;
} }
} }
impl Default for SpriteBuffer { impl Default for ObjectBuffer {
fn default() -> Self { fn default() -> Self {
Self { Self {
buf: [Default::default(); SPRITE_BUFFER_LIMIT], buf: [Default::default(); OBJECT_LIMIT],
len: 0, len: 0,
} }
} }
@ -930,17 +930,17 @@ impl Default for SpriteBuffer {
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
struct PixelFetcher { struct PixelFetcher {
state: FetcherState,
x_pos: u8, x_pos: u8,
state: FetcherState,
window_line: WindowLineCounter, window_line: WindowLineCounter,
builder: TileBuilder, tile: TileBuilder,
} }
impl PixelFetcher { impl PixelFetcher {
pub fn hblank_reset(&mut self) { pub fn hblank_reset(&mut self) {
self.window_line.hblank_reset(); self.window_line.hblank_reset();
self.builder = Default::default(); self.tile = Default::default();
self.state = Default::default(); self.state = Default::default();
self.x_pos = 0; self.x_pos = 0;
} }
@ -952,31 +952,31 @@ impl PixelFetcher {
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
struct WindowLineCounter { struct WindowLineCounter {
value: u8, count: u8,
already_checked: bool, checked: bool,
} }
impl WindowLineCounter { impl WindowLineCounter {
pub fn already_checked(&self) -> bool { pub fn checked(&self) -> bool {
self.already_checked self.checked
} }
pub fn increment(&mut self) { pub fn increment(&mut self) {
self.value += 1; self.count += 1;
self.already_checked = true; self.checked = true;
} }
pub fn hblank_reset(&mut self) { pub fn hblank_reset(&mut self) {
self.already_checked = false; self.checked = false;
} }
pub fn vblank_reset(&mut self) { pub fn vblank_reset(&mut self) {
self.value = 0; self.count = 0;
self.already_checked = false; self.checked = false;
} }
pub fn value(&self) -> u8 { pub fn count(&self) -> u8 {
self.value self.count
} }
} }
@ -997,7 +997,7 @@ impl Default for FetcherState {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
enum FifoPixelKind { enum FifoPixelKind {
Background, Background,
Sprite, Object,
} }
impl Default for FifoPixelKind { impl Default for FifoPixelKind {
@ -1014,19 +1014,29 @@ struct FifoPixel {
priority: Option<RenderPriority>, priority: Option<RenderPriority>,
} }
impl FifoPixel {
pub fn new_background(shade: GrayShade) -> Self {
Self {
kind: FifoPixelKind::Background,
shade,
..Default::default()
}
}
}
// FIXME: Fifo Registers have a known size. Are heap allocations // FIXME: Fifo Registers have a known size. Are heap allocations
// really necessary here? // really necessary here?
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct FifoRenderer { struct FifoRenderer {
background: VecDeque<FifoPixel>, background: VecDeque<FifoPixel>,
sprite: VecDeque<FifoPixel>, object: VecDeque<FifoPixel>,
} }
impl Default for FifoRenderer { impl Default for FifoRenderer {
fn default() -> Self { fn default() -> Self {
Self { Self {
background: VecDeque::with_capacity(8), background: VecDeque::with_capacity(8),
sprite: VecDeque::with_capacity(8), object: VecDeque::with_capacity(8),
} }
} }
} }
@ -1043,11 +1053,11 @@ impl TileBuilder {
self.id = Some(id); self.id = Some(id);
} }
pub fn with_data_low(&mut self, data: u8) { pub fn with_low_byte(&mut self, data: u8) {
self.low = Some(data); self.low = Some(data);
} }
pub fn with_data_high(&mut self, data: u8) { pub fn with_high_byte(&mut self, data: u8) {
self.high = Some(data); self.high = Some(data);
} }
} }