machine, runtime/interrupt: switch to use register definitions from device/gba
Signed-off-by: deadprogram <ron@hybridgroup.com>
Этот коммит содержится в:
родитель
4f7864b757
коммит
383e7ae14a
2 изменённых файлов: 55 добавлений и 81 удалений
|
@ -3,8 +3,9 @@
|
|||
package machine
|
||||
|
||||
import (
|
||||
"device/gba"
|
||||
|
||||
"image/color"
|
||||
"runtime/interrupt"
|
||||
"runtime/volatile"
|
||||
"unsafe"
|
||||
)
|
||||
|
@ -16,40 +17,37 @@ const deviceName = "GBA"
|
|||
// Interrupt numbers as used on the GameBoy Advance. Register them with
|
||||
// runtime/interrupt.New.
|
||||
const (
|
||||
IRQ_VBLANK = interrupt.IRQ_VBLANK
|
||||
IRQ_HBLANK = interrupt.IRQ_HBLANK
|
||||
IRQ_VCOUNT = interrupt.IRQ_VCOUNT
|
||||
IRQ_TIMER0 = interrupt.IRQ_TIMER0
|
||||
IRQ_TIMER1 = interrupt.IRQ_TIMER1
|
||||
IRQ_TIMER2 = interrupt.IRQ_TIMER2
|
||||
IRQ_TIMER3 = interrupt.IRQ_TIMER3
|
||||
IRQ_COM = interrupt.IRQ_COM
|
||||
IRQ_DMA0 = interrupt.IRQ_DMA0
|
||||
IRQ_DMA1 = interrupt.IRQ_DMA1
|
||||
IRQ_DMA2 = interrupt.IRQ_DMA2
|
||||
IRQ_DMA3 = interrupt.IRQ_DMA3
|
||||
IRQ_KEYPAD = interrupt.IRQ_KEYPAD
|
||||
IRQ_GAMEPAK = interrupt.IRQ_GAMEPAK
|
||||
IRQ_VBLANK = gba.IRQ_VBLANK
|
||||
IRQ_HBLANK = gba.IRQ_HBLANK
|
||||
IRQ_VCOUNT = gba.IRQ_VCOUNT
|
||||
IRQ_TIMER0 = gba.IRQ_TIMER0
|
||||
IRQ_TIMER1 = gba.IRQ_TIMER1
|
||||
IRQ_TIMER2 = gba.IRQ_TIMER2
|
||||
IRQ_TIMER3 = gba.IRQ_TIMER3
|
||||
IRQ_COM = gba.IRQ_COM
|
||||
IRQ_DMA0 = gba.IRQ_DMA0
|
||||
IRQ_DMA1 = gba.IRQ_DMA1
|
||||
IRQ_DMA2 = gba.IRQ_DMA2
|
||||
IRQ_DMA3 = gba.IRQ_DMA3
|
||||
IRQ_KEYPAD = gba.IRQ_KEYPAD
|
||||
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.
|
||||
func (p Pin) Set(value bool) {
|
||||
// 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 {
|
||||
port *[160][240]volatile.Register16
|
||||
}
|
||||
|
||||
func (d FramebufDisplay) Configure() {
|
||||
// Write into the I/O registers, setting video display parameters.
|
||||
ioram[0].Set(0x03) // Use video mode 3 (in BG2, a 16bpp bitmap in VRAM)
|
||||
ioram[1].Set(0x04) // Enable BG2 (BG0 = 1, BG1 = 2, BG2 = 4, ...)
|
||||
// Use video mode 3 (in BG2, a 16bpp bitmap in VRAM) and Enable BG2
|
||||
gba.DISP.DISPCNT.Set(gba.DISPCNT_BGMODE_3<<gba.DISPCNT_BGMODE_Pos |
|
||||
gba.DISPCNT_SCREENDISPLAY_BG2_ENABLE<<gba.DISPCNT_SCREENDISPLAY_BG2_Pos)
|
||||
}
|
||||
|
||||
func (d FramebufDisplay) Size() (x, y int16) {
|
||||
|
|
|
@ -5,37 +5,13 @@ package interrupt
|
|||
// This is good documentation of the GBA: https://www.akkit.org/info/gbatek.htm
|
||||
|
||||
import (
|
||||
"runtime/volatile"
|
||||
"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)))
|
||||
"device/gba"
|
||||
)
|
||||
|
||||
// Enable enables this interrupt. Right after calling this function, the
|
||||
// interrupt may be invoked if it was already pending.
|
||||
func (irq Interrupt) Enable() {
|
||||
regInterruptEnable.SetBits(1 << uint(irq.num))
|
||||
gba.INTERRUPT.IE.SetBits(1 << uint(irq.num))
|
||||
}
|
||||
|
||||
var inInterrupt bool
|
||||
|
@ -43,10 +19,10 @@ var inInterrupt bool
|
|||
//export handleInterrupt
|
||||
func handleInterrupt() {
|
||||
inInterrupt = true
|
||||
flags := regInterruptRequestFlags.Get()
|
||||
flags := gba.INTERRUPT.IF.Get()
|
||||
for i := 0; i < 14; i++ {
|
||||
if flags&(1<<uint(i)) != 0 {
|
||||
regInterruptRequestFlags.Set(1 << uint(i)) // acknowledge interrupt
|
||||
gba.INTERRUPT.IF.Set(1 << uint(i)) // acknowledge interrupt
|
||||
callInterruptHandler(i)
|
||||
}
|
||||
}
|
||||
|
@ -62,34 +38,34 @@ func callHandlers(num int)
|
|||
|
||||
func callInterruptHandler(id int) {
|
||||
switch id {
|
||||
case IRQ_VBLANK:
|
||||
callHandlers(IRQ_VBLANK)
|
||||
case IRQ_HBLANK:
|
||||
callHandlers(IRQ_HBLANK)
|
||||
case IRQ_VCOUNT:
|
||||
callHandlers(IRQ_VCOUNT)
|
||||
case IRQ_TIMER0:
|
||||
callHandlers(IRQ_TIMER0)
|
||||
case IRQ_TIMER1:
|
||||
callHandlers(IRQ_TIMER1)
|
||||
case IRQ_TIMER2:
|
||||
callHandlers(IRQ_TIMER2)
|
||||
case IRQ_TIMER3:
|
||||
callHandlers(IRQ_TIMER3)
|
||||
case IRQ_COM:
|
||||
callHandlers(IRQ_COM)
|
||||
case IRQ_DMA0:
|
||||
callHandlers(IRQ_DMA0)
|
||||
case IRQ_DMA1:
|
||||
callHandlers(IRQ_DMA1)
|
||||
case IRQ_DMA2:
|
||||
callHandlers(IRQ_DMA2)
|
||||
case IRQ_DMA3:
|
||||
callHandlers(IRQ_DMA3)
|
||||
case IRQ_KEYPAD:
|
||||
callHandlers(IRQ_KEYPAD)
|
||||
case IRQ_GAMEPAK:
|
||||
callHandlers(IRQ_GAMEPAK)
|
||||
case gba.IRQ_VBLANK:
|
||||
callHandlers(gba.IRQ_VBLANK)
|
||||
case gba.IRQ_HBLANK:
|
||||
callHandlers(gba.IRQ_HBLANK)
|
||||
case gba.IRQ_VCOUNT:
|
||||
callHandlers(gba.IRQ_VCOUNT)
|
||||
case gba.IRQ_TIMER0:
|
||||
callHandlers(gba.IRQ_TIMER0)
|
||||
case gba.IRQ_TIMER1:
|
||||
callHandlers(gba.IRQ_TIMER1)
|
||||
case gba.IRQ_TIMER2:
|
||||
callHandlers(gba.IRQ_TIMER2)
|
||||
case gba.IRQ_TIMER3:
|
||||
callHandlers(gba.IRQ_TIMER3)
|
||||
case gba.IRQ_COM:
|
||||
callHandlers(gba.IRQ_COM)
|
||||
case gba.IRQ_DMA0:
|
||||
callHandlers(gba.IRQ_DMA0)
|
||||
case gba.IRQ_DMA1:
|
||||
callHandlers(gba.IRQ_DMA1)
|
||||
case gba.IRQ_DMA2:
|
||||
callHandlers(gba.IRQ_DMA2)
|
||||
case gba.IRQ_DMA3:
|
||||
callHandlers(gba.IRQ_DMA3)
|
||||
case gba.IRQ_KEYPAD:
|
||||
callHandlers(gba.IRQ_KEYPAD)
|
||||
case gba.IRQ_GAMEPAK:
|
||||
callHandlers(gba.IRQ_GAMEPAK)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,9 +83,9 @@ type State uint8
|
|||
// as you called Disable (this happens naturally with the pattern above).
|
||||
func Disable() (state State) {
|
||||
// Save the previous interrupt state.
|
||||
state = State(regGlobalInterruptEnable.Get())
|
||||
state = State(gba.INTERRUPT.PAUSE.Get())
|
||||
// Disable all interrupts.
|
||||
regGlobalInterruptEnable.Set(0)
|
||||
gba.INTERRUPT.PAUSE.Set(0)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -119,7 +95,7 @@ func Disable() (state State) {
|
|||
// cricital sections.
|
||||
func Restore(state 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.
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче