mirror of
https://github.com/mattrberry/crab.git
synced 2025-02-04 08:46:04 +01:00
support open bus for io registers
This commit is contained in:
parent
004ff2c197
commit
e36b633522
12 changed files with 61 additions and 83 deletions
|
@ -148,20 +148,19 @@ module GBA
|
||||||
when 0x82 then @soundcnt_h.value.to_u8!
|
when 0x82 then @soundcnt_h.value.to_u8!
|
||||||
when 0x83 then (@soundcnt_h.value >> 8).to_u8!
|
when 0x83 then (@soundcnt_h.value >> 8).to_u8!
|
||||||
when 0x84
|
when 0x84
|
||||||
0x70_u8 |
|
(@sound_enabled ? 0x80_u8 : 0_u8) |
|
||||||
(@sound_enabled ? 0x80 : 0) |
|
|
||||||
(@channel4.enabled ? 0b1000 : 0) |
|
(@channel4.enabled ? 0b1000 : 0) |
|
||||||
(@channel3.enabled ? 0b0100 : 0) |
|
(@channel3.enabled ? 0b0100 : 0) |
|
||||||
(@channel2.enabled ? 0b0010 : 0) |
|
(@channel2.enabled ? 0b0010 : 0) |
|
||||||
(@channel1.enabled ? 0b0001 : 0)
|
(@channel1.enabled ? 0b0001 : 0)
|
||||||
when 0x85 then 0_u8 # unused
|
when 0x85, 0x86, 0x87 then 0_u8
|
||||||
when 0x88 then @soundbias.value.to_u8!
|
when 0x88 then @soundbias.value.to_u8!
|
||||||
when 0x89 then (@soundbias.value >> 8).to_u8!
|
when 0x89 then (@soundbias.value >> 8).to_u8!
|
||||||
else puts "Unmapped APU read ~ addr:#{hex_str io_addr.to_u8}".colorize.fore(:red); 0_u8 # todo: open bus
|
when 0x8A, 0x8B then 0_u8
|
||||||
|
else @gba.bus.read_open_bus_value(io_addr)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# write to apu memory
|
|
||||||
def []=(io_addr : Int, value : UInt8) : Nil
|
def []=(io_addr : Int, value : UInt8) : Nil
|
||||||
return unless @sound_enabled || 0x82 <= io_addr <= 0x89 || Channel3::WAVE_RAM_RANGE.includes?(io_addr)
|
return unless @sound_enabled || 0x82 <= io_addr <= 0x89 || Channel3::WAVE_RAM_RANGE.includes?(io_addr)
|
||||||
case io_addr
|
case io_addr
|
||||||
|
@ -190,7 +189,6 @@ module GBA
|
||||||
when 0x88 then @soundbias.value = (@soundbias.value & 0xFF00) | value
|
when 0x88 then @soundbias.value = (@soundbias.value & 0xFF00) | value
|
||||||
when 0x89 then @soundbias.value = (@soundbias.value & 0x00FF) | value.to_u16 << 8
|
when 0x89 then @soundbias.value = (@soundbias.value & 0x00FF) | value.to_u16 << 8
|
||||||
when 0xA8..0xAF # unused
|
when 0xA8..0xAF # unused
|
||||||
else puts "Unmapped APU write ~ addr:#{hex_str io_addr.to_u8}, val:#{value}".colorize(:yellow)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -79,12 +79,11 @@ module GBA
|
||||||
|
|
||||||
def [](index : Int) : UInt8
|
def [](index : Int) : UInt8
|
||||||
case index
|
case index
|
||||||
when 0x60 then 0x80_u8 | @sweep_period << 4 | (@negate ? 0x08 : 0) | @shift
|
when 0x60 then @sweep_period << 4 | (@negate ? 0x08 : 0) | @shift
|
||||||
when 0x62 then 0x3F_u8 | @duty << 6
|
when 0x62 then @duty << 6
|
||||||
when 0x63 then read_NRx2
|
when 0x63 then read_NRx2
|
||||||
when 0x64 then 0xFF_u8 # write-only
|
when 0x65 then (@length_enable ? 0x40_u8 : 0_u8)
|
||||||
when 0x65 then 0xBF_u8 | (@length_enable ? 0x40 : 0)
|
else 0_u8
|
||||||
else puts "Reading from invalid Channel1 register: #{hex_str index.to_u16}".colorize.fore(:red); 0_u8 # todo: open bus
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -45,11 +45,10 @@ module GBA
|
||||||
|
|
||||||
def [](index : Int) : UInt8
|
def [](index : Int) : UInt8
|
||||||
case index
|
case index
|
||||||
when 0x68 then 0x3F_u8 | @duty << 6
|
when 0x68 then @duty << 6
|
||||||
when 0x69 then read_NRx2
|
when 0x69 then read_NRx2
|
||||||
when 0x6C then 0xFF_u8 # write-only
|
when 0x6D then (@length_enable ? 0x40_u8 : 0_u8)
|
||||||
when 0x6D then 0xBF_u8 | (@length_enable ? 0x40 : 0)
|
else 0_u8
|
||||||
else puts "Reading from invalid Channel2 register: #{hex_str index.to_u16}".colorize.fore(:red); 0_u8 # todo: open bus
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -51,18 +51,16 @@ module GBA
|
||||||
|
|
||||||
def [](index : Int) : UInt8
|
def [](index : Int) : UInt8
|
||||||
case index
|
case index
|
||||||
when 0x70 then 0x7F_u8 | (@dac_enabled ? 0x80 : 0)
|
when 0x70 then (@dac_enabled ? 0x80_u8 : 0_u8) | @wave_ram_bank << 6 | (@wave_ram_dimension ? 0x20 : 0)
|
||||||
when 0x72 then 0xFF_u8
|
when 0x73 then (@volume_force ? 0x80_u8 : 0_u8) | @volume_code << 5
|
||||||
when 0x73 then 0x9F_u8 | @volume_code << 5
|
when 0x75 then (@length_enable ? 0x40_u8 : 0_u8)
|
||||||
when 0x74 then 0xFF_u8
|
|
||||||
when 0x75 then 0xBF_u8 | (@length_enable ? 0x40 : 0)
|
|
||||||
when WAVE_RAM_RANGE
|
when WAVE_RAM_RANGE
|
||||||
if @enabled
|
if @enabled
|
||||||
@wave_ram[@wave_ram_bank][@wave_ram_position // 2]
|
@wave_ram[@wave_ram_bank][@wave_ram_position // 2]
|
||||||
else
|
else
|
||||||
@wave_ram[@wave_ram_bank][index - WAVE_RAM_RANGE.begin]
|
@wave_ram[@wave_ram_bank][index - WAVE_RAM_RANGE.begin]
|
||||||
end
|
end
|
||||||
else puts "Reading from invalid Channel3 register: #{hex_str index.to_u16}".colorize.fore(:red); 0_u8 # todo: open bus
|
else 0_u8
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -45,11 +45,10 @@ module GBA
|
||||||
|
|
||||||
def [](index : Int) : UInt8
|
def [](index : Int) : UInt8
|
||||||
case index
|
case index
|
||||||
when 0x78 then 0xFF_u8
|
|
||||||
when 0x79 then read_NRx2
|
when 0x79 then read_NRx2
|
||||||
when 0x7C then @clock_shift << 4 | @width_mode << 3 | @divisor_code
|
when 0x7C then @clock_shift << 4 | @width_mode << 3 | @divisor_code
|
||||||
when 0x7D then 0xBF_u8 | (@length_enable ? 0x40 : 0)
|
when 0x7D then (@length_enable ? 0x40_u8 : 0_u8)
|
||||||
else puts "Reading from invalid Channel4 register: #{hex_str index.to_u16}".colorize.fore(:red); 0_u8 # todo: open bus
|
else 0_u8
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ module GBA
|
||||||
end
|
end
|
||||||
|
|
||||||
def [](index : Int) : UInt8
|
def [](index : Int) : UInt8
|
||||||
0_u8
|
@gba.bus.read_open_bus_value(index)
|
||||||
end
|
end
|
||||||
|
|
||||||
def []=(index : Int, value : Byte) : Nil
|
def []=(index : Int, value : Byte) : Nil
|
||||||
|
|
|
@ -266,5 +266,19 @@ module GBA
|
||||||
write_byte_internal(index + 2, (value >> 16).to_u8!)
|
write_byte_internal(index + 2, (value >> 16).to_u8!)
|
||||||
write_byte_internal(index + 3, (value >> 24).to_u8!)
|
write_byte_internal(index + 3, (value >> 24).to_u8!)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def read_open_bus_value(index : Int, _file = __FILE__) : Byte
|
||||||
|
log "Reading open bus at #{hex_str index.to_u32} from #{_file}"
|
||||||
|
shift = (index & 3) * 8
|
||||||
|
if @gba.cpu.cpsr.thumb
|
||||||
|
# todo: special handling for 16-bit vs 32-bit regions
|
||||||
|
# todo: does this need to have both of the previous opcodes?
|
||||||
|
opcode = read_half_internal(@gba.cpu.r[15] & ~1).to_u32!
|
||||||
|
word = opcode << 16 | opcode
|
||||||
|
else
|
||||||
|
word = read_word_internal(@gba.cpu.r[15] & ~3)
|
||||||
|
end
|
||||||
|
(word >> shift).to_u8!
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -43,7 +43,7 @@ module GBA
|
||||||
end
|
end
|
||||||
|
|
||||||
getter r = Slice(Word).new 16
|
getter r = Slice(Word).new 16
|
||||||
@cpsr : PSR = PSR.new CPU::Mode::SYS.value
|
getter cpsr : PSR = PSR.new CPU::Mode::SYS.value
|
||||||
@spsr : PSR = PSR.new CPU::Mode::SYS.value
|
@spsr : PSR = PSR.new CPU::Mode::SYS.value
|
||||||
getter pipeline = Pipeline.new
|
getter pipeline = Pipeline.new
|
||||||
getter lut : Slice(Proc(Word, Nil)) { fill_lut }
|
getter lut : Slice(Proc(Word, Nil)) { fill_lut }
|
||||||
|
@ -100,12 +100,12 @@ module GBA
|
||||||
def fill_pipeline : Nil
|
def fill_pipeline : Nil
|
||||||
if @cpsr.thumb
|
if @cpsr.thumb
|
||||||
pc = @r[15] & ~1
|
pc = @r[15] & ~1
|
||||||
@pipeline.push @gba.bus.read_half(@r[15] &- 2).to_u32! if @pipeline.size == 0
|
@pipeline.push @gba.bus.read_half(pc &- 2).to_u32! if @pipeline.size == 0
|
||||||
@pipeline.push @gba.bus.read_half(@r[15]).to_u32! if @pipeline.size == 1
|
@pipeline.push @gba.bus.read_half(pc).to_u32! if @pipeline.size == 1
|
||||||
else
|
else
|
||||||
pc = @r[15] & ~3
|
pc = @r[15] & ~3
|
||||||
@pipeline.push @gba.bus.read_word(@r[15] &- 4) if @pipeline.size == 0
|
@pipeline.push @gba.bus.read_word(pc &- 4) if @pipeline.size == 0
|
||||||
@pipeline.push @gba.bus.read_word(@r[15]) if @pipeline.size == 1
|
@pipeline.push @gba.bus.read_word(pc) if @pipeline.size == 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -46,17 +46,12 @@ module GBA
|
||||||
channel = (io_addr - 0xB0) // 12
|
channel = (io_addr - 0xB0) // 12
|
||||||
reg = (io_addr - 0xB0) % 12
|
reg = (io_addr - 0xB0) % 12
|
||||||
case reg
|
case reg
|
||||||
when 0, 1, 2, 3 # dmasad
|
when 8, 9 then 0_u8 # dmacnt_l write-only
|
||||||
0_u8 # todo: OOB read
|
when 10, 11
|
||||||
when 4, 5, 6, 7 # dmadad
|
|
||||||
0_u8 # todo: OOB read
|
|
||||||
when 8, 9 # dmacnt_l
|
|
||||||
0_u8 # write-only
|
|
||||||
when 10, 11 # dmacnt_h
|
|
||||||
val = @dmacnt_h[channel].read_byte(io_addr & 1)
|
val = @dmacnt_h[channel].read_byte(io_addr & 1)
|
||||||
val |= 0b1000 if io_addr == 0xDF && @dmacnt_h[3].game_pak # DMA3 only
|
val |= 0b1000 if io_addr == 0xDF && @dmacnt_h[3].game_pak # DMA3 only
|
||||||
val
|
val
|
||||||
else abort "Unmapped DMA read ~ addr:#{hex_str io_addr.to_u8}"
|
else @gba.bus.read_open_bus_value(io_addr)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,29 +7,23 @@ module GBA
|
||||||
|
|
||||||
def [](index : Int) : Byte
|
def [](index : Int) : Byte
|
||||||
io_addr = 0xFFFFFF_u32 & index
|
io_addr = 0xFFFFFF_u32 & index
|
||||||
if io_addr <= 0x05F
|
case io_addr
|
||||||
@gba.ppu[io_addr]
|
when 0x000..0x055 then @gba.ppu[io_addr]
|
||||||
elsif io_addr <= 0xAF
|
when 0x060..0x0A7 then @gba.apu[io_addr]
|
||||||
@gba.apu[io_addr]
|
when 0x0B0..0x0DF then @gba.dma[io_addr]
|
||||||
elsif io_addr <= 0xFF
|
when 0x100..0x10F then @gba.timer[io_addr]
|
||||||
@gba.dma[io_addr]
|
when 0x120..0x12B, 0x134..0x159
|
||||||
elsif 0x100 <= io_addr <= 0x10F
|
|
||||||
@gba.timer[io_addr]
|
|
||||||
elsif 0x130 <= io_addr <= 0x133
|
|
||||||
@gba.keypad[io_addr]
|
|
||||||
elsif 0x120 <= io_addr <= 0x12F || 0x134 <= io_addr <= 0x1FF
|
|
||||||
# todo: serial
|
# todo: serial
|
||||||
if io_addr == 0x135
|
if io_addr == 0x135
|
||||||
0x80_u8
|
0x80_u8
|
||||||
else
|
else
|
||||||
0_u8
|
0_u8
|
||||||
end
|
end
|
||||||
elsif 0x200 <= io_addr <= 0x203 || 0x208 <= io_addr <= 0x209
|
when 0x130..0x133 then @gba.keypad[io_addr]
|
||||||
@gba.interrupts[io_addr]
|
when 0x200..0x203,
|
||||||
elsif 0x204 <= io_addr <= 0x205
|
0x208..0x209 then @gba.interrupts[io_addr]
|
||||||
@waitcnt.read_byte(io_addr & 1)
|
when 0x204..0x205 then @waitcnt.read_byte(io_addr & 1)
|
||||||
else
|
else @gba.bus.read_open_bus_value(io_addr)
|
||||||
0_u8 # todo: oob reads
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -402,34 +402,16 @@ module GBA
|
||||||
when 0x002..0x003 then 0_u8 # todo green swap
|
when 0x002..0x003 then 0_u8 # todo green swap
|
||||||
when 0x004..0x005 then @dispstat.read_byte(io_addr & 1)
|
when 0x004..0x005 then @dispstat.read_byte(io_addr & 1)
|
||||||
when 0x006..0x007 then (@vcount >> (8 * (io_addr & 1))).to_u8!
|
when 0x006..0x007 then (@vcount >> (8 * (io_addr & 1))).to_u8!
|
||||||
when 0x008..0x00F then @bgcnt[(io_addr - 0x008) >> 1].read_byte(io_addr & 1)
|
when 0x008..0x00F
|
||||||
when 0x010..0x01F
|
bg_num = (io_addr - 0x008) >> 1
|
||||||
bg_num = (io_addr - 0x010) >> 2
|
val = @bgcnt[bg_num].read_byte(io_addr & 1)
|
||||||
if bit?(io_addr, 1)
|
val |= 0x20 if (io_addr == 0xD || io_addr == 0xF) && @bgcnt[bg_num].affine_wrap
|
||||||
@bgvofs[bg_num].read_byte(io_addr & 1)
|
val
|
||||||
else
|
|
||||||
@bghofs[bg_num].read_byte(io_addr & 1)
|
|
||||||
end
|
|
||||||
when 0x020..0x03F
|
|
||||||
bg_num = (io_addr & 0x10) >> 4 # (bg 0/1 represents bg 2/3, since those are the only aff bgs)
|
|
||||||
offs = io_addr & 0xF
|
|
||||||
if offs >= 8
|
|
||||||
offs -= 8
|
|
||||||
@bgref[bg_num][offs >> 2].read_byte(offs & 3)
|
|
||||||
else
|
|
||||||
@bgaff[bg_num][offs >> 1].read_byte(offs & 1)
|
|
||||||
end
|
|
||||||
when 0x040..0x041 then @win0h.read_byte(io_addr & 1)
|
|
||||||
when 0x042..0x043 then @win1h.read_byte(io_addr & 1)
|
|
||||||
when 0x044..0x045 then @win0v.read_byte(io_addr & 1)
|
|
||||||
when 0x046..0x047 then @win1v.read_byte(io_addr & 1)
|
|
||||||
when 0x048..0x049 then @winin.read_byte(io_addr & 1)
|
when 0x048..0x049 then @winin.read_byte(io_addr & 1)
|
||||||
when 0x04A..0x04B then @winout.read_byte(io_addr & 1)
|
when 0x04A..0x04B then @winout.read_byte(io_addr & 1)
|
||||||
when 0x04C..0x04D then @mosaic.read_byte(io_addr & 1)
|
|
||||||
when 0x050..0x051 then @bldcnt.read_byte(io_addr & 1)
|
when 0x050..0x051 then @bldcnt.read_byte(io_addr & 1)
|
||||||
when 0x052..0x053 then @bldalpha.read_byte(io_addr & 1)
|
when 0x052..0x053 then @bldalpha.read_byte(io_addr & 1)
|
||||||
when 0x054..0x055 then @bldy.read_byte(io_addr & 1)
|
else @gba.bus.read_open_bus_value(io_addr)
|
||||||
else log "Unmapped PPU read ~ addr:#{hex_str io_addr.to_u8}"; 0_u8 # todo: open bus
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -169,11 +169,11 @@ module GBA
|
||||||
class BGCNT < BitField(UInt16)
|
class BGCNT < BitField(UInt16)
|
||||||
include Base16
|
include Base16
|
||||||
num screen_size, 2
|
num screen_size, 2
|
||||||
bool affine_wrap
|
bool affine_wrap, write_only: true # used only in bg2 and bg3
|
||||||
num screen_base_block, 5
|
num screen_base_block, 5
|
||||||
bool color_mode_8bpp
|
bool color_mode_8bpp
|
||||||
bool mosaic
|
bool mosaic
|
||||||
num not_used, 2, read_only: true
|
num not_used, 2
|
||||||
num character_base_block, 2
|
num character_base_block, 2
|
||||||
num priority, 2
|
num priority, 2
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue