Skip to content

Commit 7cbbfd6

Browse files
zoeydeadprogram
authored andcommitted
gba: add support for mGBA debugging
Implements `putchar` when `mgbadebug` build tag is set which outputs text through the mGBA debugging output interface. mGBA allows the games running in the emulator to output debug text the process to do so is: 1. set 0x4FFF780 to value of 0xC0DE 2. write text in memory 0x4FFF600 to 0x4FFF700 3. set 0x4FFF700 to the desired log level value from 0x100 (fatal) to 0x104 (debug) Once this is done mGBA will output the text in its logs view as well as through stdout. (Setting the log level to fatal also produces a dialog box with the text) The text output in the CLI is prefixed with `[DEBUG] GBA Debug: ` so I modified the regex used for address matching in panic messages to be able to read the address when the output line doesn't start with `panic`.
1 parent e8bb38f commit 7cbbfd6

3 files changed

Lines changed: 123 additions & 2 deletions

File tree

monitor.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ func ListSerialPorts() ([]SerialPortInfo, error) {
278278
return serialPortInfo, nil
279279
}
280280

281-
var addressMatch = regexp.MustCompile(`^panic: runtime error at 0x([0-9a-f]+): `)
281+
var addressMatch = regexp.MustCompile(`panic: runtime error at 0x([0-9a-f]+): `)
282282

283283
// Extract the address from the "panic: runtime error at" message.
284284
func extractPanicAddress(line []byte) uint64 {

src/runtime/runtime_arm7tdmi.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build arm7tdmi
1+
//go:build arm7tdmi && !mgbadebug
22

33
package runtime
44

src/runtime/runtime_mgba.go

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
//go:build gameboyadvance && mgbadebug
2+
3+
package runtime
4+
5+
import (
6+
_ "runtime/interrupt" // make sure the interrupt handler is defined
7+
"runtime/volatile"
8+
"unsafe"
9+
)
10+
11+
var (
12+
// Setting this memory address to 0xC0DE enables mGBA's debug printing
13+
debugEnable = (*volatile.Register16)(unsafe.Pointer(uintptr(0x4FFF780)))
14+
// mGBA supports log levels from 0x100(fatal) to 0x104(debug)
15+
logLevel uint16 = 0x104 // use the debug log level
16+
// Once we are ready to output we set the debug flags register to logLevel
17+
// mGBA will output the text and then clear the text buffer when set
18+
debugFlags = (*volatile.Register16)(unsafe.Pointer(uintptr(0x4FFF700)))
19+
20+
textBuffer = (*[255]byte)(unsafe.Pointer(uintptr(0x4FFF600)))
21+
index = 0
22+
)
23+
24+
func putchar(c byte) {
25+
if c == '\n' || index >= len(textBuffer) {
26+
debugFlags.Set(logLevel)
27+
index = 0
28+
29+
// mGBA automatically prints a new line so we can ignore it
30+
if c == '\n' {
31+
return
32+
}
33+
}
34+
35+
textBuffer[index] = c
36+
index++
37+
}
38+
39+
func getchar() byte {
40+
// dummy, TODO
41+
return 0
42+
}
43+
44+
func buffered() int {
45+
// dummy, TODO
46+
return 0
47+
}
48+
49+
//go:extern _sbss
50+
var _sbss [0]byte
51+
52+
//go:extern _ebss
53+
var _ebss [0]byte
54+
55+
//go:extern _sdata
56+
var _sdata [0]byte
57+
58+
//go:extern _sidata
59+
var _sidata [0]byte
60+
61+
//go:extern _edata
62+
var _edata [0]byte
63+
64+
// Entry point for Go. Initialize all packages and call main.main().
65+
//
66+
//export main
67+
func main() {
68+
// Initialize .data and .bss sections.
69+
preinit()
70+
71+
// Enable mGBA debugging.
72+
debugEnable.Set(0xC0DE)
73+
74+
// Run program.
75+
run()
76+
}
77+
78+
func preinit() {
79+
// Initialize .bss: zero-initialized global variables.
80+
ptr := unsafe.Pointer(&_sbss)
81+
for ptr != unsafe.Pointer(&_ebss) {
82+
*(*uint32)(ptr) = 0
83+
ptr = unsafe.Add(ptr, 4)
84+
}
85+
86+
// Initialize .data: global variables initialized from flash.
87+
src := unsafe.Pointer(&_sidata)
88+
dst := unsafe.Pointer(&_sdata)
89+
for dst != unsafe.Pointer(&_edata) {
90+
*(*uint32)(dst) = *(*uint32)(src)
91+
dst = unsafe.Add(dst, 4)
92+
src = unsafe.Add(src, 4)
93+
}
94+
}
95+
96+
func ticksToNanoseconds(ticks timeUnit) int64 {
97+
return int64(ticks)
98+
}
99+
100+
func nanosecondsToTicks(ns int64) timeUnit {
101+
return timeUnit(ns)
102+
}
103+
104+
func ticks() timeUnit {
105+
// TODO
106+
return 0
107+
}
108+
109+
func sleepTicks(d timeUnit) {
110+
// TODO
111+
}
112+
113+
func exit(code int) {
114+
abort()
115+
}
116+
117+
func abort() {
118+
// TODO
119+
for {
120+
}
121+
}

0 commit comments

Comments
 (0)