feat(ppu): stub sprite attribute table
This commit is contained in:
parent
23de87e482
commit
770b081f98
15
src/bus.rs
15
src/bus.rs
|
@ -126,7 +126,7 @@ impl Bus {
|
||||||
}
|
}
|
||||||
0xFE00..=0xFE9F => {
|
0xFE00..=0xFE9F => {
|
||||||
// Sprite Attribute Table
|
// Sprite Attribute Table
|
||||||
unimplemented!("Unable to read {:#06X} in the Sprite Attribute Table", addr);
|
self.ppu.oam.read_byte(addr)
|
||||||
}
|
}
|
||||||
0xFEA0..=0xFEFF => {
|
0xFEA0..=0xFEFF => {
|
||||||
eprintln!("Read from {:#06X}, which is prohibited", addr);
|
eprintln!("Read from {:#06X}, which is prohibited", addr);
|
||||||
|
@ -161,10 +161,8 @@ impl Bus {
|
||||||
0xFF49 => self.ppu.monochrome.obj_palette_1.into(),
|
0xFF49 => self.ppu.monochrome.obj_palette_1.into(),
|
||||||
0xFF4A => self.ppu.pos.window_y,
|
0xFF4A => self.ppu.pos.window_y,
|
||||||
0xFF4B => self.ppu.pos.window_x,
|
0xFF4B => self.ppu.pos.window_x,
|
||||||
0xFF4D => {
|
0xFF4D => 0x00, // Reading from this address is useful on the CGB only
|
||||||
// Reading from this address is useful on the CGB only
|
0xFF7F => 0x00, // Don't think this address is used for anything
|
||||||
0x00
|
|
||||||
}
|
|
||||||
_ => unimplemented!("Unable to read {:#06X} in I/O Registers", addr),
|
_ => unimplemented!("Unable to read {:#06X} in I/O Registers", addr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,7 +230,7 @@ impl Bus {
|
||||||
}
|
}
|
||||||
0xFE00..=0xFE9F => {
|
0xFE00..=0xFE9F => {
|
||||||
// Sprite Attribute Table
|
// Sprite Attribute Table
|
||||||
unimplemented!("Unable to write to {:#06X} in Sprite Attribute Table", addr);
|
self.ppu.oam.write_byte(addr, byte);
|
||||||
}
|
}
|
||||||
0xFEA0..=0xFEFF => {
|
0xFEA0..=0xFEFF => {
|
||||||
eprintln!("Wrote {:#04X} to {:#06X}, which is prohibited", byte, addr);
|
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(),
|
0xFF49 => self.ppu.monochrome.obj_palette_1 = byte.into(),
|
||||||
0xFF4A => self.ppu.pos.window_y = byte,
|
0xFF4A => self.ppu.pos.window_y = byte,
|
||||||
0xFF4B => self.ppu.pos.window_x = byte,
|
0xFF4B => self.ppu.pos.window_x = byte,
|
||||||
0xFF4D => {
|
0xFF4D => {} // Writing to this address is useful on the CGB only
|
||||||
// Writing to this address is useful on the CGB only
|
|
||||||
}
|
|
||||||
0xFF50 => {
|
0xFF50 => {
|
||||||
// Disable Boot ROM
|
// Disable Boot ROM
|
||||||
if byte != 0 {
|
if byte != 0 {
|
||||||
self.boot = None;
|
self.boot = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
0xFF7F => {} // Don't think this address is used for anything
|
||||||
_ => unimplemented!("Unable to write to {:#06X} in I/O Registers", addr),
|
_ => unimplemented!("Unable to write to {:#06X} in I/O Registers", addr),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
143
src/ppu.rs
143
src/ppu.rs
|
@ -1,10 +1,12 @@
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
use crate::Cycle;
|
use crate::Cycle;
|
||||||
use crate::GB_HEIGHT;
|
use crate::GB_HEIGHT;
|
||||||
use crate::GB_WIDTH;
|
use crate::GB_WIDTH;
|
||||||
use bitfield::bitfield;
|
use bitfield::bitfield;
|
||||||
|
|
||||||
const VRAM_SIZE: usize = 8192;
|
const VRAM_SIZE: usize = 0x2000;
|
||||||
const OAM_SIZE: usize = 160;
|
const OAM_SIZE: usize = 0xA0;
|
||||||
const PPU_START_ADDRESS: usize = 0x8000;
|
const PPU_START_ADDRESS: usize = 0x8000;
|
||||||
|
|
||||||
const WHITE: [u8; 4] = [0xFF, 0xFF, 0xFF, 0xFF];
|
const WHITE: [u8; 4] = [0xFF, 0xFF, 0xFF, 0xFF];
|
||||||
|
@ -19,9 +21,9 @@ pub struct Ppu {
|
||||||
pub monochrome: Monochrome,
|
pub monochrome: Monochrome,
|
||||||
pub pos: ScreenPosition,
|
pub pos: ScreenPosition,
|
||||||
pub vram: Box<[u8; VRAM_SIZE]>,
|
pub vram: Box<[u8; VRAM_SIZE]>,
|
||||||
pub oam: Box<[u8; OAM_SIZE]>,
|
|
||||||
frame_buf: [u8; GB_WIDTH * GB_HEIGHT * 4],
|
|
||||||
pub stat: LCDStatus,
|
pub stat: LCDStatus,
|
||||||
|
pub oam: SpriteAttributeTable,
|
||||||
|
frame_buf: [u8; GB_WIDTH * GB_HEIGHT * 4],
|
||||||
cycles: Cycle,
|
cycles: Cycle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +205,7 @@ impl Default for Ppu {
|
||||||
pos: Default::default(),
|
pos: Default::default(),
|
||||||
stat: Default::default(),
|
stat: Default::default(),
|
||||||
vram: Box::new([0u8; VRAM_SIZE]),
|
vram: Box::new([0u8; VRAM_SIZE]),
|
||||||
oam: Box::new([0u8; OAM_SIZE]),
|
oam: Default::default(),
|
||||||
cycles: 0.into(),
|
cycles: 0.into(),
|
||||||
frame_buf: [0; GB_WIDTH * GB_HEIGHT * 4],
|
frame_buf: [0; GB_WIDTH * GB_HEIGHT * 4],
|
||||||
}
|
}
|
||||||
|
@ -592,3 +594,134 @@ impl Pixels {
|
||||||
(higher & 0x01) << 1 | lower & 0x01
|
(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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue