summaryrefslogtreecommitdiff
path: root/src/debug
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug')
-rw-r--r--src/debug/crash_screen_enhancement.c221
-rw-r--r--src/debug/crash_screen_enhancement.h37
2 files changed, 258 insertions, 0 deletions
diff --git a/src/debug/crash_screen_enhancement.c b/src/debug/crash_screen_enhancement.c
new file mode 100644
index 000000000..54547908c
--- /dev/null
+++ b/src/debug/crash_screen_enhancement.c
@@ -0,0 +1,221 @@
+#include <ultra64.h>
+#include <macros.h>
+#include <types.h>
+#include <config.h>
+#include <stdarg.h>
+#include <string.h>
+#include "../crash_screen.h"
+#include "crash_screen_enhancement.h"
+
+s32 _Printf(char *(*prout)(char *, const char *, size_t), char *dst, const char *fmt, va_list args);
+
+u32 crashScreenFont2[7 * 9 + 1] = {
+ 0x70871c30,0x8988a250,0x88808290,0x88831c90,0x888402f8,0x88882210,0x71cf9c10,0xf9cf9c70,0x8228a288,0xf200a288,0x0bc11c78,0x0a222208,0x8a222288,0x71c21c70,0x23c738f8,0x5228a480,0x8a282280,0x8bc822f0,0xfa282280,0x8a28a480,0x8bc738f8,0xf9c89c08,0x82288808,0x82088808,0xf2ef8808,0x82288888,0x82288888,0x81c89c70,0x8a08a270,0x920da288,0xa20ab288,0xc20aaa88,0xa208a688,0x9208a288,0x8be8a270,0xf1cf1cf8,0x8a28a220,0x8a28a020,0xf22f1c20,0x82aa0220,0x82492220,0x81a89c20,0x8a28a288,0x8a28a288,0x8a289488,0x8a2a8850,0x894a9420,0x894aa220,0x70852220,0xf8011000,0x08020800,0x10840400,0x20040470,0x40840400,0x80020800,0xf8011000,0x70800000,0x88822200,0x08820400,0x108f8800,0x20821000,0x00022200,0x20800020
+};
+
+extern u64 osClockRate;
+
+u8 gCrashScreenCharToGlyph[128] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, 43, -1, -1, 37, 38, -1, 42,
+ -1, 39, 44, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 36, -1, -1, -1, -1, 40, -1, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
+};
+
+char *gCauseDesc[18] = {
+ "Interrupt",
+ "TLB modification",
+ "TLB exception on load",
+ "TLB exception on store",
+ "Address error on load",
+ "Address error on store",
+ "Bus error on inst.",
+ "Bus error on data",
+ "System call exception",
+ "Breakpoint exception",
+ "Reserved instruction",
+ "Coprocessor unusable",
+ "Arithmetic overflow",
+ "Trap exception",
+ "Virtual coherency on inst.",
+ "Floating point exception",
+ "Watchpoint exception",
+ "Virtual coherency on data",
+};
+
+char *gFpcsrDesc[6] = {
+ "Unimplemented operation", "Invalid operation", "Division by zero", "Overflow", "Underflow",
+ "Inexact operation",
+};
+
+void crash_screen_draw_glyph_enhancement(s32 x, s32 y, s32 glyph) {
+ const u32 *data;
+ u16 *ptr;
+ u32 bit;
+ u32 rowMask;
+ s32 i, j;
+
+ data = &crashScreenFont2[glyph / 5 * 7];
+ ptr = pFramebuffer + SCREEN_WIDTH * y + x;
+
+ for (i = 0; i < 7; i++) {
+ bit = 0x80000000U >> ((glyph % 5) * 6);
+ rowMask = *data++;
+
+ for (j = 0; j < 6; j++) {
+ *ptr++ = (bit & rowMask) ? 0xffff : 1;
+ bit >>= 1;
+ }
+ ptr += SCREEN_WIDTH - 6;
+ }
+}
+
+void crash_screen_draw_rect(s32 x, s32 y, s32 w, s32 h) {
+ u16 *ptr;
+ s32 i, j;
+
+ ptr = pFramebuffer + SCREEN_WIDTH * y + x;
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ // 0xe738 = 0b1110011100111000
+ *ptr = ((*ptr & 0xe738) >> 2) | 1;
+ ptr++;
+ }
+ ptr += SCREEN_WIDTH - w;
+ }
+}
+
+static char *write_to_buf(char *buffer, const char *data, size_t size) {
+ return (char *) memcpy(buffer, data, size) + size;
+}
+
+void crash_screen_print(s32 x, s32 y, const char *fmt, ...) {
+ char *ptr;
+ u32 glyph;
+ s32 size;
+ char buf[0x100];
+
+ va_list args;
+ va_start(args, fmt);
+
+ size = _Printf(write_to_buf, buf, fmt, args);
+
+ if (size > 0) {
+ ptr = buf;
+
+
+ while (size > 0) {
+
+
+ glyph = gCrashScreenCharToGlyph[*ptr & 0x7f];
+
+ if (glyph != 0xff) {
+ crash_screen_draw_glyph_enhancement(x, y, glyph);
+ }
+
+ size--;
+
+ ptr++;
+ x += 6;
+ }
+ }
+
+ va_end(args);
+}
+
+void crash_screen_sleep(s32 ms) {
+ u64 cycles = ms * 1000LL * osClockRate / 1000000ULL;
+ osSetTime(0);
+ while (osGetTime() < cycles) {
+ }
+}
+
+void crash_screen_print_float_reg(s32 x, s32 y, s32 regNum, void *addr) {
+ u32 bits;
+ s32 exponent;
+
+ bits = *(u32 *) addr;
+ exponent = ((bits & 0x7f800000U) >> 0x17) - 0x7f;
+ if ((exponent >= -0x7e && exponent <= 0x7f) || bits == 0) {
+ crash_screen_print(x, y, "F%02d:%.3e", regNum, *(f32 *) addr);
+ } else {
+ crash_screen_print(x, y, "F%02d:---------", regNum);
+ }
+}
+
+void crash_screen_print_fpcsr(u32 fpcsr) {
+ s32 i;
+ u32 bit;
+
+ bit = 1 << 17;
+ crash_screen_print(30, 155, "FPCSR:%08XH", fpcsr);
+ for (i = 0; i < 6; i++) {
+ if (fpcsr & bit) {
+ crash_screen_print(132, 155, "(%s)", gFpcsrDesc[i]);
+ return;
+ }
+ bit >>= 1;
+ }
+}
+
+
+void crash_screen_draw(OSThread* thread) {
+ s16 cause;
+ __OSThreadContext *tc = &thread->context;
+
+ cause = (tc->cause >> 2) & 0x1f;
+ if (cause == 23) { // EXC_WATCH
+ cause = 16;
+ }
+ if (cause == 31) { // EXC_VCED
+ cause = 17;
+ }
+
+ osWritebackDCacheAll();
+
+ crash_screen_draw_rect(25, 20, 270, 25);
+ crash_screen_print(30, 25, "THREAD:%d (%s)", thread->id, gCauseDesc[cause]);
+ crash_screen_print(30, 35, "PC:%08XH SR:%08XH VA:%08XH", tc->pc, tc->sr, tc->badvaddr);
+ crash_screen_sleep(2000);
+ crash_screen_draw_rect(25, 45, 270, 185);
+ crash_screen_print(30, 50, "AT:%08XH V0:%08XH V1:%08XH", (u32) tc->at, (u32) tc->v0,
+ (u32) tc->v1);
+ crash_screen_print(30, 60, "A0:%08XH A1:%08XH A2:%08XH", (u32) tc->a0, (u32) tc->a1,
+ (u32) tc->a2);
+ crash_screen_print(30, 70, "A3:%08XH T0:%08XH T1:%08XH", (u32) tc->a3, (u32) tc->t0,
+ (u32) tc->t1);
+ crash_screen_print(30, 80, "T2:%08XH T3:%08XH T4:%08XH", (u32) tc->t2, (u32) tc->t3,
+ (u32) tc->t4);
+ crash_screen_print(30, 90, "T5:%08XH T6:%08XH T7:%08XH", (u32) tc->t5, (u32) tc->t6,
+ (u32) tc->t7);
+ crash_screen_print(30, 100, "S0:%08XH S1:%08XH S2:%08XH", (u32) tc->s0, (u32) tc->s1,
+ (u32) tc->s2);
+ crash_screen_print(30, 110, "S3:%08XH S4:%08XH S5:%08XH", (u32) tc->s3, (u32) tc->s4,
+ (u32) tc->s5);
+ crash_screen_print(30, 120, "S6:%08XH S7:%08XH T8:%08XH", (u32) tc->s6, (u32) tc->s7,
+ (u32) tc->t8);
+ crash_screen_print(30, 130, "T9:%08XH GP:%08XH SP:%08XH", (u32) tc->t9, (u32) tc->gp,
+ (u32) tc->sp);
+ crash_screen_print(30, 140, "S8:%08XH RA:%08XH", (u32) tc->s8, (u32) tc->ra);
+ crash_screen_print_fpcsr(tc->fpcsr);
+ crash_screen_print_float_reg(30, 170, 0, &tc->fp0.f.f_even);
+ crash_screen_print_float_reg(120, 170, 2, &tc->fp2.f.f_even);
+ crash_screen_print_float_reg(210, 170, 4, &tc->fp4.f.f_even);
+ crash_screen_print_float_reg(30, 180, 6, &tc->fp6.f.f_even);
+ crash_screen_print_float_reg(120, 180, 8, &tc->fp8.f.f_even);
+ crash_screen_print_float_reg(210, 180, 10, &tc->fp10.f.f_even);
+ crash_screen_print_float_reg(30, 190, 12, &tc->fp12.f.f_even);
+ crash_screen_print_float_reg(120, 190, 14, &tc->fp14.f.f_even);
+ crash_screen_print_float_reg(210, 190, 16, &tc->fp16.f.f_even);
+ crash_screen_print_float_reg(30, 200, 18, &tc->fp18.f.f_even);
+ crash_screen_print_float_reg(120, 200, 20, &tc->fp20.f.f_even);
+ crash_screen_print_float_reg(210, 200, 22, &tc->fp22.f.f_even);
+ crash_screen_print_float_reg(30, 210, 24, &tc->fp24.f.f_even);
+ crash_screen_print_float_reg(120, 210, 26, &tc->fp26.f.f_even);
+ crash_screen_print_float_reg(210, 210, 28, &tc->fp28.f.f_even);
+ crash_screen_print_float_reg(30, 220, 30, &tc->fp30.f.f_even);
+ osViBlack(FALSE);
+ osViSwapBuffer(pFramebuffer);
+}
diff --git a/src/debug/crash_screen_enhancement.h b/src/debug/crash_screen_enhancement.h
new file mode 100644
index 000000000..43fe8e10a
--- /dev/null
+++ b/src/debug/crash_screen_enhancement.h
@@ -0,0 +1,37 @@
+#include <ultra64.h>
+#include <macros.h>
+
+void crash_screen_draw(OSThread* thread);
+
+// Add this to the top of main.c or crash_screen.c
+//#define CRASH_SCREEN_ENHANCEMENT
+
+
+
+/**
+ * Example of how to force crash screen to run.
+ * Make sure to include the header crash_screen_enhancement.h in main.h
+*/
+
+// void display_and_vsync(void) {
+// profiler_log_thread5_time(BEFORE_DISPLAY_LISTS);
+// osRecvMesg(&gGfxVblankQueue, &gMainReceivedMesg, OS_MESG_BLOCK);
+// exec_display_list(&gGfxPool->spTask);
+// profiler_log_thread5_time(AFTER_DISPLAY_LISTS);
+// osRecvMesg(&gGameVblankQueue, &gMainReceivedMesg, OS_MESG_BLOCK);
+// osViSwapBuffer((void *) PHYSICAL_TO_VIRTUAL(gPhysicalFramebuffers[sRenderedFramebuffer]));
+// profiler_log_thread5_time(THREAD5_END);
+// osRecvMesg(&gGameVblankQueue, &gMainReceivedMesg, OS_MESG_BLOCK);
+// crash_screen_set_framebuffer((uintptr_t *) gPhysicalFramebuffers[sRenderedFramebuffer]);
+
+// crash_screen_draw((u16 *) gPhysicalFramebuffers[sRenderedFramebuffer], &gGameLoopThread);
+// Add this line ^
+
+// if (++sRenderedFramebuffer == 3) {
+// sRenderedFramebuffer = 0;
+// }
+// if (++sRenderingFramebuffer == 3) {
+// sRenderingFramebuffer = 0;
+// }
+// gGlobalTimer++;
+// }