diff --git a/lib/rubyboy/bus.rb b/lib/rubyboy/bus.rb index c67b958..f0ad272 100644 --- a/lib/rubyboy/bus.rb +++ b/lib/rubyboy/bus.rb @@ -11,74 +11,93 @@ def initialize(ppu, rom, ram, mbc, timer, interrupt, joypad, apu) @apu = apu @interrupt = interrupt @timer = timer + end + + def read_byte(addr) + case addr >> 12 + when 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0xa, 0xb + return @mbc.read_byte(addr) + when 0x8, 0x9 + return @ppu.read_byte(addr) + when 0xc + return @ram.wram1[addr - 0xc000] + when 0xd + return @ram.wram2[addr - 0xd000] + when 0xf + case addr >> 8 + when 0xfe + return @ppu.read_byte(addr) if addr <= 0xfe9f + when 0xff + last_byte = addr & 0xFF - @read_methods = Array.new(0x10000) - @write_methods = Array.new(0x10000) + case last_byte + when 0x00 + return @joypad.read_byte(addr) + when 0x04, 0x05, 0x06, 0x07 + return @timer.read_byte(addr) + when 0x0f + return @interrupt.read_byte(addr) + when 0x46 + return @ppu.read_byte(addr) + when 0xff + return @interrupt.read_byte(addr) + end - set_methods - end + return @apu.read_byte(addr) if last_byte <= 0x26 && last_byte >= 0x10 - def set_methods - 0x10000.times do |addr| - case addr - when 0x0000..0x7fff - @read_methods[addr] = -> { @mbc.read_byte(addr) } - @write_methods[addr] = ->(value) { @mbc.write_byte(addr, value) } - when 0x8000..0x9fff - @read_methods[addr] = -> { @ppu.read_byte(addr) } - @write_methods[addr] = ->(value) { @ppu.write_byte(addr, value) } - when 0xa000..0xbfff - @read_methods[addr] = -> { @mbc.read_byte(addr) } - @write_methods[addr] = ->(value) { @mbc.write_byte(addr, value) } - when 0xc000..0xcfff - @read_methods[addr] = -> { @ram.wram1[addr - 0xc000] } - @write_methods[addr] = ->(value) { @ram.wram1[addr - 0xc000] = value } - when 0xd000..0xdfff - @read_methods[addr] = -> { @ram.wram2[addr - 0xd000] } - @write_methods[addr] = ->(value) { @ram.wram2[addr - 0xd000] = value } - when 0xfe00..0xfe9f - @read_methods[addr] = -> { @ppu.read_byte(addr) } - @write_methods[addr] = ->(value) { @ppu.write_byte(addr, value) } - when 0xff00 - @read_methods[addr] = -> { @joypad.read_byte(addr) } - @write_methods[addr] = ->(value) { @joypad.write_byte(addr, value) } - when 0xff04..0xff07 - @read_methods[addr] = -> { @timer.read_byte(addr) } - @write_methods[addr] = ->(value) { @timer.write_byte(addr, value) } - when 0xff0f - @read_methods[addr] = -> { @interrupt.read_byte(addr) } - @write_methods[addr] = ->(value) { @interrupt.write_byte(addr, value) } - when 0xff10..0xff26 - @read_methods[addr] = -> { @apu.read_byte(addr) } - @write_methods[addr] = ->(value) { @apu.write_byte(addr, value) } - when 0xff30..0xff3f - @read_methods[addr] = -> { @apu.read_byte(addr) } - @write_methods[addr] = ->(value) { @apu.write_byte(addr, value) } - when 0xff46 - @read_methods[addr] = -> { @ppu.read_byte(addr) } - @write_methods[addr] = ->(value) { 0xa0.times { |i| write_byte(0xfe00 + i, read_byte((value << 8) + i)) } } - when 0xff40..0xff4b - @read_methods[addr] = -> { @ppu.read_byte(addr) } - @write_methods[addr] = ->(value) { @ppu.write_byte(addr, value) } - when 0xff80..0xfffe - @read_methods[addr] = -> { @ram.hram[addr - 0xff80] } - @write_methods[addr] = ->(value) { @ram.hram[addr - 0xff80] = value } - when 0xffff - @read_methods[addr] = -> { @interrupt.read_byte(addr) } - @write_methods[addr] = ->(value) { @interrupt.write_byte(addr, value) } - else - @read_methods[addr] = -> { 0xff } - @write_methods[addr] = ->(_value) {} + return @apu.read_byte(addr) if last_byte <= 0x3f && last_byte >= 0x30 + + return @ppu.read_byte(addr) if last_byte <= 0x4b && last_byte >= 0x40 + + return @ram.hram[addr - 0xff80] if last_byte <= 0xfe && last_byte >= 0x80 end end - end - def read_byte(addr) - @read_methods[addr].call + 0xff end def write_byte(addr, value) - @write_methods[addr].call(value) + case addr >> 12 + when 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0xa, 0xb + return @mbc.write_byte(addr, value) + when 0x8, 0x9 + return @ppu.write_byte(addr, value) + when 0xc + return @ram.wram1[addr - 0xc000] = value + when 0xd + return @ram.wram2[addr - 0xd000] = value + when 0xf + case addr >> 8 + when 0xfe + return @ppu.write_byte(addr, value) if addr <= 0xfe9f + when 0xff + last_byte = addr & 0xFF + + case last_byte + when 0x00 + return @joypad.write_byte(addr, value) + when 0x04, 0x05, 0x06, 0x07 + return @timer.write_byte(addr, value) + when 0x0f + return @interrupt.write_byte(addr, value) + when 0x46 + 0xa0.times { |i| write_byte(0xfe00 + i, read_byte((value << 8) + i)) } + return + when 0xff + return @interrupt.write_byte(addr, value) + end + + return @apu.write_byte(addr, value) if last_byte <= 0x26 && last_byte >= 0x10 + + return @apu.write_byte(addr, value) if last_byte <= 0x3f && last_byte >= 0x30 + + return @ppu.write_byte(addr, value) if last_byte <= 0x4b && last_byte >= 0x40 + + return @ram.hram[addr - 0xff80] = value if last_byte <= 0xfe && last_byte >= 0x80 + end + end + + nil end def read_word(addr)