Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/tools/src/game/crash.c
7861 views
1
/* SM64 Crash Handler */
2
3
#include <sm64.h>
4
5
#include "crash.h"
6
7
extern u32 exceptionRegContext[];
8
9
extern char *pAssertFile;
10
extern int nAssertLine;
11
extern char *pAssertExpression;
12
extern int nAssertStopProgram;
13
14
u16 fbFillColor = 0xFFFF;
15
u16 fbShadeColor = 0x0000;
16
u16 *fbAddress = NULL;
17
18
extern u8 crashFont[];
19
20
const char *szErrCodes[] = {
21
"INTERRUPT",
22
"TLB MOD",
23
"UNMAPPED LOAD ADDR",
24
"UNMAPPED STORE ADDR",
25
"BAD LOAD ADDR",
26
"BAD STORE ADDR",
27
"BUS ERR ON INSTR FETCH",
28
"BUS ERR ON LOADSTORE",
29
"SYSCALL",
30
"BREAKPOINT",
31
"UNKNOWN INSTR",
32
"COP UNUSABLE",
33
"ARITHMETIC OVERFLOW",
34
"TRAP EXC",
35
"VIRTUAL COHERENCY INSTR",
36
"FLOAT EXC",
37
};
38
39
const char *szGPRegisters1[] = { "R0", "AT", "V0", "V1", "A0", "A1", "A2", "A3",
40
"T0", "T1", "T2", "T3", "T4", "T5", "T6", NULL };
41
42
const char *szGPRegisters2[] = { "T7", "S0", "S1", "S2", "S3", "S4",
43
"S5", "S6", "S7", "T8", "T9", /*"K0", "K1",*/
44
"GP", "SP", "FP", "RA", NULL };
45
46
int crash_strlen(char *str) {
47
int len = 0;
48
while (*str++) {
49
len++;
50
}
51
return len;
52
}
53
54
void show_crash_screen_and_hang(void) {
55
u32 cause;
56
u32 epc;
57
u8 errno;
58
59
fb_set_address((void *) (*(u32 *) 0xA4400004 | 0x80000000)); // replace me
60
61
cause = cop0_get_cause();
62
epc = cop0_get_epc();
63
64
errno = (cause >> 2) & 0x1F;
65
66
if (nAssertStopProgram == 0) {
67
fbFillColor = 0x6253;
68
fb_fill(10, 10, 300, 220);
69
70
fb_print_str(80, 20, "AN ERROR HAS OCCURRED!");
71
fb_print_int_hex(80, 30, errno, 8);
72
fb_print_str(95, 30, szErrCodes[errno]);
73
74
if (errno >= 2 && errno <= 5) {
75
/*
76
2 UNMAPPED LOAD ADDR
77
3 UNMAPPED STORE ADDR
78
4 BAD LOAD ADDR
79
5 BAD STORE ADDR
80
*/
81
u32 badvaddr = cop0_get_badvaddr();
82
83
fb_print_str(145, 50, "VA");
84
fb_print_int_hex(160, 50, badvaddr, 32);
85
}
86
} else {
87
int afterFileX;
88
int exprBoxWidth;
89
fbFillColor = 0x5263;
90
fb_fill(10, 10, 300, 220);
91
92
fb_print_str(80, 20, "ASSERTION FAILED!");
93
94
afterFileX = fb_print_str(80, 30, pAssertFile);
95
fb_print_str(afterFileX, 30, ":");
96
fb_print_uint(afterFileX + 5, 30, nAssertLine);
97
98
exprBoxWidth = (crash_strlen(pAssertExpression) * 5) + 2;
99
fbFillColor = 0x0001;
100
fb_fill(80 - 1, 40 - 1, exprBoxWidth, 10);
101
fb_print_str(80, 40, pAssertExpression);
102
}
103
104
fb_print_str(80, 50, "PC");
105
fb_print_int_hex(95, 50, epc, 32);
106
107
fb_print_gpr_states(80, 70, szGPRegisters1, &exceptionRegContext[6 + 0]);
108
fb_print_gpr_states(145, 70, szGPRegisters2, &exceptionRegContext[6 + 15 * 2]);
109
110
fb_swap();
111
osWritebackDCacheAll();
112
113
while (1) // hang forever
114
{
115
UNUSED volatile int t = 0; // keep pj64 happy
116
}
117
}
118
119
u8 ascii_to_idx(char c) {
120
return c - 0x20;
121
}
122
123
void fb_set_address(void *address) {
124
fbAddress = (u16 *) address;
125
}
126
127
void fb_swap() {
128
// update VI frame buffer register
129
// todo other registers
130
*(u32 *) (0xA4400004) = (u32) fbAddress & 0x00FFFFFF;
131
}
132
133
void fb_fill(int baseX, int baseY, int width, int height) {
134
int y, x;
135
136
for (y = baseY; y < baseY + height; y++) {
137
for (x = baseX; x < baseX + width; x++) {
138
fbAddress[y * 320 + x] = fbFillColor;
139
}
140
}
141
}
142
143
void fb_draw_char(int x, int y, u8 idx) {
144
u16 *out = &fbAddress[y * 320 + x];
145
const u8 *in = &crashFont[idx * 3];
146
int nbyte;
147
int nrow;
148
int ncol;
149
150
for (nbyte = 0; nbyte < 3; nbyte++) {
151
u8 curbyte = in[nbyte];
152
for (nrow = 0; nrow < 2; nrow++) {
153
for (ncol = 0; ncol < 4; ncol++) {
154
u8 px = curbyte & (1 << (7 - (nrow * 4 + ncol)));
155
if (px != 0) {
156
out[ncol] = fbFillColor;
157
}
158
}
159
out += 320;
160
}
161
}
162
}
163
164
void fb_draw_char_shaded(int x, int y, u8 idx) {
165
fbFillColor = 0x0001;
166
fb_draw_char(x - 1, y + 1, idx);
167
168
fbFillColor = 0xFFFF;
169
fb_draw_char(x, y, idx);
170
}
171
172
int fb_print_str(int x, int y, const char *str) {
173
while (1) {
174
int yoffs = 0;
175
u8 idx;
176
char c = *str++;
177
178
if (c == '\0') {
179
break;
180
}
181
182
if (c == ' ') {
183
x += 5;
184
continue;
185
}
186
187
switch (c) {
188
case 'j':
189
case 'g':
190
case 'p':
191
case 'q':
192
case 'y':
193
case 'Q':
194
yoffs = 1;
195
break;
196
case ',':
197
yoffs = 2;
198
break;
199
}
200
201
idx = ascii_to_idx(c);
202
fb_draw_char_shaded(x, y + yoffs, idx);
203
x += 5;
204
}
205
206
return x;
207
}
208
209
void fb_print_int_hex(int x, int y, u32 value, int nbits) {
210
nbits -= 4;
211
212
while (nbits >= 0) {
213
int nib = ((value >> nbits) & 0xF);
214
u8 idx;
215
216
if (nib > 9) {
217
idx = ('A' - 0x20) + (nib - 0xa);
218
} else {
219
idx = ('0' - 0x20) + nib;
220
}
221
222
fb_draw_char_shaded(x, y, idx);
223
x += 5;
224
225
nbits -= 4;
226
}
227
}
228
229
int fb_print_uint(int x, int y, u32 value) {
230
int nchars = 0;
231
232
int v = value;
233
int i;
234
while (v /= 10) {
235
nchars++;
236
}
237
238
x += nchars * 5;
239
240
for (i = nchars; i >= 0; i--) {
241
fb_draw_char_shaded(x, y, ('0' - 0x20) + (value % 10));
242
value /= 10;
243
x -= 5;
244
}
245
246
return (x + nchars * 5);
247
}
248
249
void fb_print_gpr_states(int x, int y, const char *regNames[], u32 *regContext) {
250
int i;
251
for (i = 0;; i++) {
252
if (regNames[i] == NULL) {
253
break;
254
}
255
256
fb_print_str(x, y, regNames[i]);
257
fb_print_int_hex(x + 15, y, regContext[i * 2 + 1], 32);
258
y += 10;
259
}
260
}
261
262