aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <[email protected]>2018-01-04 18:30:00 +0800
committerDeterminant <[email protected]>2018-01-04 18:30:00 +0800
commitdf6acf714c3ea975e75057b8b5a1d5e0fdf83109 (patch)
treec439741c5aa753bb3a56f8e5d9c0c4fa626bf5a1
parentb93b77d07d91bd2cd518005bce5cfd9a0622e9df (diff)
optimize CPU/PPU memory access
-rw-r--r--src/memory.rs174
-rw-r--r--src/ppu.rs12
2 files changed, 99 insertions, 87 deletions
diff --git a/src/memory.rs b/src/memory.rs
index 765aeb5..20adb39 100644
--- a/src/memory.rs
+++ b/src/memory.rs
@@ -112,32 +112,37 @@ impl<'a> CPUMemory<'a> {
pub fn read_without_tick(&self, addr: u16) -> u8 {
let cpu = self.bus.get_cpu();
let ppu = self.bus.get_ppu();
- if addr < 0x2000 {
- self.sram[(addr & 0x07ff) as usize]
- } else if addr < 0x4000 {
- match addr & 0x7 {
- 0x2 => {
- if ppu.cycle == 2 || ppu.cycle == 3 {
- cpu.suppress_nmi()
- } /* race condition when status is read near vbl/nmi */
- ppu.read_status()
- },
- 0x4 => ppu.read_oamdata(),
- 0x7 => ppu.read_data(),
- _ => 0
- }
- } else if addr < 0x4020 {
- let apu = self.bus.get_apu();
- match addr {
- 0x4015 => apu.read_status(),
- 0x4016 => if let Some(c) = self.ctl1 { c.read() } else { 0 },
- 0x4017 => if let Some(c) = self.ctl2 { c.read() } else { 0 },
- _ => 0
- }
- } else if addr < 0x6000 {
- 0
- } else {
- self.mapper.read(addr)
+ match addr >> 12 {
+ /* [0x0000..0x2000) */
+ 0 | 1 => self.sram[(addr & 0x07ff) as usize],
+ /* [0x2000..0x4000) */
+ 2 | 3 => {
+ match addr & 0x7 {
+ 0x2 => {
+ if ppu.cycle == 2 || ppu.cycle == 3 {
+ cpu.suppress_nmi()
+ } /* race condition when status is read near vbl/nmi */
+ ppu.read_status()
+ },
+ 0x4 => ppu.read_oamdata(),
+ 0x7 => ppu.read_data(),
+ _ => 0
+ }
+ },
+ /* [0x4000..0x5000) */
+ 4 => {
+ let apu = self.bus.get_apu();
+ match addr {
+ 0x4015 => apu.read_status(),
+ 0x4016 => if let Some(c) = self.ctl1 { c.read() } else { 0 },
+ 0x4017 => if let Some(c) = self.ctl2 { c.read() } else { 0 },
+ _ => 0
+ }
+ },
+ /* [0x5000..0x6000) */
+ 5 => 0,
+ /* [0x6000..0xffff) */
+ _ => self.mapper.read(addr)
}
}
@@ -145,10 +150,11 @@ impl<'a> CPUMemory<'a> {
pub fn write_without_tick(&mut self, addr: u16, data: u8) {
let cpu = self.bus.get_cpu();
let ppu = self.bus.get_ppu();
- if addr < 0x2000 {
- self.sram[(addr & 0x07ff) as usize] = data;
- } else if addr < 0x4000 {
- match addr & 0x7 {
+ match addr >> 12 {
+ /* [0x0000..0x2000) */
+ 0 | 1 => self.sram[(addr & 0x07ff) as usize] = data,
+ /* [0x2000..0x4000) */
+ 2 | 3 => match addr & 0x7 {
0x0 => {
let old = ppu.get_flag_nmi();
ppu.write_ctl(data);
@@ -165,42 +171,44 @@ impl<'a> CPUMemory<'a> {
0x4 => ppu.write_oamdata(data),
0x5 => ppu.write_scroll(data),
0x6 => ppu.write_addr(data),
- 0x7 => ppu.write_data(data),
- _ => panic!("invalid ppu reg write access at 0x{:04x}", addr)
- }
- } else if addr < 0x4020 {
- let apu = self.bus.get_apu();
- match addr {
- 0x4000 => apu.pulse1.write_reg1(data),
- 0x4001 => apu.pulse1.write_reg2(data),
- 0x4002 => apu.pulse1.write_reg3(data),
- 0x4003 => apu.pulse1.write_reg4(data),
- 0x4004 => apu.pulse2.write_reg1(data),
- 0x4005 => apu.pulse2.write_reg2(data),
- 0x4006 => apu.pulse2.write_reg3(data),
- 0x4007 => apu.pulse2.write_reg4(data),
- 0x4008 => apu.triangle.write_reg1(data),
- 0x400a => apu.triangle.write_reg3(data),
- 0x400b => apu.triangle.write_reg4(data),
- 0x400c => apu.noise.write_reg1(data),
- 0x400e => apu.noise.write_reg3(data),
- 0x400f => apu.noise.write_reg4(data),
- 0x4010 => apu.dmc.write_reg1(data),
- 0x4011 => apu.dmc.write_reg2(data),
- 0x4012 => apu.dmc.write_reg3(data),
- 0x4013 => apu.dmc.write_reg4(data),
- 0x4015 => apu.write_status(data),
- 0x4017 => apu.write_frame_counter(data),
- 0x4014 => ppu.write_oamdma(data, &self.bus),
- 0x4016 => {
- if let Some(c) = self.ctl1 { c.write(data) }
- if let Some(c) = self.ctl2 { c.write(data) }
+ _ => ppu.write_data(data),
+ },
+ /* [0x4000..0x5000) */
+ 4 => {
+ let apu = self.bus.get_apu();
+ match addr {
+ 0x4000 => apu.pulse1.write_reg1(data),
+ 0x4001 => apu.pulse1.write_reg2(data),
+ 0x4002 => apu.pulse1.write_reg3(data),
+ 0x4003 => apu.pulse1.write_reg4(data),
+ 0x4004 => apu.pulse2.write_reg1(data),
+ 0x4005 => apu.pulse2.write_reg2(data),
+ 0x4006 => apu.pulse2.write_reg3(data),
+ 0x4007 => apu.pulse2.write_reg4(data),
+ 0x4008 => apu.triangle.write_reg1(data),
+ 0x400a => apu.triangle.write_reg3(data),
+ 0x400b => apu.triangle.write_reg4(data),
+ 0x400c => apu.noise.write_reg1(data),
+ 0x400e => apu.noise.write_reg3(data),
+ 0x400f => apu.noise.write_reg4(data),
+ 0x4010 => apu.dmc.write_reg1(data),
+ 0x4011 => apu.dmc.write_reg2(data),
+ 0x4012 => apu.dmc.write_reg3(data),
+ 0x4013 => apu.dmc.write_reg4(data),
+ 0x4015 => apu.write_status(data),
+ 0x4017 => apu.write_frame_counter(data),
+ 0x4014 => ppu.write_oamdma(data, &self.bus),
+ 0x4016 => {
+ if let Some(c) = self.ctl1 { c.write(data) }
+ if let Some(c) = self.ctl2 { c.write(data) }
+ }
+ _ => ()
}
- _ => ()
- }
- } else if addr < 0x6000 {
- } else {
- self.mapper.get_mut().write(addr, data)
+ },
+ /* [0x5000..0x6000) */
+ 5 => (),
+ /* [0x6000..0xffff) */
+ _ => self.mapper.get_mut().write(addr, data)
}
}
}
@@ -296,27 +304,31 @@ impl<'a> PPUMemory<'a> {
impl<'a> VMem for PPUMemory<'a> {
fn read(&self, mut addr: u16) -> u8 {
addr &= 0x3fff;
- if addr < 0x2000 {
- self.read_mapper(addr)
- } else if addr < 0x3f00 {
- self.read_nametable((addr - 0x2000) & 0xfff)
- } else if addr < 0x4000 {
- self.read_palette((addr - 0x3f00) & 0x1f)
- } else {
- panic!("invalid ppu read access at 0x{:04x}", addr)
+ match addr >> 12 {
+ /* [0x0000..0x2000) */
+ 0 | 1 => self.read_mapper(addr),
+ /* [0x2000..0x3000) */
+ 2 => self.read_nametable((addr - 0x2000) & 0xfff),
+ /* [0x3000..0x4000) */
+ _ => match addr >> 8 {
+ 0x3f => self.read_palette((addr - 0x3f00) & 0x1f),
+ _ => self.read_nametable((addr - 0x2000) & 0xfff)
+ },
}
}
fn write(&mut self, mut addr: u16, data: u8) {
addr &= 0x3fff;
- if addr < 0x2000 {
- self.write_mapper(addr, data);
- } else if addr < 0x3f00 {
- self.write_nametable((addr - 0x2000) & 0xfff, data);
- } else if addr < 0x4000 {
- self.write_palette((addr - 0x3f00) & 0x1f, data);
- } else {
- panic!("invalid ppu write access at 0x{:04x}", addr)
+ match addr >> 12 {
+ /* [0x0000..0x2000) */
+ 0 | 1 => self.write_mapper(addr, data),
+ /* [0x2000..0x3000) */
+ 2 => self.write_nametable((addr - 0x2000) & 0xfff, data),
+ /* [0x3000..0x4000) */
+ _ => match addr >> 8 {
+ 0x3f => self.write_palette((addr - 0x3f00) & 0x1f, data),
+ _ => self.write_nametable((addr - 0x2000) & 0xfff, data)
+ },
}
}
}
diff --git a/src/ppu.rs b/src/ppu.rs
index 50303b6..7c516b6 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -243,7 +243,7 @@ impl<'a> PPU<'a> {
fn load_bgtile(&mut self) {
/* load the tile bitmap to high 8 bits of bitmap,
* assume the high 8 bits are zeros */
- assert!(self.bg_pixel >> 32 == 0);
+ debug_assert!(self.bg_pixel >> 32 == 0);
let mut t: u64 = 0;
let mut bl = self.bg_bit_low;
let mut bh = self.bg_bit_high;
@@ -505,15 +505,15 @@ impl<'a> PPU<'a> {
}
fn _tick(&mut self) -> bool {
- if self.scanline == 240 {
- self.vblank_lines = true
- } else if self.scanline == 261 {
- self.vblank_lines = false
- }
//self.elapsed += 1;
let cycle = self.cycle;
if cycle == 0 {
self.cycle = 1;
+ if self.scanline == 240 {
+ self.vblank_lines = true
+ } else if self.scanline == 261 {
+ self.vblank_lines = false
+ }
return false;
}
let rendering = self.get_show_bg() || self.get_show_sp();