diff --git a/.vscode/launch.json b/.vscode/launch.json index 6c42d76..bca8e4d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -40,17 +40,15 @@ "linux": { "args": [ "-f", "/dev/ttyUSB0", - "-b", "3", + "-b", "4", "-q", - "sw/n64/build/n64boot.bin", ] }, "windows": { "args": [ "-f", "\\\\.\\D:", - "-b", "3", + "-b", "4", "-q", - "sw/n64/build/n64boot.bin", ] } }, diff --git a/sw/n64/src/error.c b/sw/n64/src/error.c index c42b6e2..4630e24 100644 --- a/sw/n64/src/error.c +++ b/sw/n64/src/error.c @@ -2,7 +2,7 @@ #include "exception.h" -void error_display (const char *message) { +void error_display (const char *fmt, ...) { EXCEPTION_TRIGGER(TRIGGER_CODE_ERROR); while (1); } diff --git a/sw/n64/src/error.h b/sw/n64/src/error.h index 2cf69e7..af9a504 100644 --- a/sw/n64/src/error.h +++ b/sw/n64/src/error.h @@ -2,7 +2,7 @@ #define ERROR_H__ -void error_display (const char *message); +void error_display (const char *fmt, ...); #endif diff --git a/sw/n64/src/exception.c b/sw/n64/src/exception.c index 3fa4a3f..d1951ba 100644 --- a/sw/n64/src/exception.c +++ b/sw/n64/src/exception.c @@ -147,21 +147,29 @@ static void exception_draw_character (int x, int y, char c) { } } -static void exception_print_string (int x, int y, const char *s) { +static void exception_print_string (int *x, int *y, const char *s) { + int line_x = *x; + while (*s != '\0') { - exception_draw_character(x, y, *s++); - x += FONT_WIDTH; + if (*s == '\n') { + line_x = BORDER_WIDTH; + *y += LINE_HEIGHT; + s++; + } else { + exception_draw_character(line_x, *y, *s++); + line_x += FONT_WIDTH; + } } } static void exception_print (int *x, int *y, const char* fmt, ...) { - char line[80]; + char line[256]; va_list args; va_start(args, fmt); vsniprintf(line, sizeof(line), fmt, args); - exception_print_string(*x, *y, line); + exception_print_string(x, y, line); *y += LINE_HEIGHT; va_end(args); @@ -199,8 +207,7 @@ void exception_fatal_handler (uint32_t exception_code, uint32_t interrupt_mask, exception_init_screen(); - exception_print(&x, &y, "%s at pc: 0x%08lX", exception_get_description(exception_code), e->epc.u32); - exception_print(&x, &y, ""); + exception_print(&x, &y, "%s at pc: 0x%08lX\n", exception_get_description(exception_code), e->epc.u32); exception_print(&x, &y, "sr: 0x%08lX, cr: 0x%08lX", e->sr, e->cr); exception_print(&x, &y, "zr: 0x%08lX, at: 0x%08lX, v0: 0x%08lX, v1: 0x%08lX", e->zr.u32, e->at.u32, e->v0.u32, e->v1.u32); exception_print(&x, &y, "a0: 0x%08lX, a1: 0x%08lX, a2: 0x%08lX, a3: 0x%08lX", e->a0.u32, e->a1.u32, e->a2.u32, e->a3.u32); @@ -209,12 +216,9 @@ void exception_fatal_handler (uint32_t exception_code, uint32_t interrupt_mask, exception_print(&x, &y, "s0: 0x%08lX, s1: 0x%08lX, s2: 0x%08lX, s3: 0x%08lX", e->s0.u32, e->s1.u32, e->s2.u32, e->s3.u32); exception_print(&x, &y, "s4: 0x%08lX, s5: 0x%08lX, s6: 0x%08lX, s7: 0x%08lX", e->s4.u32, e->s5.u32, e->s6.u32, e->s7.u32); exception_print(&x, &y, "t8: 0x%08lX, t9: 0x%08lX, k0: 0x%08lX, k1: 0x%08lX", e->t8.u32, e->t9.u32, e->k0.u32, e->k1.u32); - exception_print(&x, &y, "gp: 0x%08lX, sp: 0x%08lX, fp: 0x%08lX, ra: 0x%08lX", e->gp.u32, e->sp.u32, e->fp.u32, e->ra.u32); - exception_print(&x, &y, ""); - exception_print(&x, &y, "0x%08lX: 0x%08lX = [%4s]", (uint32_t) (&SC64->VERSION), sc64_version, (char *) (&sc64_version)); - exception_print(&x, &y, ""); - exception_print(&x, &y, "------------------------------------------------------------------------"); - exception_print(&x, &y, ""); + exception_print(&x, &y, "gp: 0x%08lX, sp: 0x%08lX, fp: 0x%08lX, ra: 0x%08lX\n", e->gp.u32, e->sp.u32, e->fp.u32, e->ra.u32); + exception_print(&x, &y, "0x%08lX: 0x%08lX = [%4s]\n", (uint32_t) (&SC64->VERSION), sc64_version, (char *) (&sc64_version)); + exception_print(&x, &y, "------------------------------------------------------------------------\n"); if (exception_code == EXCEPTION_INTERRUPT) { if (interrupt_mask & INTERRUPT_MASK_TIMER) { @@ -224,14 +228,12 @@ void exception_fatal_handler (uint32_t exception_code, uint32_t interrupt_mask, uint32_t code = (((*instruction_address) & SYSCALL_CODE_MASK) >> SYSCALL_CODE_BIT); if (code == TRIGGER_CODE_ERROR) { - const char *message = (const char *) (e->a0.u32); - exception_print(&x, &y, "%s", message); + exception_print(&x, &y, (const char *) (e->a0.u32), e->a1.u32, e->a2.u32, e->a3.u32); } else if (code == TRIGGER_CODE_ASSERT) { const char *file = (const char *) (e->a0.u32); int line = (int) (e->a1.u32); const char *func = (const char *) (e->a2.u32); const char *failedexpr = (const char *) (e->a3.u32); - exception_print(&x, &y, "Assertion \"%s\" failed:", failedexpr); exception_print(&x, &y, " file \"%s\", line %d, %s%s", file, line, func ? "function: " : "", func); } diff --git a/sw/n64/src/exception.h b/sw/n64/src/exception.h index c67dfc5..49c0f74 100644 --- a/sw/n64/src/exception.h +++ b/sw/n64/src/exception.h @@ -4,8 +4,8 @@ #define EXCEPTION_TRIGGER(code) { asm volatile ("syscall %[c]\n" :: [c] "i" (code)); } -#define TRIGGER_CODE_ERROR (0) -#define TRIGGER_CODE_ASSERT (1) +#define TRIGGER_CODE_ERROR (0) +#define TRIGGER_CODE_ASSERT (16) #endif diff --git a/sw/n64/src/main.c b/sw/n64/src/main.c index 98bcbf2..314f2c8 100644 --- a/sw/n64/src/main.c +++ b/sw/n64/src/main.c @@ -25,12 +25,12 @@ void main (void) { boot_info.device_type = BOOT_DEVICE_TYPE_DD; break; - case BOOT_MODE_DIRECT: + case BOOT_MODE_MENU_USB: storage_run_menu(STORAGE_BACKEND_USB, &boot_info, &sc64_info); break; default: - error_display("Unknown boot mode selected"); + error_display("Unknown boot mode selected [%d]", sc64_info.boot_mode); break; } diff --git a/sw/n64/src/sc64.h b/sw/n64/src/sc64.h index fbbd205..9ca4e8d 100644 --- a/sw/n64/src/sc64.h +++ b/sw/n64/src/sc64.h @@ -71,6 +71,7 @@ typedef enum { BOOT_MODE_ROM = 1, BOOT_MODE_DDIPL = 2, BOOT_MODE_DIRECT = 3, + BOOT_MODE_MENU_USB = 4, } boot_mode_t; typedef struct { diff --git a/sw/n64/src/storage.c b/sw/n64/src/storage.c index 72110f2..4ff35ec 100644 --- a/sw/n64/src/storage.c +++ b/sw/n64/src/storage.c @@ -5,9 +5,35 @@ #include "fatfs/ff.h" -#define FF_CHECK(x) { \ +static const char *fatfs_error_codes[] = { + "Succeeded [0]", + "A hard error occurred in the low level disk I/O layer [1]", + "Assertion failed [2]", + "The physical drive cannot work [3]", + "Could not find the file [4]", + "Could not find the path [5]", + "The path name format is invalid [6]", + "Access denied due to prohibited access or directory full [7]", + "Access denied due to prohibited access [8]", + "The file/directory object is invalid [9]", + "The physical drive is write protected [10]", + "The logical drive number is invalid [11]", + "The volume has no work area [12]", + "There is no valid FAT volume [13]", + "The f_mkfs() aborted due to any problem [14]", + "Could not get a grant to access the volume within defined period [15]", + "The operation is rejected according to the file sharing policy [16]", + "LFN working buffer could not be allocated [17]", + "Number of open files > FF_FS_LOCK [18]", + "Given parameter is invalid [19]", +}; + + +#define FF_CHECK(x, message) { \ FRESULT fatfs_result = x; \ - assert(fatfs_result == FR_OK); \ + if (fatfs_result != FR_OK) { \ + error_display("%s:\n %s", message, fatfs_error_codes[fatfs_result]); \ + } \ } @@ -16,20 +42,20 @@ void storage_run_menu (storage_backend_t storage_backend, boot_info_t *boot_info FIL fil; if (storage_backend == STORAGE_BACKEND_SD) { - FF_CHECK(f_mount(&fs, "0:", 1)); - FF_CHECK(f_chdrive("0:")); + FF_CHECK(f_mount(&fs, "0:", 1), "Couldn't mount SD drive"); + FF_CHECK(f_chdrive("0:"), "Couldn't chdrive to SD drive"); } else if (storage_backend == STORAGE_BACKEND_USB) { - FF_CHECK(f_mount(&fs, "1:", 1)); - FF_CHECK(f_chdrive("1:")); + FF_CHECK(f_mount(&fs, "1:", 1), "Couldn't mount USB drive"); + FF_CHECK(f_chdrive("1:"), "Couldn't chdrive to USB drive"); } else { - error_display("Unknown storage backend"); + error_display("Unknown storage backend [%d]", storage_backend); } - FF_CHECK(f_open(&fil, "sc64menu.elf", FA_READ)); + FF_CHECK(f_open(&fil, "sc64menu.elf", FA_READ), "Couldn't open menu file"); // TODO: Implement ELF loader here - FF_CHECK(f_close(&fil)); + FF_CHECK(f_close(&fil), "Couldn't close menu file"); // TODO: Execute ELF here // menu(&boot_info, &sc64_info); diff --git a/sw/pc/sc64.py b/sw/pc/sc64.py index 3797cb3..32f3020 100644 --- a/sw/pc/sc64.py +++ b/sw/pc/sc64.py @@ -264,20 +264,21 @@ class SC64: def set_boot_mode(self, mode: int) -> None: - if (mode >= 0 and mode <= 3): + if (mode >= 0 and mode <= 4): self.__change_config(self.__CFG_ID_BOOT_MODE, mode) else: raise SC64Exception("Boot mode outside of supported values") def get_boot_mode_label(self, mode: int) -> None: - if (mode < 0 or mode > 3): + if (mode < 0 or mode > 4): return "Unknown" return { 0: "Load menu from SD card", 1: "Load ROM from SDRAM through bootloader", 2: "Load DDIPL from SDRAM", - 3: "Load ROM from SDRAM directly without bootloader" + 3: "Load ROM from SDRAM directly without bootloader", + 4: "Load menu from USB", }[mode]