chore: improve performance of match statements

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-05-19 02:52:32 -05:00
parent e89e89df5b
commit 9ea26d4a05
7 changed files with 99 additions and 89 deletions

View File

@ -113,15 +113,15 @@ impl Bus {
self.var_ram.read_byte(addr)
}
0xE000..=0xFDFF => {
// Mirror of 0xC000 to 0xDDFF
// ECHO RAM
match addr {
0xE000..=0xEFFF => {
// Mirror of 0xC000 to 0xDDFF (ECHO RAM)
match addr & 0x1FFF {
// 0xE000 ..= 0xEFFF
0x0000..=0x0FFF => {
// 4KB Work RAM Bank 0
self.work_ram.read_byte(addr)
}
0xF000..=0xFDFF => {
// 0xF000 ..= 0xFDFF
0x1000..=0x1DFF => {
// 4KB Work RAM Bank 1 -> N
self.var_ram.read_byte(addr)
}
@ -139,33 +139,36 @@ impl Bus {
}
0xFF00..=0xFF7F => {
// IO Registers
match addr {
0xFF00 => self.joypad.status.into(),
0xFF01 => self.serial.next,
0xFF02 => self.serial.control.into(),
0xFF04 => (self.timer.divider >> 8) as u8,
0xFF05 => self.timer.counter,
0xFF06 => self.timer.modulo,
0xFF07 => self.timer.control.into(),
0xFF0F => self.interrupt_flag().into(),
0xFF11 => self.sound.ch1.sound_duty.into(),
0xFF12 => self.sound.ch1.vol_envelope.into(),
0xFF14 => self.sound.ch1.freq_hi.into(),
0xFF24 => self.sound.control.channel.into(),
0xFF25 => self.sound.control.output.into(),
0xFF26 => self.sound.control.status.into(),
0xFF40 => self.ppu.control.into(),
0xFF41 => self.ppu.stat.into(),
0xFF42 => self.ppu.pos.scroll_y,
0xFF43 => self.ppu.pos.scroll_x,
0xFF44 => self.ppu.pos.line_y,
0xFF45 => self.ppu.pos.ly_compare as u8,
0xFF47 => self.ppu.monochrome.bg_palette.into(),
0xFF48 => self.ppu.monochrome.obj_palette_0.into(),
0xFF49 => self.ppu.monochrome.obj_palette_1.into(),
0xFF4A => self.ppu.pos.window_y,
0xFF4B => self.ppu.pos.window_x,
0xFF4D => 0x00, // Reading from this address is useful on the CGB only
// Every address here starts with 0xFF so we can just check the
// low byte to figure out which register it is
match addr & 0x00FF {
0x00 => self.joypad.status.into(),
0x01 => self.serial.next,
0x02 => self.serial.control.into(),
0x04 => (self.timer.divider >> 8) as u8,
0x05 => self.timer.counter,
0x06 => self.timer.modulo,
0x07 => self.timer.control.into(),
0x0F => self.interrupt_flag().into(),
0x11 => self.sound.ch1.sound_duty.into(),
0x12 => self.sound.ch1.vol_envelope.into(),
0x14 => self.sound.ch1.freq_hi.into(),
0x24 => self.sound.control.channel.into(),
0x25 => self.sound.control.output.into(),
0x26 => self.sound.control.status.into(),
0x40 => self.ppu.control.into(),
0x41 => self.ppu.stat.into(),
0x42 => self.ppu.pos.scroll_y,
0x43 => self.ppu.pos.scroll_x,
0x44 => self.ppu.pos.line_y,
0x45 => self.ppu.pos.ly_compare as u8,
0x47 => self.ppu.monochrome.bg_palette.into(),
0x48 => self.ppu.monochrome.obj_palette_0.into(),
0x49 => self.ppu.monochrome.obj_palette_1.into(),
0x4A => self.ppu.pos.window_y,
0x4B => self.ppu.pos.window_x,
0x4D => 0x00, // Reading from this address is useful on the CGB only
_ => unimplemented!("Unable to read {:#06X} in I/O Registers", addr),
}
}
@ -216,15 +219,15 @@ impl Bus {
self.var_ram.write_byte(addr, byte);
}
0xE000..=0xFDFF => {
// Mirror of 0xC000 to 0xDDFF
// ECHO RAM
match addr {
0xE000..=0xEFFF => {
// Mirror of 0xC000 to 0xDDFF (ECHO RAM)
match addr & 0x1FFF {
// 0xE000 ..= 0xEFFF
0x0000..=0x0FFF => {
// 4KB Work RAM Bank 0
self.work_ram.write_byte(addr, byte);
}
0xF000..=0xFDFF => {
// 0xF000 ..= 0xFDFF
0x1000..=0x1DFF => {
// 4KB Work RAM Bank 1 -> N
self.var_ram.write_byte(addr, byte);
}
@ -241,28 +244,31 @@ impl Bus {
}
0xFF00..=0xFF7F => {
// IO Registers
match addr {
0xFF00 => self.joypad.status.update(byte),
0xFF01 => self.serial.next = byte,
0xFF02 => self.serial.control = byte.into(),
0xFF04 => self.timer.divider = 0x0000,
0xFF05 => self.timer.counter = byte,
0xFF06 => self.timer.modulo = byte,
0xFF07 => self.timer.control = byte.into(),
0xFF0F => self.set_interrupt_flag(byte),
0xFF11 => self.sound.ch1.sound_duty = byte.into(),
0xFF12 => self.sound.ch1.vol_envelope = byte.into(),
0xFF13 => self.sound.ch1.freq_lo = byte.into(),
0xFF14 => self.sound.ch1.freq_hi = byte.into(),
0xFF24 => self.sound.control.channel = byte.into(),
0xFF25 => self.sound.control.output = byte.into(),
0xFF26 => self.sound.control.status = byte.into(), // FIXME: Should we control which bytes are written to here?
0xFF40 => self.ppu.control = byte.into(),
0xFF41 => self.ppu.stat.update(byte),
0xFF42 => self.ppu.pos.scroll_y = byte,
0xFF43 => self.ppu.pos.scroll_x = byte,
0xFF44 => self.ppu.pos.line_y = byte,
0xFF45 => {
// Every address here starts with 0xFF so we can just check the
// low byte to figure out which register it is
match addr & 0x00FF {
0x00 => self.joypad.status.update(byte),
0x01 => self.serial.next = byte,
0x02 => self.serial.control = byte.into(),
0x04 => self.timer.divider = 0x0000,
0x05 => self.timer.counter = byte,
0x06 => self.timer.modulo = byte,
0x07 => self.timer.control = byte.into(),
0x0F => self.set_interrupt_flag(byte),
0x11 => self.sound.ch1.sound_duty = byte.into(),
0x12 => self.sound.ch1.vol_envelope = byte.into(),
0x13 => self.sound.ch1.freq_lo = byte.into(),
0x14 => self.sound.ch1.freq_hi = byte.into(),
0x24 => self.sound.control.channel = byte.into(),
0x25 => self.sound.control.output = byte.into(),
0x26 => self.sound.control.status = byte.into(), // FIXME: Should we control which bytes are written to here?
0x40 => self.ppu.control = byte.into(),
0x41 => self.ppu.stat.update(byte),
0x42 => self.ppu.pos.scroll_y = byte,
0x43 => self.ppu.pos.scroll_x = byte,
0x44 => self.ppu.pos.line_y = byte,
0x45 => {
// Update LYC
self.ppu.pos.ly_compare = byte;
@ -275,13 +281,13 @@ impl Bus {
self.ppu.int.set_lcd_stat(true);
}
}
0xFF47 => self.ppu.monochrome.bg_palette = byte.into(),
0xFF48 => self.ppu.monochrome.obj_palette_0 = byte.into(),
0xFF49 => self.ppu.monochrome.obj_palette_1 = byte.into(),
0xFF4A => self.ppu.pos.window_y = byte,
0xFF4B => self.ppu.pos.window_x = byte,
0xFF4D => {} // Writing to this address is useful on the CGB only
0xFF50 => {
0x47 => self.ppu.monochrome.bg_palette = byte.into(),
0x48 => self.ppu.monochrome.obj_palette_0 = byte.into(),
0x49 => self.ppu.monochrome.obj_palette_1 = byte.into(),
0x4A => self.ppu.pos.window_y = byte,
0x4B => self.ppu.pos.window_x = byte,
0x4D => {} // Writing to this address is useful on the CGB only
0x50 => {
// Disable Boot ROM
if byte != 0 {
self.boot = None;

View File

@ -88,9 +88,11 @@ impl Cartridge {
impl Cartridge {
pub fn read_byte(&self, addr: u16) -> u8 {
use MbcResult::*;
match self.mbc.handle_read(addr) {
MbcResult::Address(addr) => self.memory[addr as usize],
MbcResult::Value(byte) => byte,
Address(addr) => self.memory[addr as usize],
Value(byte) => byte,
}
}
pub fn write_byte(&mut self, addr: u16, byte: u8) {
@ -166,12 +168,14 @@ impl Mbc1 {
}
fn calc_ram_address(&self, addr: u16) -> u16 {
use RamSize::*;
match self.ram_size {
RamSize::_2KB | RamSize::_8KB => {
_2KB | _8KB => {
let ram_size = self.ram_size.as_byte_count() as u16;
(addr - 0xA000) % ram_size
}
RamSize::_32KB => {
_32KB => {
if self.mode {
0x2000 * self.ram_bank as u16 + (addr - 0xA000)
} else {

View File

@ -98,7 +98,7 @@ pub enum ButtonState {
impl From<u8> for ButtonState {
fn from(byte: u8) -> Self {
match byte {
match byte & 0b01 {
0b00 => Self::Pressed,
0b01 => Self::Released,
_ => unreachable!("{:#04X} is not a valid value for ButtonStatus", byte),
@ -129,7 +129,7 @@ enum RowState {
impl From<u8> for RowState {
fn from(byte: u8) -> Self {
match byte {
match byte & 0b01 {
0b00 => Self::Selected,
0b01 => Self::Deselected,
_ => unreachable!("{:#04X} is not a valid value for ButtonRowStatus", byte),

View File

@ -52,7 +52,7 @@ pub enum PpuMode {
impl From<u8> for PpuMode {
fn from(byte: u8) -> Self {
match byte {
match byte & 0b11 {
0b00 => Self::HBlank,
0b01 => Self::VBlank,
0b10 => Self::OamScan,
@ -129,7 +129,7 @@ impl TileMapAddress {
impl From<u8> for TileMapAddress {
fn from(byte: u8) -> Self {
match byte {
match byte & 0b01 {
0b00 => Self::X9800,
0b01 => Self::X9C00,
_ => unreachable!("{:#04X} is not a valid value for TileMapRegister", byte),
@ -157,7 +157,7 @@ pub enum TileDataAddress {
impl From<u8> for TileDataAddress {
fn from(byte: u8) -> Self {
match byte {
match byte & 0b01 {
0b00 => Self::X8800,
0b01 => Self::X8000,
_ => unreachable!("{:#04X} is not a valid value for TileDataRegister", byte),
@ -196,7 +196,7 @@ impl ObjectSize {
impl From<u8> for ObjectSize {
fn from(byte: u8) -> Self {
match byte {
match byte & 0b01 {
0b00 => Self::Eight,
0b01 => Self::Sixteen,
_ => unreachable!("{:#04X} is not a valid value for ObjSize", byte),
@ -227,7 +227,7 @@ bitfield! {
impl BackgroundPalette {
pub fn shade(&self, id: u8) -> GrayShade {
match id {
match id & 0b11 {
0b00 => self.i0_colour(),
0b01 => self.i1_colour(),
0b10 => self.i2_colour(),
@ -272,7 +272,7 @@ bitfield! {
impl ObjectPalette {
pub fn shade(&self, id: u8) -> Option<GrayShade> {
match id {
match id & 0b11 {
0b00 => None,
0b01 => Some(self.i1_colour()),
0b10 => Some(self.i2_colour()),
@ -376,7 +376,7 @@ pub enum ObjectPaletteId {
impl From<u8> for ObjectPaletteId {
fn from(byte: u8) -> Self {
match byte {
match byte & 0b01 {
0b00 => ObjectPaletteId::Zero,
0b01 => ObjectPaletteId::One,
_ => unreachable!("{:#04X} is not a valid value for BgPaletteNumber", byte),
@ -398,7 +398,7 @@ pub enum RenderPriority {
impl From<u8> for RenderPriority {
fn from(byte: u8) -> Self {
match byte {
match byte & 0b01 {
0b00 => Self::Object,
0b01 => Self::BackgroundAndWindow,
_ => unreachable!("{:#04X} is not a valid value for RenderPriority", byte),
@ -459,7 +459,7 @@ impl Default for GrayShade {
impl From<u8> for GrayShade {
fn from(byte: u8) -> Self {
match byte {
match byte & 0b11 {
0b00 => GrayShade::White,
0b01 => GrayShade::LightGray,
0b10 => GrayShade::DarkGray,

View File

@ -53,7 +53,7 @@ impl Default for ShiftClock {
impl From<u8> for ShiftClock {
fn from(byte: u8) -> Self {
match byte {
match byte & 0b01 {
0b00 => Self::External,
0b01 => Self::Internal,
_ => unreachable!("{:#04X} is not a valid value for ShiftClock", byte),
@ -75,7 +75,7 @@ impl Default for ClockSpeed {
impl From<u8> for ClockSpeed {
fn from(byte: u8) -> Self {
match byte {
match byte & 0b01 {
0b00 => Self::Normal,
0b01 => Self::Fast,
_ => unreachable!("{:#04X} is not a valid value for ClockSpeed", byte),

View File

@ -93,7 +93,7 @@ enum FrequencyType {
impl From<u8> for FrequencyType {
fn from(byte: u8) -> Self {
match byte {
match byte & 0b01 {
0b00 => Self::Counter,
0b01 => Self::Consecutive,
_ => unreachable!("{:#04X} is not a valid value for FrequencyType"),
@ -191,7 +191,7 @@ enum EnvelopeDirection {
impl From<u8> for EnvelopeDirection {
fn from(byte: u8) -> Self {
match byte {
match byte & 0b01 {
0b00 => Self::Decrease,
0b01 => Self::Increase,
_ => unreachable!("{:#04X} is not a valid value for EnvelopeDirection", byte),
@ -259,7 +259,7 @@ impl From<WavePattern> for u8 {
impl From<u8> for WavePattern {
fn from(byte: u8) -> Self {
match byte {
match byte & 0b11 {
0b00 => Self::OneEighth,
0b01 => Self::OneQuarter,
0b10 => Self::OneHalf,

View File

@ -84,7 +84,7 @@ pub enum TimerSpeed {
impl From<u8> for TimerSpeed {
fn from(byte: u8) -> Self {
match byte {
match byte & 0b11 {
0b00 => Self::Hz4096,
0b01 => Self::Hz262144,
0b10 => Self::Hz65536,