starting to separate platform-specific code to facilitate a PC build
[gbajam22] / src / gba / debug.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <ctype.h>
4 #include <stdarg.h>
5 #include "gbaregs.h"
6 #include "intr.h"
7 #include "debug.h"
8 #include "util.h"
9
10 uint16_t vblperf_color[] = {
11         /* grn  blue   cyan  yellow  orng    red     purple  d.green purple ... */
12         /* 60    30     20     15     12      10      8.5     7.5    ... */
13         0x3e0, 0xf863, 0xffc0, 0x3ff, 0x1ff, 0x001f, 0xf81f, 0x1e0, 0xf81f, 0xf81f, 0xf81f
14 };
15
16 void vblperf_setcolor(int palidx)
17 {
18         vblperf_palptr = (uint16_t*)CRAM_BG_ADDR + palidx;
19 }
20
21
22 uint32_t panic_regs[16];
23 void get_panic_regs(void);
24
25 void panic(void *pc, const char *fmt, ...)
26 {
27         int y;
28         va_list ap;
29         uint32_t *reg;
30
31         get_panic_regs();
32
33         intr_disable();
34         REG_DISPCNT = 4 | DISPCNT_BG2;
35
36         set_bg_color(0, 31, 0, 0);
37         set_bg_color(0xff, 31, 31, 31);
38
39         fillblock_16byte((void*)VRAM_LFB_FB0_ADDR, 0, 240 * 160 / 16);
40
41         fillblock_16byte((unsigned char*)VRAM_LFB_FB0_ADDR + 240 * 3, 0xffffffff, 240 / 16);
42         dbg_drawstr(44, 0, " Panic at %p ", pc);
43
44         va_start(ap, fmt);
45         y = dbg_vdrawstr(0, 12, fmt, ap) + 8;
46         va_end(ap);
47
48         fillblock_16byte((unsigned char*)VRAM_LFB_FB0_ADDR + 240 * (y + 4), 0xffffffff, 240 / 16);
49         y += 8;
50
51         reg = panic_regs;
52         y = dbg_drawstr(0, y, " r0 %08x  r1 %08x\n r2 %08x  r3 %08x\n r4 %08x  r5 %08x\n r6 %08x  r7 %08x\n",
53                         reg[0], reg[1], reg[2], reg[3], reg[4], reg[5], reg[6], reg[7]);
54         y = dbg_drawstr(0, y, " r8 %08x  r9 %08x\nr10 %08x r11 %08x\n ip %08x  sp %08x\n lr %08x  pc %08x\n",
55                         reg[8], reg[9], reg[10], reg[11], reg[12], reg[13], reg[14], reg[15]);
56
57         /* stop any sound/music playback */
58         REG_SOUNDCNT_H = SCNT_DSA_CLRFIFO | SCNT_DSB_CLRFIFO;
59         REG_TMCNT_H(1) &= ~TMCNT_EN;
60         REG_DMA1CNT_H = 0;
61         REG_DMA2CNT_H = 0;
62
63         for(;;);
64 }
65
66 void dbg_drawglyph(int x, int y, int c)
67 {
68         int i;
69         uint16_t pp;
70         unsigned char row;
71         uint16_t *ptr = (uint16_t*)VRAM_LFB_FB0_ADDR + (y << 7) - (y << 3) + (x >> 1);
72         unsigned char *fnt = font_8x8 + ((c & 0xff) << 3);
73
74         for(i=0; i<8; i++) {
75                 row = *fnt++;
76                 pp = row & 0x80 ? 0xff : 0;
77                 *ptr++ = pp | (row & 0x40 ? 0xff00 : 0);
78                 pp = row & 0x20 ? 0xff : 0;
79                 *ptr++ = pp | (row & 0x10 ? 0xff00 : 0);
80                 pp = row & 0x08 ? 0xff : 0;
81                 *ptr++ = pp | (row & 0x04 ? 0xff00 : 0);
82                 pp = row & 0x02 ? 0xff : 0;
83                 *ptr++ = pp | (row & 0x01 ? 0xff00 : 0);
84                 ptr += 120 - 4;
85         }
86 }
87
88 int dbg_vdrawstr(int x, int y, const char *fmt, va_list ap)
89 {
90         int startx, c;
91         char buf[128];
92         char *ptr = buf;
93
94         vsnprintf(buf, sizeof buf, fmt, ap);
95
96         startx = x;
97         while(*ptr) {
98                 if(y >= 160) break;
99
100                 c = *ptr++;
101                 switch(c) {
102                 case '\n':
103                         y += 8;
104                 case '\r':
105                         x = startx;
106                         break;
107
108                 default:
109                         dbg_drawglyph(x, y, c);
110                         x += 8;
111                         if(x >= 240 - 8) {
112                                 while(*ptr && isspace(*ptr)) ptr++;
113                                 x = 0;
114                                 y += 8;
115                         }
116                 }
117         }
118
119         return y;
120 }
121
122 int dbg_drawstr(int x, int y, const char *fmt, ...)
123 {
124         int res;
125         va_list ap;
126
127         va_start(ap, fmt);
128         res = dbg_vdrawstr(x, y, fmt, ap);
129         va_end(ap);
130         return res;
131 }
132
133 #ifdef EMUBUILD
134 #define REG_DBG_ENABLE  REG16(0xfff780)
135 #define REG_DBG_FLAGS   REG16(0xfff700)
136 #define REG_DBG_STR             REG8(0xfff600)
137
138 /*__attribute__((target("arm")))*/
139 void emuprint(const char *fmt, ...)
140 {
141         static int opened;
142         char buf[128];
143         va_list ap;
144
145         if(!opened) {
146                 REG_DBG_ENABLE = 0xc0de;
147                 if(REG_DBG_ENABLE != 0x1dea) {
148                         return;
149                 }
150                 opened = 1;
151         }
152
153         va_start(ap, fmt);
154         vsnprintf(buf, sizeof buf, fmt, ap);
155         va_end(ap);
156
157         strcpy((char*)0x4fff600, buf);
158         REG_DBG_FLAGS = 0x104;  /* debug message */
159
160         /*
161         asm volatile(
162                 "mov r0, %0\n\t"
163                 "swi 0xff0000\n\t" :
164                 : "r" (buf)
165                 : "r0"
166         );
167         */
168 }
169 #else
170 void emuprint(const char *fmt, ...)
171 {
172 }
173 #endif