Browse Source

machine, runtime/interrupt: switch to use register definitions from device/gba

Signed-off-by: deadprogram <ron@hybridgroup.com>
pull/3566/head
deadprogram 2 years ago
committed by Ayke
parent
commit
383e7ae14a
  1. 42
      src/machine/machine_gameboyadvance.go
  2. 94
      src/runtime/interrupt/interrupt_gameboyadvance.go

42
src/machine/machine_gameboyadvance.go

@ -3,8 +3,9 @@
package machine package machine
import ( import (
"device/gba"
"image/color" "image/color"
"runtime/interrupt"
"runtime/volatile" "runtime/volatile"
"unsafe" "unsafe"
) )
@ -16,40 +17,37 @@ const deviceName = "GBA"
// Interrupt numbers as used on the GameBoy Advance. Register them with // Interrupt numbers as used on the GameBoy Advance. Register them with
// runtime/interrupt.New. // runtime/interrupt.New.
const ( const (
IRQ_VBLANK = interrupt.IRQ_VBLANK IRQ_VBLANK = gba.IRQ_VBLANK
IRQ_HBLANK = interrupt.IRQ_HBLANK IRQ_HBLANK = gba.IRQ_HBLANK
IRQ_VCOUNT = interrupt.IRQ_VCOUNT IRQ_VCOUNT = gba.IRQ_VCOUNT
IRQ_TIMER0 = interrupt.IRQ_TIMER0 IRQ_TIMER0 = gba.IRQ_TIMER0
IRQ_TIMER1 = interrupt.IRQ_TIMER1 IRQ_TIMER1 = gba.IRQ_TIMER1
IRQ_TIMER2 = interrupt.IRQ_TIMER2 IRQ_TIMER2 = gba.IRQ_TIMER2
IRQ_TIMER3 = interrupt.IRQ_TIMER3 IRQ_TIMER3 = gba.IRQ_TIMER3
IRQ_COM = interrupt.IRQ_COM IRQ_COM = gba.IRQ_COM
IRQ_DMA0 = interrupt.IRQ_DMA0 IRQ_DMA0 = gba.IRQ_DMA0
IRQ_DMA1 = interrupt.IRQ_DMA1 IRQ_DMA1 = gba.IRQ_DMA1
IRQ_DMA2 = interrupt.IRQ_DMA2 IRQ_DMA2 = gba.IRQ_DMA2
IRQ_DMA3 = interrupt.IRQ_DMA3 IRQ_DMA3 = gba.IRQ_DMA3
IRQ_KEYPAD = interrupt.IRQ_KEYPAD IRQ_KEYPAD = gba.IRQ_KEYPAD
IRQ_GAMEPAK = interrupt.IRQ_GAMEPAK IRQ_GAMEPAK = gba.IRQ_GAMEPAK
) )
// Make it easier to directly write to I/O RAM.
var ioram = (*[0x400]volatile.Register8)(unsafe.Pointer(uintptr(0x04000000)))
// Set has not been implemented. // Set has not been implemented.
func (p Pin) Set(value bool) { func (p Pin) Set(value bool) {
// do nothing // do nothing
} }
var Display = FramebufDisplay{(*[160][240]volatile.Register16)(unsafe.Pointer(uintptr(0x06000000)))} var Display = FramebufDisplay{(*[160][240]volatile.Register16)(unsafe.Pointer(uintptr(gba.MEM_VRAM)))}
type FramebufDisplay struct { type FramebufDisplay struct {
port *[160][240]volatile.Register16 port *[160][240]volatile.Register16
} }
func (d FramebufDisplay) Configure() { func (d FramebufDisplay) Configure() {
// Write into the I/O registers, setting video display parameters. // Use video mode 3 (in BG2, a 16bpp bitmap in VRAM) and Enable BG2
ioram[0].Set(0x03) // Use video mode 3 (in BG2, a 16bpp bitmap in VRAM) gba.DISP.DISPCNT.Set(gba.DISPCNT_BGMODE_3<<gba.DISPCNT_BGMODE_Pos |
ioram[1].Set(0x04) // Enable BG2 (BG0 = 1, BG1 = 2, BG2 = 4, ...) gba.DISPCNT_SCREENDISPLAY_BG2_ENABLE<<gba.DISPCNT_SCREENDISPLAY_BG2_Pos)
} }
func (d FramebufDisplay) Size() (x, y int16) { func (d FramebufDisplay) Size() (x, y int16) {

94
src/runtime/interrupt/interrupt_gameboyadvance.go

@ -5,37 +5,13 @@ package interrupt
// This is good documentation of the GBA: https://www.akkit.org/info/gbatek.htm // This is good documentation of the GBA: https://www.akkit.org/info/gbatek.htm
import ( import (
"runtime/volatile" "device/gba"
"unsafe"
)
const (
IRQ_VBLANK = 0
IRQ_HBLANK = 1
IRQ_VCOUNT = 2
IRQ_TIMER0 = 3
IRQ_TIMER1 = 4
IRQ_TIMER2 = 5
IRQ_TIMER3 = 6
IRQ_COM = 7
IRQ_DMA0 = 8
IRQ_DMA1 = 9
IRQ_DMA2 = 10
IRQ_DMA3 = 11
IRQ_KEYPAD = 12
IRQ_GAMEPAK = 13
)
var (
regInterruptEnable = (*volatile.Register16)(unsafe.Pointer(uintptr(0x4000200)))
regInterruptRequestFlags = (*volatile.Register16)(unsafe.Pointer(uintptr(0x4000202)))
regGlobalInterruptEnable = (*volatile.Register16)(unsafe.Pointer(uintptr(0x4000208)))
) )
// Enable enables this interrupt. Right after calling this function, the // Enable enables this interrupt. Right after calling this function, the
// interrupt may be invoked if it was already pending. // interrupt may be invoked if it was already pending.
func (irq Interrupt) Enable() { func (irq Interrupt) Enable() {
regInterruptEnable.SetBits(1 << uint(irq.num)) gba.INTERRUPT.IE.SetBits(1 << uint(irq.num))
} }
var inInterrupt bool var inInterrupt bool
@ -43,10 +19,10 @@ var inInterrupt bool
//export handleInterrupt //export handleInterrupt
func handleInterrupt() { func handleInterrupt() {
inInterrupt = true inInterrupt = true
flags := regInterruptRequestFlags.Get() flags := gba.INTERRUPT.IF.Get()
for i := 0; i < 14; i++ { for i := 0; i < 14; i++ {
if flags&(1<<uint(i)) != 0 { if flags&(1<<uint(i)) != 0 {
regInterruptRequestFlags.Set(1 << uint(i)) // acknowledge interrupt gba.INTERRUPT.IF.Set(1 << uint(i)) // acknowledge interrupt
callInterruptHandler(i) callInterruptHandler(i)
} }
} }
@ -62,34 +38,34 @@ func callHandlers(num int)
func callInterruptHandler(id int) { func callInterruptHandler(id int) {
switch id { switch id {
case IRQ_VBLANK: case gba.IRQ_VBLANK:
callHandlers(IRQ_VBLANK) callHandlers(gba.IRQ_VBLANK)
case IRQ_HBLANK: case gba.IRQ_HBLANK:
callHandlers(IRQ_HBLANK) callHandlers(gba.IRQ_HBLANK)
case IRQ_VCOUNT: case gba.IRQ_VCOUNT:
callHandlers(IRQ_VCOUNT) callHandlers(gba.IRQ_VCOUNT)
case IRQ_TIMER0: case gba.IRQ_TIMER0:
callHandlers(IRQ_TIMER0) callHandlers(gba.IRQ_TIMER0)
case IRQ_TIMER1: case gba.IRQ_TIMER1:
callHandlers(IRQ_TIMER1) callHandlers(gba.IRQ_TIMER1)
case IRQ_TIMER2: case gba.IRQ_TIMER2:
callHandlers(IRQ_TIMER2) callHandlers(gba.IRQ_TIMER2)
case IRQ_TIMER3: case gba.IRQ_TIMER3:
callHandlers(IRQ_TIMER3) callHandlers(gba.IRQ_TIMER3)
case IRQ_COM: case gba.IRQ_COM:
callHandlers(IRQ_COM) callHandlers(gba.IRQ_COM)
case IRQ_DMA0: case gba.IRQ_DMA0:
callHandlers(IRQ_DMA0) callHandlers(gba.IRQ_DMA0)
case IRQ_DMA1: case gba.IRQ_DMA1:
callHandlers(IRQ_DMA1) callHandlers(gba.IRQ_DMA1)
case IRQ_DMA2: case gba.IRQ_DMA2:
callHandlers(IRQ_DMA2) callHandlers(gba.IRQ_DMA2)
case IRQ_DMA3: case gba.IRQ_DMA3:
callHandlers(IRQ_DMA3) callHandlers(gba.IRQ_DMA3)
case IRQ_KEYPAD: case gba.IRQ_KEYPAD:
callHandlers(IRQ_KEYPAD) callHandlers(gba.IRQ_KEYPAD)
case IRQ_GAMEPAK: case gba.IRQ_GAMEPAK:
callHandlers(IRQ_GAMEPAK) callHandlers(gba.IRQ_GAMEPAK)
} }
} }
@ -107,9 +83,9 @@ type State uint8
// as you called Disable (this happens naturally with the pattern above). // as you called Disable (this happens naturally with the pattern above).
func Disable() (state State) { func Disable() (state State) {
// Save the previous interrupt state. // Save the previous interrupt state.
state = State(regGlobalInterruptEnable.Get()) state = State(gba.INTERRUPT.PAUSE.Get())
// Disable all interrupts. // Disable all interrupts.
regGlobalInterruptEnable.Set(0) gba.INTERRUPT.PAUSE.Set(0)
return return
} }
@ -119,7 +95,7 @@ func Disable() (state State) {
// cricital sections. // cricital sections.
func Restore(state State) { func Restore(state State) {
// Restore interrupts to the previous state. // Restore interrupts to the previous state.
regGlobalInterruptEnable.Set(uint16(state)) gba.INTERRUPT.PAUSE.Set(uint16(state))
} }
// In returns whether the system is currently in an interrupt. // In returns whether the system is currently in an interrupt.

Loading…
Cancel
Save