diff --git a/include/arm11/menu/menu_util.h b/include/arm11/menu/menu_util.h index f6c7a75..9db047b 100644 --- a/include/arm11/menu/menu_util.h +++ b/include/arm11/menu/menu_util.h @@ -22,8 +22,14 @@ char* mallocpyString(const char* str); void truncateString(char* dest, const char* orig, int nsize, int tpos); void formatBytes(char* str, u64 bytes); +void keysToString(u32 keys, char* string); +void stringWordWrap(char* str, int llen); + u32 stringGetHeight(const char* str); u32 stringGetWidth(const char* str); -void stringWordWrap(char* str, int llen); + u32 ee_printf_line_center(const char *const fmt, ...); + +void updateScreens(void); +void outputEndWait(void); void sleepmode(void); diff --git a/source/arm11/main.c b/source/arm11/main.c index 047508c..4e196bc 100644 --- a/source/arm11/main.c +++ b/source/arm11/main.c @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +#include #include "types.h" #include "arm11/hardware/hardware.h" #include "arm11/hardware/interrupt.h" @@ -24,10 +25,12 @@ #include "arm11/hardware/i2c.h" #include "arm11/menu/menu.h" #include "arm11/menu/menu_fb3ds.h" +#include "arm11/menu/menu_util.h" #include "hardware/pxi.h" #include "hardware/gfx.h" #include "arm11/firm.h" #include "arm11/console.h" +#include "arm11/debug.h" #include "arm11/fmt.h" #include "fsutils.h" #include "arm11/config.h" @@ -40,12 +43,24 @@ int main(void) { + bool show_menu = false; + bool gfx_initialized = false; + char* err_string = NULL; + + // init hardware / filesystem / load config hardwareInit(); fsMountSdmc(); fsMountNandFilesystems(); loadConfigFile(); + + // init and select terminal console + PrintConsole term_con; + consoleInit(SCREEN_TOP, &term_con, true); + consoleSelect(&term_con); + + // check keys held at boot hidScanInput(); u32 kHeld = hidKeysHeld(); @@ -53,6 +68,14 @@ // boot slot keycombo held? if (kHeld & 0xfff) { + err_string = (char*) malloc(512); + char* err_ptr = err_string; + if(!err_string) panicMsg("Out of memory"); + + char combo_str[0x80]; + keysToString(kHeld & 0xfff, combo_str); + err_ptr += ee_sprintf(err_ptr, "Keys held on boot: %s\n", combo_str); + for(u32 i = 0; (i < 3) && !g_startFirmLaunch; i++) { if(!configDataExist(KBootOption1 + i) || @@ -63,63 +86,134 @@ if((kHeld & 0xfff) == combo) { char* path = (char*) configGetData(KBootOption1 + i); + err_ptr += ee_sprintf(err_ptr, "Keys match boot slot #%lu.\nBoot path is %s\n", (i+1), path); g_startFirmLaunch = (loadVerifyFirm(path, false) >= 0); + err_ptr += ee_sprintf(err_ptr, "Load slot #%lu %s.\n", (i+1), g_startFirmLaunch ? "success" : "failed"); + break; } } + + if (!g_startFirmLaunch) + { + err_ptr += ee_sprintf(err_ptr, "Firmware not loaded!\nKeys may not match a boot slot.\n"); + } + else + { + free(err_string); + err_string = NULL; + } } + // get bootmode from config u32 bootmode = BootModeNormal; if(configDataExist(KBootMode)) bootmode = *(u32*) configGetData(KBootMode); - - // menu specific code - // HOME button detection may not work yet - if(!g_startFirmLaunch && ((bootmode == BootModeNormal) || hidIsHomeButtonHeldRaw())) - { - // init screens - GFX_init(); - - // init menu console - PrintConsole menu_con; - consoleInit(SCREEN_SUB, &menu_con, false); - - // init description console - PrintConsole desc_con; - consoleInit(SCREEN_TOP, &desc_con, false); - - // run menu - g_continueBootloader = false; - menuProcess(&menu_con, &desc_con, menu_fb3ds); - - // write config (if something changed) - if (configHasChanged()) writeConfigFile(); - - // deinit GFX - GFX_deinit(); - } - // search for a bootable firmware (all slots) - if (g_continueBootloader && !g_startFirmLaunch) + // show menu if either bootmode is normal or HOME is held + // ... or not if we already got a firmware waiting in line + show_menu = show_menu || + (!g_startFirmLaunch && ((bootmode == BootModeNormal) || hidIsHomeButtonHeldRaw())); + + + // main loop + while(!g_startFirmLaunch) { - for(u32 i = 0; (i < 3) && !g_startFirmLaunch; i++) + // init screens (if we'll need them below) + if((show_menu || err_string) && !gfx_initialized) { - if(!configDataExist(KBootOption1 + i)) - continue; + GFX_init(); + gfx_initialized = true; + } + + // if there is an error, output it to screen + if (err_string) + { + ee_printf("%s\nPress B or HOME to enter menu.\n", err_string); + updateScreens(); + outputEndWait(); - char* path = (char*) configGetData(KBootOption1 + i); - g_startFirmLaunch = (loadVerifyFirm(path, false) >= 0); + show_menu = true; + free(err_string); + err_string = NULL; + + if(hidGetPowerButton(false)) break; + } + + // menu specific code + if(show_menu) + { + // init menu console + PrintConsole menu_con; + consoleInit(SCREEN_SUB, &menu_con, false); + + // run menu + g_continueBootloader = false; + menuProcess(&menu_con, &term_con, menu_fb3ds); + + // clear consoles and screen + consoleSelect(&menu_con); + consoleClear(); + consoleSelect(&term_con); + consoleClear(); + updateScreens(); + + // write config (if something changed) + if (configHasChanged()) writeConfigFile(); + + // check POWER button + if(hidGetPowerButton(false)) break; + } + + // search for a bootable firmware (all slots) + if (g_continueBootloader && !g_startFirmLaunch) + { + err_string = (char*) malloc(512); + char* err_ptr = err_string; + if(!err_string) panicMsg("Out of memory"); + + err_ptr += ee_sprintf(err_ptr, "Continuing bootloader...\n"); + for(u32 i = 0; (i < 3) && !g_startFirmLaunch; i++) + { + if(!configDataExist(KBootOption1 + i)) + continue; + + char* path = (char*) configGetData(KBootOption1 + i); + err_ptr += ee_sprintf(err_ptr, "Trying boot slot #%lu.\nBoot path is %s\n", (i+1), path); + g_startFirmLaunch = (loadVerifyFirm(path, false) >= 0); + err_ptr += ee_sprintf(err_ptr, "Load slot #%lu %s.\n", (i+1), g_startFirmLaunch ? "success" : "failed"); + break; + } + + if (!g_startFirmLaunch) + { + err_ptr += ee_sprintf(err_ptr, "Firmware not loaded!\nAre boot slots properly set up?\n"); + } + else + { + free(err_string); + err_string = NULL; + } } } + + // deinit GFX if it was initialized + if(gfx_initialized) GFX_deinit(); + // deinit filesystem fsUnmountAll(); + + // free memory (should already be free at this time) + if(err_string) free(err_string); + + // power off + if(hidGetPowerButton(true)) power_off(); // firm launch if(g_startFirmLaunch) firmLaunch(); - // power off - power_off(); + // reaching here was never intended.... return 0; } diff --git a/source/arm11/menu/menu.c b/source/arm11/menu/menu.c index 8b761e4..e4b51d6 100644 --- a/source/arm11/menu/menu.c +++ b/source/arm11/menu/menu.c @@ -202,7 +202,7 @@ GFX_waitForEvent(GFX_EVENT_PDC0, true); // VBlank // handle power button - if(hidGetPowerButton(true)) + if(hidGetPowerButton(false)) break; // deinits & poweroff outside of this function hidScanInput(); diff --git a/source/arm11/menu/menu_func.c b/source/arm11/menu/menu_func.c index db90912..b2bfa06 100644 --- a/source/arm11/menu/menu_func.c +++ b/source/arm11/menu/menu_func.c @@ -33,32 +33,6 @@ -void outputEndWait(void) -{ - u32 kDown = 0; - - do - { - GFX_waitForEvent(GFX_EVENT_PDC0, true); - - if(hidGetPowerButton(false)) // handle power button - break; - - hidScanInput(); - kDown = hidKeysDown(); - if (kDown & (KEY_SHELL)) sleepmode(); - } - while (!(kDown & (KEY_B|KEY_HOME))); -} - -void updateScreens(void) -{ - GX_textureCopy((u64*)RENDERBUF_TOP, 0, (u64*)GFX_getFramebuffer(SCREEN_TOP), - 0, SCREEN_SIZE_TOP + SCREEN_SIZE_SUB); - GFX_swapFramebufs(); - GFX_waitForEvent(GFX_EVENT_PDC0, true); // VBlank -} - u32 menuPresetBootMode(void) { if (configDataExist(KBootMode)) @@ -116,11 +90,6 @@ return res; } -static const char * convTable[] = { - "A", "B", "SELECT", "START", "RIGHT", "LEFT", - "UP", "DOWN", "R", "L", "X", "Y" -}; - u32 menuSetupBootKeys(PrintConsole* con, u32 param) { const u32 y_center = 7; @@ -133,18 +102,7 @@ { // build button string char button_str[80]; - char* ptr = button_str; - bool first = true; - for (u32 i = 0; i < 12; i++) - { - if (kHeld & (1< #include "types.h" #include "arm11/hardware/hid.h" +#include "arm11/hardware/interrupt.h" +#include "arm11/menu/menu_util.h" #include "arm11/console.h" #include "arm11/fmt.h" -#include "arm11/hardware/interrupt.h" char* mallocpyString(const char* str) @@ -36,40 +37,61 @@ void truncateString(char* dest, const char* orig, int nsize, int tpos) { - int osize = strlen(orig); + int osize = strlen(orig); - if (nsize < 0) + if (nsize < 0) { - return; - } else if (nsize <= 3) + return; + } else if (nsize <= 3) { - ee_snprintf(dest, nsize, orig); - } else if (nsize >= osize) + ee_snprintf(dest, nsize, orig); + } else if (nsize >= osize) { - ee_snprintf(dest, nsize + 1, orig); - } else + ee_snprintf(dest, nsize + 1, orig); + } else { - if (tpos + 3 > nsize) tpos = nsize - 3; - ee_snprintf(dest, nsize + 1, "%-.*s...%-.*s", tpos, orig, nsize - (3 + tpos), orig + osize - (nsize - (3 + tpos))); - } + if (tpos + 3 > nsize) tpos = nsize - 3; + ee_snprintf(dest, nsize + 1, "%-.*s...%-.*s", tpos, orig, nsize - (3 + tpos), orig + osize - (nsize - (3 + tpos))); + } } void formatBytes(char* str, u64 bytes) { // str should be 32 byte in size, just to be safe - const char* units[] = {" Byte", " kiB", " MiB", " GiB"}; - - if (bytes < 1024) + const char* units[] = {" Byte", " kiB", " MiB", " GiB"}; + + if (bytes < 1024) { ee_snprintf(str, 32, "%llu%s", bytes, units[0]); } - else + else { - u32 scale = 1; - u64 bytes100 = (bytes * 100) >> 10; - for(; (bytes100 >= 1024*100) && (scale < 3); scale++, bytes100 >>= 10); - ee_snprintf(str, 32, "%llu.%llu%s", bytes100 / 100, (bytes100 % 100) / 10, units[scale]); - } + u32 scale = 1; + u64 bytes100 = (bytes * 100) >> 10; + for(; (bytes100 >= 1024*100) && (scale < 3); scale++, bytes100 >>= 10); + ee_snprintf(str, 32, "%llu.%llu%s", bytes100 / 100, (bytes100 % 100) / 10, units[scale]); + } +} + +static const char * convTable[] = { + "A", "B", "SELECT", "START", "RIGHT", "LEFT", + "UP", "DOWN", "R", "L", "X", "Y" +}; + +void keysToString(u32 keys, char* string) +{ + char* ptr = string; + bool first = true; + for (u32 i = 0; i < 12; i++) + { + if (keys & (1<