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