keyinput implemented

This commit is contained in:
Matthew Berry 2020-10-17 00:18:11 -07:00
parent 337e7d0bc8
commit b51e07b643
3 changed files with 104 additions and 3 deletions

View file

@ -3,6 +3,7 @@ require "./util"
require "./scheduler" require "./scheduler"
require "./cartridge" require "./cartridge"
require "./mmio" require "./mmio"
require "./keypad"
require "./bus" require "./bus"
require "./interrupts" require "./interrupts"
require "./cpu" require "./cpu"
@ -13,6 +14,7 @@ class GBA
getter scheduler : Scheduler getter scheduler : Scheduler
getter cartridge : Cartridge getter cartridge : Cartridge
getter mmio : MMIO { MMIO.new self } getter mmio : MMIO { MMIO.new self }
getter keypad : Keypad { Keypad.new }
getter bus : Bus { Bus.new self } getter bus : Bus { Bus.new self }
getter interrupts : Interrupts { Interrupts.new } getter interrupts : Interrupts { Interrupts.new }
getter cpu : CPU { CPU.new self } getter cpu : CPU { CPU.new self }
@ -36,7 +38,7 @@ class GBA
when SDL::Event::Quit then exit 0 when SDL::Event::Quit then exit 0
when SDL::Event::Keyboard, when SDL::Event::Keyboard,
SDL::Event::JoyHat, SDL::Event::JoyHat,
SDL::Event::JoyButton SDL::Event::JoyButton then keypad.handle_keypad_event event
else nil else nil
end end
end end

97
src/crab/keypad.cr Normal file
View file

@ -0,0 +1,97 @@
class Keypad
class KEYINPUT < BitField(UInt16)
num not_used, 6
bool l
bool r
bool down
bool up
bool left
bool right
bool start
bool :select
bool b
bool a
end
class KEYCNT < BitField(UInt16)
bool irq_condition
bool irq_enable
num not_used, 4
bool l
bool r
bool down
bool up
bool left
bool right
bool start
bool :select
bool b
bool a
end
@keyinput = KEYINPUT.new 0xFFFF_u16
@keycnt = KEYCNT.new 0xFFFF_u16
def read_io(io_addr : Int) : Byte
case io_addr
when 0x130 then 0xFF_u8 & @keyinput.value
when 0x131 then 0xFF_u8 & @keyinput.value >> 8
when 0x132 then 0xFF_u8 & @keycnt.value
when 0x133 then 0xFF_u8 & @keycnt.value >> 8
else raise "Unimplemented keypad read ~ addr:#{hex_str io_addr.to_u8!}"
end
end
def write_io(io_addr : Int, value : Byte) : Nil
case io_addr
when 0x130 then nil
when 0x131 then nil
else raise "Unimplemented keypad write ~ addr:#{hex_str io_addr.to_u8!}, val:#{value}"
end
end
def handle_keypad_event(event : SDL::Event) : Nil
case event
when SDL::Event::Keyboard
bit = !event.pressed?
case event.sym
when .down?, .d? then @keyinput.down = bit
when .up?, .e? then @keyinput.up = bit
when .left?, .s? then @keyinput.left = bit
when .right?, .f? then @keyinput.right = bit
when .semicolon? then @keyinput.start = bit
when .l? then @keyinput.select = bit
when .b?, .j? then @keyinput.b = bit
when .a?, .k? then @keyinput.a = bit
when .w? then @keyinput.l = bit
when .r? then @keyinput.r = bit
else nil
end
when SDL::Event::JoyHat
@keyinput.value |= 0x00F0
case event.value
when LibSDL::HAT_DOWN then @keyinput.down = false
when LibSDL::HAT_UP then @keyinput.up = false
when LibSDL::HAT_LEFT then @keyinput.left = false
when LibSDL::HAT_RIGHT then @keyinput.right = false
when LibSDL::HAT_LEFTUP then @keyinput.left = true; @keyinput.up = true
when LibSDL::HAT_LEFTDOWN then @keyinput.left = true; @keyinput.down = true
when LibSDL::HAT_RIGHTUP then @keyinput.right = true; @keyinput.up = true
when LibSDL::HAT_RIGHTDOWN then @keyinput.right = true; @keyinput.down = true
else nil
end
when SDL::Event::JoyButton
bit = !event.pressed?
case event.button
when 0 then @keyinput.b = bit
when 1 then @keyinput.a = bit
when 4 then @keyinput.l = bit
when 5 then @keyinput.r = bit
when 6 then @keyinput.select = bit
when 7 then @keyinput.start = bit
else nil
end
else nil
end
end
end

View file

@ -8,8 +8,8 @@ class MMIO
@gba.ppu.read_io io_addr @gba.ppu.read_io io_addr
elsif (io_addr >= 0x200 && io_addr <= 0x203) || (io_addr >= 0x208 && io_addr <= 0x209) elsif (io_addr >= 0x200 && io_addr <= 0x203) || (io_addr >= 0x208 && io_addr <= 0x209)
@gba.interrupts.read_io io_addr @gba.interrupts.read_io io_addr
elsif io_addr >= 0x130 && io_addr <= 0x133 # todo keypad elsif io_addr >= 0x130 && io_addr <= 0x133
0xFF_u8 @gba.keypad.read_io io_addr
elsif not_used? io_addr elsif not_used? io_addr
0xFF_u8 # todo what is returned here? 0xFF_u8 # todo what is returned here?
else else
@ -23,6 +23,8 @@ class MMIO
@gba.ppu.write_io io_addr, value @gba.ppu.write_io io_addr, value
elsif (io_addr >= 0x200 && io_addr <= 0x203) || (io_addr >= 0x208 && io_addr <= 0x209) elsif (io_addr >= 0x200 && io_addr <= 0x203) || (io_addr >= 0x208 && io_addr <= 0x209)
@gba.interrupts.write_io io_addr, value @gba.interrupts.write_io io_addr, value
elsif io_addr >= 0x130 && io_addr <= 0x133
@gba.keypad.read_io io_addr
elsif not_used? io_addr elsif not_used? io_addr
else else
raise "Unmapped MMIO write: #{hex_str index.to_u32}" raise "Unmapped MMIO write: #{hex_str index.to_u32}"