aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDeterminant <[email protected]>2017-11-14 22:36:54 -0500
committerDeterminant <[email protected]>2017-11-14 22:36:54 -0500
commitf960742a3de3723bb21d2ca0b98a2b3856dbd402 (patch)
treeb7d30f575fa6b99f1d40a9b64bd6b17a2640cf28 /src
parent372f447e6007146e6cfa34d0df7723d4586af249 (diff)
optimize ppu internal mem read
Diffstat (limited to 'src')
-rw-r--r--src/memory.rs67
-rw-r--r--src/ppu.rs31
2 files changed, 63 insertions, 35 deletions
diff --git a/src/memory.rs b/src/memory.rs
index b7ea2c0..6e7cc75 100644
--- a/src/memory.rs
+++ b/src/memory.rs
@@ -1,5 +1,5 @@
#![allow(dead_code)]
-use ppu::PPU;
+use ppu::{PPU, PMem};
use mos6502::CPU;
use cartridge::{MirrorType, Cartridge};
use core::cell::{UnsafeCell, Cell};
@@ -121,11 +121,10 @@ const MIRROR_IDX: [[u8; 4]; 5] = [
];
#[inline(always)]
-fn get_mirror_addr(kind: MirrorType, mut addr: u16) -> u16 {
- addr = (addr - 0x2000) & 0x0fff;
+fn get_mirror_addr(kind: MirrorType, addr: u16) -> u16 {
let table = addr >> 10;
let offset = addr & 0x03ff;
- 0x2000 + ((MIRROR_IDX[kind as usize][table as usize] as u16) << 10) + offset
+ ((MIRROR_IDX[kind as usize][table as usize] as u16) << 10) + offset
}
#[inline(always)]
@@ -135,22 +134,49 @@ fn get_mirror_palette(addr: u16) -> u16 {
} else { addr }
}
+impl<'a> PMem for PPUMemory<'a> {
+ #[inline(always)]
+ fn read_nametable(&self, addr: u16) -> u8 {
+ let kind = self.cart.mirror_type;
+ unsafe {(*self.nametable.get())[(get_mirror_addr(kind, addr) & 0x7ff) as usize]}
+ }
+
+ #[inline(always)]
+ fn read_palette(&self, addr: u16) -> u8 { unsafe {
+ (*self.palette.get())[get_mirror_palette(addr) as usize]
+ }}
+
+ #[inline(always)]
+ fn write_nametable(&self, addr: u16, data: u8) {
+ let kind = self.cart.mirror_type;
+ unsafe {(*self.nametable.get())[(get_mirror_addr(kind, addr) & 0x7ff) as usize] = data}
+ }
+
+ #[inline(always)]
+ fn write_palette(&self, addr: u16, data: u8) { unsafe {
+ (*self.palette.get())[get_mirror_palette(addr) as usize] = data;
+ }}
+
+ #[inline(always)]
+ fn read_mapper(&self, addr: u16) -> u8 {
+ self.mapper.read(addr)
+ }
+
+ #[inline(always)]
+ fn write_mapper(&self, addr: u16, data: u8) {
+ self.mapper.write(addr, data);
+ }
+}
+
impl<'a> VMem for PPUMemory<'a> {
fn read(&self, mut addr: u16) -> u8 {
addr &= 0x3fff;
if addr < 0x2000 {
- self.mapper.read(addr)
+ self.read_mapper(addr)
} else if addr < 0x3f00 {
- let kind = self.cart.mirror_type;
- unsafe {
- (*self.nametable.get())
- [(get_mirror_addr(kind, addr) & 0x07ff) as usize]
- }
+ self.read_nametable((addr - 0x2000) & 0xfff)
} else if addr < 0x4000 {
- unsafe {
- (*self.palette.get())
- [get_mirror_palette(addr & 0x1f) as usize]
- }
+ self.read_palette((addr - 0x3f00) & 0x1f)
} else {
panic!("invalid ppu read access at 0x{:04x}", addr)
}
@@ -159,18 +185,11 @@ impl<'a> VMem for PPUMemory<'a> {
fn write(&self, mut addr: u16, data: u8) {
addr &= 0x3fff;
if addr < 0x2000 {
- self.mapper.write(addr, data)
+ self.write_mapper(addr, data);
} else if addr < 0x3f00 {
- let kind = self.cart.mirror_type;
- unsafe {
- (*self.nametable.get())
- [(get_mirror_addr(kind, addr) & 0x07ff) as usize] = data;
- }
+ self.write_nametable((addr - 0x2000) & 0xfff, data);
} else if addr < 0x4000 {
- unsafe {
- (*self.palette.get())
- [get_mirror_palette(addr & 0x1f) as usize] = data;
- }
+ self.write_palette((addr - 0x3f00) & 0x1f, data);
} else {
panic!("invalid ppu write access at 0x{:04x}", addr)
}
diff --git a/src/ppu.rs b/src/ppu.rs
index 4759ddc..b317b9b 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -9,6 +9,15 @@ pub trait Screen {
fn render(&self);
}
+pub trait PMem: VMem {
+ fn read_nametable(&self, addr: u16) -> u8;
+ fn read_palette(&self, addr: u16) -> u8;
+ fn write_nametable(&self, addr: u16, data: u8);
+ fn write_palette(&self, addr: u16, data: u8);
+ fn read_mapper(&self, addr: u16) -> u8;
+ fn write_mapper(&self, addr: u16, data: u8);
+}
+
#[repr(C, packed)]
#[derive(Copy, Clone)]
struct Sprite {
@@ -51,7 +60,7 @@ pub struct PPU<'a> {
buffered_read: u8,
early_read: bool,
/* IO */
- mem: &'a VMem,
+ mem: &'a PMem,
scr: &'a Screen,
}
@@ -200,14 +209,14 @@ impl<'a> PPU<'a> {
#[inline(always)]
fn fetch_nametable_byte(&mut self) {
- self.bg_nt = self.mem.read(0x2000 | (self.v & 0x0fff));
+ self.bg_nt = self.mem.read_nametable(self.v & 0x0fff);
}
#[inline(always)]
fn fetch_attrtable_byte(&mut self) {
let v = self.v;
/* the byte representing 4x4 tiles */
- let b = self.mem.read(0x23c0 | (v & 0x0c00) |
+ let b = self.mem.read_nametable(0x03c0 | (v & 0x0c00) |
((v >> 4) & 0x38) | ((v >> 2) & 0x07));
self.bg_attr = (b >> ((v & 2) | ((v & 0x40) >> 4))) & 3;
}
@@ -215,7 +224,7 @@ impl<'a> PPU<'a> {
#[inline(always)]
fn fetch_low_bgtile_byte(&mut self) {
/* 0x?000 */
- self.bg_bit_low = self.mem.read(((self.ppuctl as u16 & 0x10) << 8) |
+ self.bg_bit_low = self.mem.read_mapper(((self.ppuctl as u16 & 0x10) << 8) |
/* 0x-??0 */
((self.bg_nt as u16) << 4) |
/* 0x---? (0 - 7) */
@@ -225,7 +234,7 @@ impl<'a> PPU<'a> {
#[inline(always)]
fn fetch_high_bgtile_byte(&mut self) {
/* 0x?000 */
- self.bg_bit_high = self.mem.read(((self.ppuctl as u16 & 0x10) << 8) |
+ self.bg_bit_high = self.mem.read_mapper(((self.ppuctl as u16 & 0x10) << 8) |
/* 0x-??0 */
((self.bg_nt as u16) << 4) |
/* 0x---? (8 - f) */
@@ -379,8 +388,8 @@ impl<'a> PPU<'a> {
};
self.sp_idx[i] = j;
self.sp_cnt[i] = s.x;
- let mut low = self.mem.read(ptable | ((tidx as u16) << 4) | 0x0 | y as u16);
- let mut high = self.mem.read(ptable | ((tidx as u16) << 4) | 0x8 | y as u16);
+ let mut low = self.mem.read_mapper(ptable | ((tidx as u16) << 4) | 0x0 | y as u16);
+ let mut high = self.mem.read_mapper(ptable | ((tidx as u16) << 4) | 0x8 | y as u16);
if (s.attr & 0x40) == 0x40 {
low = PPU::reverse_byte(low);
high = PPU::reverse_byte(high);
@@ -431,17 +440,17 @@ impl<'a> PPU<'a> {
assert!(self.scanline < 240);
self.scr.put((self.cycle - 1) as u8,
self.scanline as u8,
- self.mem.read(if (pri == 0 || bg_pidx == 0) && sp_pidx != 0 {
- 0x3f10 | sp
+ self.mem.read_palette(if (pri == 0 || bg_pidx == 0) && sp_pidx != 0 {
+ 0x0010 | sp
} else {
- 0x3f00 | match bg_pidx {
+ 0x0000 | match bg_pidx {
0 => 0,
_ => bg
}
}));
}
- pub fn new(mem: &'a VMem, scr: &'a Screen) -> Self {
+ pub fn new(mem: &'a PMem, scr: &'a Screen) -> Self {
let ppuctl = 0x00;
let ppumask = 0x00;
let ppustatus = 0xa0;