direct reads of words / halfwords, improves fps ~25%

This commit is contained in:
Matthew Berry 2021-01-30 17:21:49 -08:00
parent 79ed746d6c
commit 190ce42ea6
4 changed files with 57 additions and 19 deletions

View file

@ -22,19 +22,40 @@ class Bus
when 0x7 then @gba.ppu.oam[index & 0x3FF] when 0x7 then @gba.ppu.oam[index & 0x3FF]
when 0x8, 0x9, when 0x8, 0x9,
0xA, 0xB, 0xA, 0xB,
0xC, 0xD then @gba.cartridge[index & 0x01FFFFFF] 0xC, 0xD then @gba.cartridge.rom[index & 0x01FFFFFF]
when 0xE then @gba.storage[index & 0xFFFF] when 0xE then @gba.storage[index & 0xFFFF]
else abort "Unmapped read: #{hex_str index.to_u32}" else abort "Unmapped read: #{hex_str index.to_u32}"
end end
end end
def read_half(index : Int) : Word def read_half_slow(index : Int) : HalfWord
self[index & ~1].to_u32 | self[index].to_u16 |
(self[(index & ~1) + 1].to_u32 << 8) (self[index + 1].to_u16 << 8)
end
def read_half(index : Int) : HalfWord
index &= ~1
case bits(index, 24..27)
when 0x0 then (@bios.to_unsafe + (index & 0x3FFF)).as(HalfWord*).value
when 0x2 then (@wram_board.to_unsafe + (index & 0x3FFFF)).as(HalfWord*).value
when 0x3 then (@wram_chip.to_unsafe + (index & 0x7FFF)).as(HalfWord*).value
when 0x4 then read_half_slow(index)
when 0x5 then (@gba.ppu.pram.to_unsafe + (index & 0x3FF)).as(HalfWord*).value
when 0x6
address = 0x1FFFF_u32 & index
address -= 0x8000 if address > 0x17FFF
(@gba.ppu.vram.to_unsafe + address).as(HalfWord*).value
when 0x7 then (@gba.ppu.oam.to_unsafe + (index & 0x3FF)).as(HalfWord*).value
when 0x8, 0x9,
0xA, 0xB,
0xC, 0xD then (@gba.cartridge.rom.to_unsafe + (index & 0x01FFFFFF)).as(HalfWord*).value
when 0xE then read_half_slow(index)
else abort "Unmapped read: #{hex_str index.to_u32}"
end
end end
def read_half_rotate(index : Int) : Word def read_half_rotate(index : Int) : Word
half = read_half index half = read_half(index).to_u32!
bits = (index & 1) << 3 bits = (index & 1) << 3
half >> bits | half << (32 - bits) half >> bits | half << (32 - bits)
end end
@ -50,11 +71,32 @@ class Bus
end end
end end
private def read_word_slow(index : Int) : Word
self[index].to_u32 |
(self[index + 1].to_u32 << 8) |
(self[index + 2].to_u32 << 16) |
(self[index + 3].to_u32 << 24)
end
def read_word(index : Int) : Word def read_word(index : Int) : Word
self[index & ~3].to_u32 | index &= ~3
(self[(index & ~3) + 1].to_u32 << 8) | case bits(index, 24..27)
(self[(index & ~3) + 2].to_u32 << 16) | when 0x0 then (@bios.to_unsafe + (index & 0x3FFF)).as(Word*).value
(self[(index & ~3) + 3].to_u32 << 24) when 0x2 then (@wram_board.to_unsafe + (index & 0x3FFFF)).as(Word*).value
when 0x3 then (@wram_chip.to_unsafe + (index & 0x7FFF)).as(Word*).value
when 0x4 then read_word_slow(index)
when 0x5 then (@gba.ppu.pram.to_unsafe + (index & 0x3FF)).as(Word*).value
when 0x6
address = 0x1FFFF_u32 & index
address -= 0x8000 if address > 0x17FFF
(@gba.ppu.vram.to_unsafe + address).as(Word*).value
when 0x7 then (@gba.ppu.oam.to_unsafe + (index & 0x3FF)).as(Word*).value
when 0x8, 0x9,
0xA, 0xB,
0xC, 0xD then (@gba.cartridge.rom.to_unsafe + (index & 0x01FFFFFF)).as(Word*).value
when 0xE then read_word_slow(index)
else abort "Unmapped read: #{hex_str index.to_u32}"
end
end end
def read_word_rotate(index : Int) : Word def read_word_rotate(index : Int) : Word

View file

@ -15,8 +15,4 @@ class Cartridge
def initialize(rom_path : String) def initialize(rom_path : String)
File.open(rom_path) { |file| file.read @rom } File.open(rom_path) { |file| file.read @rom }
end end
def [](index : Int) : Byte
@rom[index]
end
end end

View file

@ -104,12 +104,12 @@ class CPU
end end
while @pipeline.size < 2 while @pipeline.size < 2
if @cpsr.thumb if @cpsr.thumb
log "Fetch pc: #{hex_str @r[15]}, instr: #{hex_str @gba.bus.read_half(@r[15]).to_u16}" log "Fetch pc: #{hex_str @r[15]}, instr: #{hex_str @gba.bus.read_half(@r[15])}"
@pipeline.push @gba.bus.read_half @r[15] @pipeline.push(@gba.bus.read_half(@r[15]).to_u32!)
@r[15] &+= 2 @r[15] &+= 2
else else
log "Fetch pc: #{hex_str @r[15]}, instr: #{hex_str @gba.bus.read_word @r[15]}" log "Fetch pc: #{hex_str @r[15]}, instr: #{hex_str @gba.bus.read_word @r[15]}"
@pipeline.push @gba.bus.read_word @r[15] @pipeline.push(@gba.bus.read_word(@r[15]))
@r[15] &+= 4 @r[15] &+= 4
end end
end end
@ -156,9 +156,9 @@ class CPU
end end
@[AlwaysInline] @[AlwaysInline]
def set_reg(reg : Int, value : UInt32) : UInt32 def set_reg(reg : Int, value : Int) : UInt32
clear_pipeline if reg == 15 clear_pipeline if reg == 15
@r[reg] = value @r[reg] = value.to_u32!
end end
@[AlwaysInline] @[AlwaysInline]

View file

@ -127,7 +127,7 @@ class DMA
delta_dest = word_size * dest_control.delta delta_dest = word_size * dest_control.delta
len.times do |idx| len.times do |idx|
@gba.bus[@dst[channel]] = word_size == 4 ? @gba.bus.read_word(@src[channel]) : @gba.bus.read_half(@src[channel]).to_u16! @gba.bus[@dst[channel]] = word_size == 4 ? @gba.bus.read_word(@src[channel]) : @gba.bus.read_half(@src[channel])
@src[channel] += delta_source @src[channel] += delta_source
@dst[channel] += delta_dest @dst[channel] += delta_dest
end end