From df6acf714c3ea975e75057b8b5a1d5e0fdf83109 Mon Sep 17 00:00:00 2001 From: Determinant Date: Thu, 4 Jan 2018 18:30:00 +0800 Subject: optimize CPU/PPU memory access --- src/memory.rs | 174 +++++++++++++++++++++++++++++++--------------------------- src/ppu.rs | 12 ++-- 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(); -- cgit v1.2.3