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