mirror of
https://github.com/FranLMSP/snes.git
synced 2026-08-03 08:30:01 -04:00
WIP PPU registers and background rendering
This commit is contained in:
@@ -4,8 +4,8 @@ use crate::rom::ROM;
|
||||
use crate::rom::lo_rom::LoROM;
|
||||
|
||||
pub struct Emulator {
|
||||
cpu: CPU,
|
||||
bus: Bus,
|
||||
pub cpu: CPU,
|
||||
pub bus: Bus,
|
||||
pub rom: Box<dyn ROM>,
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,56 @@ pub const WOBJLOG: u16 = 0x212B; // Window 2 Mask Logic (W)
|
||||
pub const TMW: u16 = 0x212E; // Window Area Main Screen Disable (W)
|
||||
pub const TSW: u16 = 0x212F; // Window Area Sub Screen Disable (W)
|
||||
|
||||
|
||||
pub const MAX_BG_WIDTH: usize = 16 * 64;
|
||||
pub const MAX_BG_HEIGHT: usize = 16 * 64;
|
||||
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
pub enum TileSize {
|
||||
P8x8,
|
||||
P16x16,
|
||||
P16x8,
|
||||
}
|
||||
|
||||
impl TileSize {
|
||||
pub fn to_usize(&self) -> (usize, usize) {
|
||||
match self {
|
||||
Self::P8x8 => (8, 8),
|
||||
Self::P16x16 => (16, 16),
|
||||
Self::P16x8 => (16, 8),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
pub enum BgSize {
|
||||
T32x32,
|
||||
T64x32, // V Mirror
|
||||
T32x64, // H Mirror
|
||||
T64x64, // H Mirror
|
||||
}
|
||||
|
||||
impl BgSize {
|
||||
pub fn to_usize(&self) -> (usize, usize) {
|
||||
match self {
|
||||
Self::T32x32 => (32, 32),
|
||||
Self::T64x32 => (64, 32),
|
||||
Self::T32x64 => (32, 64),
|
||||
Self::T64x64 => (64, 64),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum Background {
|
||||
Bg1,
|
||||
Bg2,
|
||||
Bg3,
|
||||
Bg4,
|
||||
}
|
||||
|
||||
|
||||
pub struct PPURegisters {
|
||||
data: [u8; 256],
|
||||
}
|
||||
@@ -78,4 +128,63 @@ impl PPURegisters {
|
||||
pub fn write(&mut self, address: u16, value: u8) {
|
||||
self.data[(address as usize) - 0x2100] = value;
|
||||
}
|
||||
|
||||
|
||||
/// 7 BG4 Tile Size (0=8x8, 1=16x16) ;\(BgMode0..4: variable 8x8 or 16x16)
|
||||
/// 6 BG3 Tile Size (0=8x8, 1=16x16) ; (BgMode5: 8x8 acts as 16x8)
|
||||
/// 5 BG2 Tile Size (0=8x8, 1=16x16) ; (BgMode6: fixed 16x8?)
|
||||
/// 4 BG1 Tile Size (0=8x8, 1=16x16) ;/(BgMode7: fixed 8x8)
|
||||
/// 3 BG3 Priority in Mode 1 (0=Normal, 1=High)
|
||||
/// 2-0 BG Screen Mode (0..7 = see below)
|
||||
pub fn get_bg_tile_size(&self, background: Background) -> TileSize {
|
||||
let byte = self.read(BGMODE);
|
||||
let bit = match background {
|
||||
Background::Bg1 => byte >> 3 & 0b1 == 1, // Bit 4
|
||||
Background::Bg2 => byte >> 4 & 0b1 == 1, // Bit 5
|
||||
Background::Bg3 => byte >> 5 & 0b1 == 1, // Bit 6
|
||||
Background::Bg4 => byte >> 6 & 0b1 == 1, // Bit 7
|
||||
};
|
||||
match bit {
|
||||
true => TileSize::P16x16,
|
||||
false => TileSize::P8x8,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_bg_size(&self, background: Background) -> BgSize {
|
||||
let byte = match background {
|
||||
Background::Bg1 => self.read(BG1SC),
|
||||
Background::Bg2 => self.read(BG2SC),
|
||||
Background::Bg3 => self.read(BG3SC),
|
||||
Background::Bg4 => self.read(BG4SC),
|
||||
};
|
||||
match byte & 0b11 {
|
||||
0 => BgSize::T32x32,
|
||||
1 => BgSize::T64x32,
|
||||
2 => BgSize::T32x64,
|
||||
3 => BgSize::T64x64,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod ppu_registers_test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_get_bg_tile_size() {
|
||||
let mut registers = PPURegisters::new();
|
||||
registers.write(BGMODE, 0b00000100);
|
||||
assert_eq!(registers.get_bg_tile_size(Background::Bg1), TileSize::P8x8);
|
||||
registers.write(BGMODE, 0b00001100);
|
||||
assert_eq!(registers.get_bg_tile_size(Background::Bg1), TileSize::P16x16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_bg_size() {
|
||||
let mut registers = PPURegisters::new();
|
||||
registers.write(BG1SC, 2);
|
||||
assert_eq!(registers.get_bg_size(Background::Bg1), BgSize::T32x64);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user