feat(ppu): stub sprite attribute table

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-04-08 20:28:16 -05:00
parent 23de87e482
commit 770b081f98
2 changed files with 144 additions and 14 deletions

View File

@ -126,7 +126,7 @@ impl Bus {
}
0xFE00..=0xFE9F => {
// Sprite Attribute Table
unimplemented!("Unable to read {:#06X} in the Sprite Attribute Table", addr);
self.ppu.oam.read_byte(addr)
}
0xFEA0..=0xFEFF => {
eprintln!("Read from {:#06X}, which is prohibited", addr);
@ -161,10 +161,8 @@ impl Bus {
0xFF49 => self.ppu.monochrome.obj_palette_1.into(),
0xFF4A => self.ppu.pos.window_y,
0xFF4B => self.ppu.pos.window_x,
0xFF4D => {
// Reading from this address is useful on the CGB only
0x00
}
0xFF4D => 0x00, // Reading from this address is useful on the CGB only
0xFF7F => 0x00, // Don't think this address is used for anything
_ => unimplemented!("Unable to read {:#06X} in I/O Registers", addr),
}
}
@ -232,7 +230,7 @@ impl Bus {
}
0xFE00..=0xFE9F => {
// Sprite Attribute Table
unimplemented!("Unable to write to {:#06X} in Sprite Attribute Table", addr);
self.ppu.oam.write_byte(addr, byte);
}
0xFEA0..=0xFEFF => {
eprintln!("Wrote {:#04X} to {:#06X}, which is prohibited", byte, addr);
@ -276,15 +274,14 @@ impl Bus {
0xFF49 => self.ppu.monochrome.obj_palette_1 = byte.into(),
0xFF4A => self.ppu.pos.window_y = byte,
0xFF4B => self.ppu.pos.window_x = byte,
0xFF4D => {
// Writing to this address is useful on the CGB only
}
0xFF4D => {} // Writing to this address is useful on the CGB only
0xFF50 => {
// Disable Boot ROM
if byte != 0 {
self.boot = None;
}
}
0xFF7F => {} // Don't think this address is used for anything
_ => unimplemented!("Unable to write to {:#06X} in I/O Registers", addr),
};
}

View File

@ -1,10 +1,12 @@
use std::convert::TryInto;
use crate::Cycle;
use crate::GB_HEIGHT;
use crate::GB_WIDTH;
use bitfield::bitfield;
const VRAM_SIZE: usize = 8192;
const OAM_SIZE: usize = 160;
const VRAM_SIZE: usize = 0x2000;
const OAM_SIZE: usize = 0xA0;
const PPU_START_ADDRESS: usize = 0x8000;
const WHITE: [u8; 4] = [0xFF, 0xFF, 0xFF, 0xFF];
@ -19,9 +21,9 @@ pub struct Ppu {
pub monochrome: Monochrome,
pub pos: ScreenPosition,
pub vram: Box<[u8; VRAM_SIZE]>,
pub oam: Box<[u8; OAM_SIZE]>,
frame_buf: [u8; GB_WIDTH * GB_HEIGHT * 4],
pub stat: LCDStatus,
pub oam: SpriteAttributeTable,
frame_buf: [u8; GB_WIDTH * GB_HEIGHT * 4],
cycles: Cycle,
}
@ -203,7 +205,7 @@ impl Default for Ppu {
pos: Default::default(),
stat: Default::default(),
vram: Box::new([0u8; VRAM_SIZE]),
oam: Box::new([0u8; OAM_SIZE]),
oam: Default::default(),
cycles: 0.into(),
frame_buf: [0; GB_WIDTH * GB_HEIGHT * 4],
}
@ -592,3 +594,134 @@ impl Pixels {
(higher & 0x01) << 1 | lower & 0x01
}
}
#[derive(Debug, Clone)]
pub struct SpriteAttributeTable {
buf: Box<[u8; OAM_SIZE]>,
}
impl SpriteAttributeTable {
pub fn read_byte(&self, addr: u16) -> u8 {
let index = (addr - 0xFE00) as usize;
self.buf[index]
}
pub fn write_byte(&mut self, addr: u16, byte: u8) {
let index = (addr - 0xFE00) as usize;
self.buf[index] = byte;
}
}
impl SpriteAttributeTable {
pub fn read_attribute(&self, addr: u16) -> SpriteAttribute {
let buf_index = (addr - 0xFE00) as usize;
self.attribute(buf_index)
}
pub fn attribute(&self, index: usize) -> SpriteAttribute {
let bytes: [u8; 4] = self.buf[index..(index + 4)]
.try_into()
.expect("Byte slice was not four bytes in length");
bytes.into()
}
}
impl Default for SpriteAttributeTable {
fn default() -> Self {
Self {
buf: Box::new([0; OAM_SIZE]),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct SpriteAttribute {
x: u8,
y: u8,
tile_index: u8,
attributes: SpriteFlag,
}
impl From<[u8; 4]> for SpriteAttribute {
fn from(bytes: [u8; 4]) -> Self {
Self {
x: bytes[0],
y: bytes[1],
tile_index: bytes[2],
attributes: bytes[3].into(),
}
}
}
bitfield! {
pub struct SpriteFlag(u8);
impl Debug;
bg_window_over_obj, set_bg_window_over_obj: 7;
from into SpriteFlip, y_flip, set_y_flip: 6, 6;
from into SpriteFlip, x_flit, set_x_flip: 5, 5;
from into BgPaletteNumber, palette, set_palette: 4, 4;
}
impl Copy for SpriteFlag {}
impl Clone for SpriteFlag {
fn clone(&self) -> Self {
*self
}
}
impl From<u8> for SpriteFlag {
fn from(byte: u8) -> Self {
Self(byte)
}
}
impl From<SpriteFlag> for u8 {
fn from(flags: SpriteFlag) -> Self {
flags.0
}
}
#[derive(Debug, Clone, Copy)]
pub enum SpriteFlip {
Normal = 0,
HorizontalMirror = 1,
}
impl From<u8> for SpriteFlip {
fn from(byte: u8) -> Self {
match byte {
0b00 => SpriteFlip::Normal,
0b01 => SpriteFlip::HorizontalMirror,
_ => unreachable!("{:#04X} is not a valid value for SpriteFlip", byte),
}
}
}
impl From<SpriteFlip> for u8 {
fn from(flip: SpriteFlip) -> Self {
flip as u8
}
}
#[derive(Debug, Clone, Copy)]
pub enum BgPaletteNumber {
BgPalette0 = 0,
BgPalette1 = 1,
}
impl From<u8> for BgPaletteNumber {
fn from(byte: u8) -> Self {
match byte {
0b00 => BgPaletteNumber::BgPalette0,
0b01 => BgPaletteNumber::BgPalette1,
_ => unreachable!("{:#04X} is not a valid value for BgPaletteNumber", byte),
}
}
}
impl From<BgPaletteNumber> for u8 {
fn from(flip: BgPaletteNumber) -> Self {
flip as u8
}
}