diff --git a/meson.build b/meson.build index 3a12cab..e9944b4 100644 --- a/meson.build +++ b/meson.build @@ -52,7 +52,9 @@ font = custom_target( gekkoboot = executable( 'gekkoboot', 'source/main.c', - 'source/utils.c', + 'source/filesystem.c', + 'source/shortcut.c', + 'source/cli_args.c', 'source/fatfs/ff.c', 'source/fatfs/ffsystem.c', 'source/fatfs/ffunicode.c', diff --git a/source/cli_args.c b/source/cli_args.c new file mode 100644 index 0000000..fd30424 --- /dev/null +++ b/source/cli_args.c @@ -0,0 +1,78 @@ +#include "cli_args.h" +#include +#include +#include + +#define MAX_NUM_ARGV 1024 + +// 0 - Failure +// 1 - OK/Empty +int +parse_cli_args(struct __argv *argv, char *cli_option_str) { + kprintf("Parsing CLI args...\n"); + + argv->argc = 0; + argv->length = 0; + argv->commandLine = NULL; + + char *cli = cli_option_str; + char *dol_argv[MAX_NUM_ARGV]; + int dol_argc = 0; + int size = strlen(cli_option_str); + + // Parse CLI file + // https://github.com/emukidid/swiss-gc/blob/a0fa06d81360ad6d173acd42e4dd5495e268de42/cube/swiss/source/swiss.c#L1236 + // First argument is at the beginning of the file + if (cli[0] != '\r' && cli[0] != '\n') { + dol_argv[dol_argc] = cli; + dol_argc++; + } + + // Search for the others after each newline + for (int i = 0; i < size; i++) { + if (cli[i] == '\r' || cli[i] == '\n') { + cli[i] = '\0'; + } else if (cli[i - 1] == '\0') { + dol_argv[dol_argc] = cli + i; + dol_argc++; + if (dol_argc >= MAX_NUM_ARGV) { + kprintf("Reached max of %i args.\n", MAX_NUM_ARGV); + break; + } + } + } + + kprintf("Found %i CLI args\n", dol_argc); + + if (!dol_argc) { + return 0; + } + + // https://github.com/emukidid/swiss-gc/blob/f5319aab248287c847cb9468325ebcf54c993fb1/cube/swiss/source/aram/sidestep.c#L350 + argv->argc = dol_argc; + argv->length = 1; + + for (int i = 0; i < dol_argc; i++) { + size_t arg_length = strlen(dol_argv[i]) + 1; + argv->length += arg_length; + } + + kprintf("CLI argv size is %iB\n", argv->length); + argv->commandLine = (char *) malloc(argv->length); + + if (!argv->commandLine) { + kprintf("Couldn't allocate memory for CLI argv\n"); + argv->length = 0; + return 0; + } + + unsigned int position = 0; + for (int i = 0; i < dol_argc; i++) { + size_t arg_length = strlen(dol_argv[i]) + 1; + memcpy(argv->commandLine + position, dol_argv[i], arg_length); + position += arg_length; + } + argv->commandLine[argv->length - 1] = '\0'; + + return 1; +} \ No newline at end of file diff --git a/source/cli_args.h b/source/cli_args.h new file mode 100644 index 0000000..fc97273 --- /dev/null +++ b/source/cli_args.h @@ -0,0 +1,8 @@ +#ifndef INC_CLI_ARGS_H +#define INC_CLI_ARGS_H +#include + +int +parse_cli_args(struct __argv *argv, char *cli_option_str); + +#endif diff --git a/source/filesystem.c b/source/filesystem.c new file mode 100644 index 0000000..afb69ee --- /dev/null +++ b/source/filesystem.c @@ -0,0 +1,115 @@ +#include "filesystem.h" +#include "fatfs/ff.h" +#include "ffshim.h" +#include +#include + +FATFS fs; +FS_RESULT +fs_mount(const DISC_INTERFACE *iface_) { + iface = iface_; + return f_mount(&fs, "", 1); +} + +void +fs_unmount() { + f_unmount(""); + iface->shutdown(); + iface = NULL; +} + +void +fs_get_volume_label(const char *path, char *label) { + FRESULT res = f_getlabel(path, label, NULL); + if (res != FR_OK) { + *label = '\0'; + } +} + +FS_RESULT +_fs_read_file(void **contents_, const char *path, int is_string) { + FIL file; + FRESULT result = f_open(&file, path, FA_READ); + if (result != FR_OK) { + kprintf("Failed to open file: %s\n", get_fs_result_message(result)); + return result; + } + + size_t size = f_size(&file); + if (size <= 0) { + kprintf("File is empty\n"); + return FS_FILE_EMPTY; + } + kprintf("File size: %iB\n", size); + + // Malloc an extra byte if we are reading as a string incase we need to add NUL character. + void *contents = malloc(size + (is_string ? 1 : 0)); + if (!contents) { + kprintf("Couldn't allocate memory for file\n"); + return FS_NOT_ENOUGH_MEMORY; + } + + kprintf("Reading file...\n"); + UINT _; + result = f_read(&file, contents, size, &_); + if (result != FR_OK) { + kprintf("Failed to read file: %s\n", get_fs_result_message(result)); + return result; + } + + f_close(&file); + + // Ensure files read as strings end with NUL character. + if (is_string) { + // This is safe because we malloc an extra byte above if reading as string. + ((char *) contents)[size] = '\0'; + } + + *contents_ = contents; + return FS_OK; +} + +FS_RESULT +fs_read_file(void **contents, const char *path) { + return _fs_read_file(contents, path, false); +} +FS_RESULT +fs_read_file_string(const char **contents, const char *path) { + return _fs_read_file((void **) contents, path, true); +} + +#define NUM_FS_RESULT_MSGS 22 +const char *fs_result_msgs[NUM_FS_RESULT_MSGS] = { + /*FS_OK ( 0)*/ "Succeeded", + /*FS_DISK_ERR ( 1)*/ "A hard error occurred in the low level disk I/O layer", + /*FS_INT_ERR ( 2)*/ "Assertion failed", + /*FS_NOT_READY ( 3)*/ "Device not ready", + /*FS_NO_FILE ( 4)*/ "Could not find the file", + /*FS_NO_PATH ( 5)*/ "Could not find the path", + /*FS_INVALID_NAME ( 6)*/ "The path name format is invalid", + /*FS_DENIED ( 7)*/ "Access denied due to prohibited access or directory full", + /*FS_EXIST ( 8)*/ "Access denied due to prohibited access", + /*FS_INVALID_OBJECT ( 9)*/ "The file/directory object is invalid", + /*FS_WRITE_PROTECTED (10)*/ "The physical drive is write protected", + /*FS_INVALID_DRIVE (11)*/ "The logical drive number is invalid", + /*FS_NOT_ENABLED (12)*/ "The volume has no work area", + /*FS_NO_FILESYSTEM (13)*/ "There is no valid FAT volume", + /*FS_MKFS_ABORTED (14)*/ "The f_mkfs() aborted due to any problem", + /*FS_TIMEOUT (15)*/ + "Could not get a grant to access the volume within defined period", + /*FS_LOCKED (16)*/ + "The operation is rejected according to the file sharing policy", + /*FS_NOT_ENOUGH_CORE (17)*/ "LFN working buffer could not be allocated", + /*FS_TOO_MANY_OPEN_FILES (18)*/ "Number of open files > FF_FS_LOCK", + /*FS_INVALID_PARAMETER (19)*/ "Given parameter is invalid", + /*FS_FILE_EMPTY (20)*/ "File is empty", + /*FS_NOT_ENOUGH_MEMORY (21)*/ "Not enough memory", +}; + +const char * +get_fs_result_message(FS_RESULT result) { + if (result < 0 || result >= NUM_FS_RESULT_MSGS) { + return "Unknown"; + } + return fs_result_msgs[result]; +} diff --git a/source/filesystem.h b/source/filesystem.h new file mode 100644 index 0000000..4ae983e --- /dev/null +++ b/source/filesystem.h @@ -0,0 +1,45 @@ +#ifndef INC_FILESYSTEM_H +#define INC_FILESYSTEM_H +#include + +// See ./fatfs/ff.h:276 +typedef enum { + FS_OK = 0, /* ( 0) Succeeded */ + FS_DISK_ERR, /* ( 1) A hard error occurred in the low level disk I/O layer */ + FS_INT_ERR, /* ( 2) Assertion failed */ + FS_NOT_READY, /* ( 3) The physical drive cannot work */ + FS_NO_FILE, /* ( 4) Could not find the file */ + FS_NO_PATH, /* ( 5) Could not find the path */ + FS_INVALID_NAME, /* ( 6) The path name format is invalid */ + FS_DENIED, /* ( 7) Access denied due to prohibited access or directory full */ + FS_EXIST, /* ( 8) Access denied due to prohibited access */ + FS_INVALID_OBJECT, /* ( 9) The file/directory object is invalid */ + FS_WRITE_PROTECTED, /* (10) The physical drive is write protected */ + FS_INVALID_DRIVE, /* (11) The logical drive number is invalid */ + FS_NOT_ENABLED, /* (12) The volume has no work area */ + FS_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ + FS_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */ + FS_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ + FS_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ + FS_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FS_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ + FS_INVALID_PARAMETER, /* (19) Given parameter is invalid */ + FS_FILE_EMPTY, /* (20) File is empty */ + FS_NOT_ENOUGH_MEMORY, /* (21) Not enough memory to malloc file */ +} FS_RESULT; +// Changes to this enum should also be made to fs_result_msgs in filesystem.c + +FS_RESULT +fs_mount(const DISC_INTERFACE *iface_); +void +fs_unmount(); +void +fs_get_volume_label(const char *path, char *label); +FS_RESULT +fs_read_file(void **contents, const char *path); +FS_RESULT +fs_read_file_string(const char **contents, const char *path); +const char * +get_fs_result_message(FS_RESULT result); + +#endif diff --git a/source/main.c b/source/main.c index 53e782f..174f551 100644 --- a/source/main.c +++ b/source/main.c @@ -1,8 +1,9 @@ -#include "fatfs/ff.h" -#include "ffshim.h" -#include "utils.h" +#include "cli_args.h" +#include "filesystem.h" +#include "shortcut.h" #include "version.h" #include +#include #include #include #include @@ -16,171 +17,108 @@ #define VERBOSE_LOGGING 0 -u8 *dol = NULL; -int dol_argc = 0; -#define MAX_NUM_ARGV 1024 -char *dol_argv[MAX_NUM_ARGV]; +// Global State +// -------------------- u16 all_buttons_held; +extern u8 __xfb[]; +// -------------------- -char *default_path = "/ipl.dol"; -struct shortcut { - u16 pad_buttons; - char *path; -} shortcuts[] = { - {PAD_BUTTON_A, "/a.dol"}, - {PAD_BUTTON_B, "/b.dol"}, - {PAD_BUTTON_X, "/x.dol"}, - {PAD_BUTTON_Y, "/y.dol"}, - {PAD_TRIGGER_Z, "/z.dol"}, - {PAD_BUTTON_START, "/start.dol"}, - // NOTE: Shouldn't use L, R or Joysticks as analog inputs are calibrated on boot. - // Should also avoid D-Pad as it is used for special functionality. -}; -int num_shortcuts = sizeof(shortcuts) / sizeof(shortcuts[0]); +typedef struct { + u8 *dol_file; + struct __argv argv; +} BOOT_PAYLOAD; void -dol_alloc(int size) { - int mram_size = (SYS_GetArenaHi() - SYS_GetArenaLo()); - kprintf("Memory available: %iB\n", mram_size); - - kprintf("DOL size is %iB\n", size); - - if (size <= 0) { - kprintf("Empty DOL\n"); - return; - } +scan_all_buttons_held() { + PAD_ScanPads(); + all_buttons_held = + (PAD_ButtonsHeld(PAD_CHAN0) | PAD_ButtonsHeld(PAD_CHAN1) + | PAD_ButtonsHeld(PAD_CHAN2) | PAD_ButtonsHeld(PAD_CHAN3)); +} - dol = (u8 *) memalign(32, size); +void +read_dol_file(u8 **dol_file, const char *path) { + *dol_file = NULL; - if (!dol) { - kprintf("Couldn't allocate memory\n"); - } + kprintf("Reading %s\n", path); + fs_read_file((void **) dol_file, path); } void -load_parse_cli(char *path) { - int path_length = strlen(path); +read_cli_file(char **cli_file, const char *dol_path) { + *cli_file = NULL; + + int path_length = strlen(dol_path); + char path[path_length + 1]; + strcpy(path, dol_path); path[path_length - 3] = 'c'; path[path_length - 2] = 'l'; path[path_length - 1] = 'i'; kprintf("Reading %s\n", path); - FIL file; - FRESULT result = f_open(&file, path, FA_READ); - if (result != FR_OK) { - if (result == FR_NO_FILE) { - kprintf("CLI file not found\n"); - } else { - kprintf("Failed to open CLI file: %s\n", get_fresult_message(result)); - } - return; - } - - size_t size = f_size(&file); - kprintf("CLI file size is %iB\n", size); - - if (size <= 0) { - kprintf("Empty CLI file\n"); - return; - } - - char *cli = (char *) malloc(size + 1); + fs_read_file_string((const char **) cli_file, path); +} - if (!cli) { - kprintf("Couldn't allocate memory for CLI file\n"); - return; +// 0 - Device should not be used. +// 1 - Device should be used. +int +load_shortcut_files(BOOT_PAYLOAD *payload, int shortcut_index) { + // Attempt to read shortcut paths from from mounted FAT device. + u8 *dol_file = NULL; + const char *dol_path = shortcuts[shortcut_index].path; + read_dol_file(&dol_file, dol_path); + if (!dol_file && shortcut_index != 0) { + shortcut_index = 0; + dol_path = shortcuts[shortcut_index].path; + read_dol_file(&dol_file, dol_path); } - - UINT _; - f_read(&file, cli, size, &_); - f_close(&file); - - if (cli[size - 1] != '\0') { - cli[size] = '\0'; - size++; + if (!dol_file) { + return 0; } - // Parse CLI file - // https://github.com/emukidid/swiss-gc/blob/a0fa06d81360ad6d173acd42e4dd5495e268de42/cube/swiss/source/swiss.c#L1236 - dol_argv[dol_argc] = path; - dol_argc++; + // Attempt to read CLI file. + char *cli_file; + read_cli_file(&cli_file, dol_path); - // First argument is at the beginning of the file - if (cli[0] != '\r' && cli[0] != '\n') { - dol_argv[dol_argc] = cli; - dol_argc++; - } - - // Search for the others after each newline - for (int i = 0; i < size; i++) { - if (cli[i] == '\r' || cli[i] == '\n') { - cli[i] = '\0'; - } else if (cli[i - 1] == '\0') { - dol_argv[dol_argc] = cli + i; - dol_argc++; - if (dol_argc >= MAX_NUM_ARGV) { - kprintf("Reached max of %i args.\n", MAX_NUM_ARGV); - break; - } - } + // Parse CLI file. + if (cli_file) { + parse_cli_args(&payload->argv, cli_file); + free((void *) cli_file); } - kprintf("Found %i CLI args\n", dol_argc); - -#if VERBOSE_LOGGING - for (int i = 0; i < dol_argc; ++i) { - kprintf("arg%i: %s\n", i, dol_argv[i]); - } -#endif + payload->dol_file = dol_file; + return 1; } +// 0 - Device should not be used. +// 1 - Device should be used. int -load_fat(const char *slot_name, const DISC_INTERFACE *iface_, char **paths, int num_paths) { +load_fat( + BOOT_PAYLOAD *payload, + const char *slot_name, + const DISC_INTERFACE *iface, + int shortcut_index +) { int res = 0; kprintf("Trying %s\n", slot_name); - FATFS fs; - iface = iface_; - FRESULT mount_result = f_mount(&fs, "", 1); - if (mount_result != FR_OK) { - kprintf("Couldn't mount %s: %s\n", slot_name, get_fresult_message(mount_result)); + // Mount device. + FS_RESULT result = fs_mount(iface); + if (result != FS_OK) { + kprintf("Couldn't mount %s: %s\n", slot_name, get_fs_result_message(result)); goto end; } - char name[256]; - f_getlabel(slot_name, name, NULL); - kprintf("Mounted %s as %s\n", name, slot_name); - - for (int i = 0; i < num_paths; ++i) { - char *path = paths[i]; - kprintf("Reading %s\n", path); - FIL file; - FRESULT open_result = f_open(&file, path, FA_READ); - if (open_result != FR_OK) { - kprintf("Failed to open file: %s\n", get_fresult_message(open_result)); - continue; - } - - size_t size = f_size(&file); - dol_alloc(size); - if (!dol) { - continue; - } - UINT _; - f_read(&file, dol, size, &_); - f_close(&file); - - // Attempt to load and parse CLI file - load_parse_cli(path); + char volume_label[256]; + fs_get_volume_label(slot_name, volume_label); + kprintf("Mounted %s as %s\n", volume_label, slot_name); - res = 1; - break; - } + // Attempt to load shortcut files. + res = load_shortcut_files(payload, shortcut_index); kprintf("Unmounting %s\n", slot_name); - iface->shutdown(); - iface = NULL; + fs_unmount(); end: return res; @@ -203,27 +141,18 @@ convert_int(unsigned int in) { #define GC_READY 0x88 #define GC_OK 0x89 +// 0 - Device should not be used. +// 1 - Device should be used. int -load_usb(char slot) { - kprintf("Trying USB Gecko in slot %c\n", slot); - - int channel, res = 1; - - switch (slot) { - case 'B': - channel = 1; - break; +load_usb(BOOT_PAYLOAD *payload, char slot) { + int res = 0; + int channel = slot == 'B' ? 1 : 0; - case 'A': - default: - channel = 0; - break; - } + kprintf("Trying USB Gecko in slot %c\n", slot); if (!usb_isgeckoalive(channel)) { kprintf("Not present\n"); - res = 0; - goto end; + return res; } usb_flush(channel); @@ -241,13 +170,14 @@ load_usb(char slot) { current_time = gettime(); if (diff_sec(start_time, current_time) >= 5) { kprintf("PC did not respond in time\n"); - res = 0; - goto end; + return res; } usb_recvbuffer_safe_ex(channel, &data, 1, 10); // 10 retries } + res = 1; + if (data == PC_READY) { kprintf("Respond with OK\n"); // Sometimes the PC can fail to receive the byte, this helps @@ -261,15 +191,20 @@ load_usb(char slot) { usb_recvbuffer_safe(channel, &size, 4); size = convert_int(size); - dol_alloc(size); - unsigned char *pointer = dol; + if (size <= 0) { + kprintf("DOL is empty\n"); + return res; + } + kprintf("DOL size is %iB\n", size); - if (!dol) { - res = 0; - goto end; + u8 *dol_file = (u8 *) malloc(size); + if (!dol_file) { + kprintf("Couldn't allocate memory for DOL file\n"); + return res; } kprintf("Receiving file...\n"); + unsigned char *pointer = dol_file; while (size > 0xF7D8) { usb_recvbuffer_safe(channel, (void *) pointer, 0xF7D8); size -= 0xF7D8; @@ -279,12 +214,10 @@ load_usb(char slot) { usb_recvbuffer_safe(channel, (void *) pointer, size); } -end: + payload->dol_file = dol_file; return res; } -extern u8 __xfb[]; - void delay_exit() { // Wait while the d-pad down direction or reset button is held. @@ -297,10 +230,7 @@ delay_exit() { while (all_buttons_held & PAD_BUTTON_DOWN || SYS_ResetButtonDown()) { VIDEO_WaitVSync(); - PAD_ScanPads(); - all_buttons_held = - (PAD_ButtonsHeld(PAD_CHAN0) | PAD_ButtonsHeld(PAD_CHAN1) - | PAD_ButtonsHeld(PAD_CHAN2) | PAD_ButtonsHeld(PAD_CHAN3)); + scan_all_buttons_held(); } } @@ -346,106 +276,88 @@ main() { EXI_Sync(EXI_CHANNEL_0); EXI_Deselect(EXI_CHANNEL_0); EXI_Unlock(EXI_CHANNEL_0); + // Since we've disabled the Qoob, we wil reboot to the Nintendo IPL - PAD_ScanPads(); - - all_buttons_held = - (PAD_ButtonsHeld(PAD_CHAN0) | PAD_ButtonsHeld(PAD_CHAN1) - | PAD_ButtonsHeld(PAD_CHAN2) | PAD_ButtonsHeld(PAD_CHAN3)); + scan_all_buttons_held(); if (all_buttons_held & PAD_BUTTON_LEFT || SYS_ResetButtonDown()) { - // Since we've disabled the Qoob, we wil reboot to the Nintendo IPL kprintf("Skipped. Rebooting into original IPL...\n"); delay_exit(); return 0; } - char *paths[2]; - int num_paths = 0; + int mram_size = SYS_GetArenaHi() - SYS_GetArenaLo(); + kprintf("Memory available: %iB\n", mram_size); - for (int i = 0; i < num_shortcuts; i++) { + // Detect selected shortcut. + int shortcut_index = 0; + for (int i = 1; i < NUM_SHORTCUTS; i++) { if (all_buttons_held & shortcuts[i].pad_buttons) { - paths[num_paths++] = shortcuts[i].path; + shortcut_index = i; break; } } - paths[num_paths++] = default_path; - - if (load_usb('B')) { - goto load; - } - - if (load_fat("sdb", &__io_gcsdb, paths, num_paths)) { - goto load; - } - - if (load_usb('A')) { - goto load; - } - - if (load_fat("sda", &__io_gcsda, paths, num_paths)) { - goto load; - } - - if (load_fat("sd2", &__io_gcsd2, paths, num_paths)) { - goto load; - } - -load: - if (!dol) { - kprintf("No DOL found! Halting."); + // Init payload. + BOOT_PAYLOAD payload; + payload.dol_file = NULL; + payload.argv.argc = 0; + payload.argv.length = 0; + payload.argv.commandLine = NULL; + payload.argv.argvMagic = ARGV_MAGIC; + + // Attempt to load from each device. + int res = + (load_usb(&payload, 'B') || load_fat(&payload, "sdb", &__io_gcsdb, shortcut_index) + || load_usb(&payload, 'A') + || load_fat(&payload, "sda", &__io_gcsda, shortcut_index) + || load_fat(&payload, "sd2", &__io_gcsd2, shortcut_index)); + + if (!res || !payload.dol_file) { + // If we reach here, all attempts to load a DOL failed + kprintf("No DOL loaded! Halting."); while (true) { VIDEO_WaitVSync(); } } - struct __argv dolargs; - dolargs.commandLine = (char *) NULL; - dolargs.length = 0; - - // https://github.com/emukidid/swiss-gc/blob/f5319aab248287c847cb9468325ebcf54c993fb1/cube/swiss/source/aram/sidestep.c#L350 - if (dol_argc) { - dolargs.argvMagic = ARGV_MAGIC; - dolargs.argc = dol_argc; - dolargs.length = 1; - - for (int i = 0; i < dol_argc; i++) { - size_t arg_length = strlen(dol_argv[i]) + 1; - dolargs.length += arg_length; + // Print DOL args. +#if VERBOSE_LOGGING + if (payload.argv.length > 0) { + kprintf("----------\n"); + size_t position = 0; + for (int i = 0; i < payload.argv.argc; ++i) { + kprintf("arg%i: %s\n", i, payload.argv.commandLine + position); + position += strlen(payload.argv.commandLine + position) + 1; } + kprintf("----------\n\n"); + } else { + kprintf("No CLI args\n"); + } +#endif - kprintf("CLI argv size is %iB\n", dolargs.length); - dolargs.commandLine = (char *) malloc(dolargs.length); - - if (!dolargs.commandLine) { - kprintf("Couldn't allocate memory for CLI argv\n"); - dolargs.length = 0; - } else { - unsigned int position = 0; - for (int i = 0; i < dol_argc; i++) { - size_t arg_length = strlen(dol_argv[i]) + 1; - memcpy(dolargs.commandLine + position, dol_argv[i], arg_length); - position += arg_length; - } - dolargs.commandLine[dolargs.length - 1] = '\0'; - DCStoreRange(dolargs.commandLine, dolargs.length); - } + // Prepare DOL argv. + if (payload.argv.length > 0) { + DCStoreRange(payload.argv.commandLine, payload.argv.length); } + // Load stub. memcpy((void *) STUB_ADDR, stub, (size_t) stub_size); DCStoreRange((void *) STUB_ADDR, (u32) stub_size); delay_exit(); + // Boot DOL. SYS_ResetSystem(SYS_SHUTDOWN, 0, FALSE); SYS_SwitchFiber( - (intptr_t) dol, + (intptr_t) payload.dol_file, 0, - (intptr_t) dolargs.commandLine, - dolargs.length, + (intptr_t) payload.argv.commandLine, + payload.argv.length, STUB_ADDR, STUB_STACK ); + + // Will never reach here. return 0; } diff --git a/source/shortcut.c b/source/shortcut.c new file mode 100644 index 0000000..28803e8 --- /dev/null +++ b/source/shortcut.c @@ -0,0 +1,14 @@ +#include "shortcut.h" +#include + +SHORTCUT shortcuts[NUM_SHORTCUTS] = { + {0, "/ipl.dol"}, + {PAD_BUTTON_A, "/a.dol"}, + {PAD_BUTTON_B, "/b.dol"}, + {PAD_BUTTON_X, "/x.dol"}, + {PAD_BUTTON_Y, "/y.dol"}, + {PAD_TRIGGER_Z, "/z.dol"}, + {PAD_BUTTON_START, "/start.dol"}, + // NOTE: Shouldn't use L, R or Joysticks as analog inputs are calibrated on boot. + // Should also avoid D-Pad as it is used for special functionality. +}; diff --git a/source/shortcut.h b/source/shortcut.h new file mode 100644 index 0000000..a56b34b --- /dev/null +++ b/source/shortcut.h @@ -0,0 +1,14 @@ +#ifndef INC_SHORTCUT_H +#define INC_SHORTCUT_H +#include + +#define NUM_SHORTCUTS 7 + +typedef struct { + const u16 pad_buttons; + const char *path; +} SHORTCUT; + +extern SHORTCUT shortcuts[NUM_SHORTCUTS]; + +#endif diff --git a/source/utils.c b/source/utils.c deleted file mode 100644 index c52e4c7..0000000 --- a/source/utils.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "fatfs/ff.h" - -// See ./fatfs/ff.h:276 -char *fresult_msgs[] = { - /*FR_OK ( 0)*/ "Succeeded", - /*FR_DISK_ERR ( 1)*/ "A hard error occurred in the low level disk I/O layer", - /*FR_INT_ERR ( 2)*/ "Assertion failed", - /*FR_NOT_READY ( 3)*/ "Device not ready", - /*FR_NO_FILE ( 4)*/ "Could not find the file", - /*FR_NO_PATH ( 5)*/ "Could not find the path", - /*FR_INVALID_NAME ( 6)*/ "The path name format is invalid", - /*FR_DENIED ( 7)*/ "Access denied due to prohibited access or directory full", - /*FR_EXIST ( 8)*/ "Access denied due to prohibited access", - /*FR_INVALID_OBJECT ( 9)*/ "The file/directory object is invalid", - /*FR_WRITE_PROTECTED (10)*/ "The physical drive is write protected", - /*FR_INVALID_DRIVE (11)*/ "The logical drive number is invalid", - /*FR_NOT_ENABLED (12)*/ "The volume has no work area", - /*FR_NO_FILESYSTEM (13)*/ "There is no valid FAT volume", - /*FR_MKFS_ABORTED (14)*/ "The f_mkfs() aborted due to any problem", - /*FR_TIMEOUT (15)*/ - "Could not get a grant to access the volume within defined period", - /*FR_LOCKED (16)*/ - "The operation is rejected according to the file sharing policy", - /*FR_NOT_ENOUGH_CORE (17)*/ "LFN working buffer could not be allocated", - /*FR_TOO_MANY_OPEN_FILES (18)*/ "Number of open files > FF_FS_LOCK", - /*FR_INVALID_PARAMETER (19)*/ "Given parameter is invalid", -}; -int num_fresult_msgs = sizeof(fresult_msgs) / sizeof(fresult_msgs[0]); - -char * -get_fresult_message(FRESULT result) { - if (result < 0 || result >= num_fresult_msgs) { - return "Unknown"; - } - return fresult_msgs[result]; -} diff --git a/source/utils.h b/source/utils.h deleted file mode 100644 index 9fda394..0000000 --- a/source/utils.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef INC_UTILS_H -#define INC_UTILS_H - -#include "fatfs/ff.h" - -extern char * -get_fresult_message(FRESULT result); - -#endif