mirror of
https://github.com/FranLMSP/snes.git
synced 2026-01-01 07:21:35 -05:00
WIP vblank nmi
This commit is contained in:
@@ -49,7 +49,7 @@ impl Bus {
|
||||
0x0000..=0x1FFF => MemoryMap::WRAM,
|
||||
0x2100..=0x21FF => MemoryMap::PPU,
|
||||
0x4016..=0x4017 => MemoryMap::Joypad,
|
||||
0x4200..=0x43FF => MemoryMap::CPU,
|
||||
0x4200..=0x420F => MemoryMap::CPU,
|
||||
_ => MemoryMap::Cartridge,
|
||||
},
|
||||
_ => MemoryMap::Cartridge,
|
||||
@@ -61,7 +61,10 @@ impl Bus {
|
||||
match section {
|
||||
MemoryMap::WRAM => self.read_wram(address),
|
||||
MemoryMap::PPU => self.ppu.registers.read(address as u16),
|
||||
MemoryMap::CPU => self.internal_registers.read(address as u16),
|
||||
MemoryMap::CPU => self.internal_registers.read(
|
||||
address as u16,
|
||||
&self.ppu.registers,
|
||||
),
|
||||
MemoryMap::Joypad => 0x00, // TODO: Placeholder
|
||||
MemoryMap::Cartridge => self.rom.read(address),
|
||||
}
|
||||
|
||||
@@ -1,24 +1,62 @@
|
||||
use crate::ppu::registers::PPURegisters;
|
||||
use crate::ppu::registers::{
|
||||
RDNMI
|
||||
};
|
||||
|
||||
pub const INTERNAL_REGISTERS_ADDRESS: u16 = 0x4200;
|
||||
|
||||
pub struct InternalRegisters {
|
||||
_registers: [u8; 32],
|
||||
registers: [u8; 32],
|
||||
}
|
||||
|
||||
impl InternalRegisters {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
_registers: [0; 32],
|
||||
registers: [0; 32],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&self, _address: u16) -> u8 {
|
||||
// TODO: Placeholder
|
||||
// self.registers[(address - INTERNAL_REGISTERS_ADDRESS) as usize]
|
||||
0x00
|
||||
fn _read(&self, address: u16) -> u8 {
|
||||
self.registers[(address - INTERNAL_REGISTERS_ADDRESS) as usize]
|
||||
}
|
||||
|
||||
pub fn write(&mut self, _address: u16, _value: u8) {
|
||||
// TODO: Placeholder
|
||||
// self.registers[(address - INTERNAL_REGISTERS_ADDRESS) as usize] = value;
|
||||
fn _write(&mut self, address: u16, value: u8) {
|
||||
self.registers[(address - INTERNAL_REGISTERS_ADDRESS) as usize] = value
|
||||
}
|
||||
|
||||
pub fn read(&self, address: u16, ppu_registers: &PPURegisters) -> u8 {
|
||||
match address {
|
||||
RDNMI => self.read_vblank_nmi(ppu_registers),
|
||||
_ => self._read(address),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&mut self, address: u16, value: u8) {
|
||||
self._write(address, value);
|
||||
}
|
||||
|
||||
fn read_vblank_nmi(&self, ppu_registers: &PPURegisters) -> u8 {
|
||||
let byte = self._read(RDNMI);
|
||||
// TODO: when this register is read, bit 7 is cleared
|
||||
(byte & 0x7F) | ((ppu_registers.is_vblanking() as u8) << 7)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod ppu_general_test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_read_vblank_nmi() {
|
||||
let registers = InternalRegisters::new();
|
||||
let mut ppu_registers = PPURegisters::new();
|
||||
ppu_registers.h_count = 20;
|
||||
assert_eq!(registers.read_vblank_nmi(&ppu_registers), 0x00);
|
||||
ppu_registers.h_count = 300;
|
||||
assert_eq!(registers.read_vblank_nmi(&ppu_registers), 0x80);
|
||||
// TODO: reset vblank bit after read
|
||||
// ppu_registers.h_count = 300;
|
||||
// assert_eq!(registers.read_vblank_nmi(&ppu_registers), 0x00);
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,6 @@ use super::registers::PPURegisters;
|
||||
|
||||
pub struct PPU {
|
||||
framebuffer: Vec<u8>,
|
||||
h_count: u16,
|
||||
v_count: u16,
|
||||
pub registers: PPURegisters,
|
||||
}
|
||||
|
||||
@@ -11,8 +9,6 @@ impl PPU {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
framebuffer: vec![],
|
||||
h_count: 0,
|
||||
v_count: 0,
|
||||
registers: PPURegisters::new(),
|
||||
}
|
||||
}
|
||||
@@ -28,12 +24,12 @@ impl PPU {
|
||||
}
|
||||
|
||||
fn increment_hv_count(&mut self) {
|
||||
self.h_count += 1;
|
||||
if self.h_count > 339 {
|
||||
self.h_count = 0;
|
||||
self.v_count += 1;
|
||||
if self.v_count > 261 {
|
||||
self.v_count = 0;
|
||||
self.registers.h_count += 1;
|
||||
if self.registers.h_count > 339 {
|
||||
self.registers.h_count = 0;
|
||||
self.registers.v_count += 1;
|
||||
if self.registers.v_count > 261 {
|
||||
self.registers.v_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,17 +48,17 @@ mod ppu_general_test {
|
||||
fn test_increment_hv_count() {
|
||||
let mut ppu = PPU::new();
|
||||
ppu.increment_hv_count();
|
||||
assert_eq!(ppu.h_count, 1);
|
||||
assert_eq!(ppu.registers.h_count, 1);
|
||||
|
||||
ppu.h_count = 339;
|
||||
ppu.registers.h_count = 339;
|
||||
ppu.increment_hv_count();
|
||||
assert_eq!(ppu.h_count, 0);
|
||||
assert_eq!(ppu.v_count, 1);
|
||||
assert_eq!(ppu.registers.h_count, 0);
|
||||
assert_eq!(ppu.registers.v_count, 1);
|
||||
|
||||
ppu.h_count = 339;
|
||||
ppu.v_count = 261;
|
||||
ppu.registers.h_count = 339;
|
||||
ppu.registers.v_count = 261;
|
||||
ppu.increment_hv_count();
|
||||
assert_eq!(ppu.h_count, 0);
|
||||
assert_eq!(ppu.v_count, 0);
|
||||
assert_eq!(ppu.registers.h_count, 0);
|
||||
assert_eq!(ppu.registers.v_count, 0);
|
||||
}
|
||||
}
|
||||
@@ -114,12 +114,16 @@ pub enum Background {
|
||||
|
||||
pub struct PPURegisters {
|
||||
data: [u8; 256],
|
||||
pub h_count: u16,
|
||||
pub v_count: u16,
|
||||
}
|
||||
|
||||
impl PPURegisters {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
data: [0x00; 256],
|
||||
h_count: 0,
|
||||
v_count: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,6 +171,13 @@ impl PPURegisters {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_vblanking(&self) -> bool {
|
||||
if self.h_count >= 1 && self.h_count <= 224 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -189,4 +200,21 @@ mod ppu_registers_test {
|
||||
registers.write(BG1SC, 2);
|
||||
assert_eq!(registers.get_bg_size(Background::Bg1), BgSize::T32x64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_vblanking() {
|
||||
let mut registers = PPURegisters::new();
|
||||
registers.h_count = 339;
|
||||
assert_eq!(registers.is_vblanking(), true);
|
||||
registers.h_count = 0;
|
||||
assert_eq!(registers.is_vblanking(), true);
|
||||
registers.h_count = 225;
|
||||
assert_eq!(registers.is_vblanking(), true);
|
||||
registers.h_count = 224;
|
||||
assert_eq!(registers.is_vblanking(), false);
|
||||
registers.h_count = 2;
|
||||
assert_eq!(registers.is_vblanking(), false);
|
||||
registers.h_count = 50;
|
||||
assert_eq!(registers.is_vblanking(), false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user