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 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 93 insertions(+), 81 deletions(-) (limited to 'src/memory.rs') 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) + }, } } } -- cgit v1.2.3-70-g09d2