diff --git a/include/arm11/main.h b/include/arm11/main.h index 2541931..acf6986 100644 --- a/include/arm11/main.h +++ b/include/arm11/main.h @@ -20,5 +20,5 @@ -extern volatile bool g_poweroffAllowed; +extern volatile bool g_continueBootloader; extern volatile bool g_startFirmLaunch; diff --git a/include/arm11/menu/menu_fb3ds.h b/include/arm11/menu/menu_fb3ds.h index 0c3f22d..c9c6514 100644 --- a/include/arm11/menu/menu_fb3ds.h +++ b/include/arm11/menu/menu_fb3ds.h @@ -75,9 +75,9 @@ { "Main Menu", 6, NULL, 0, { - { "Continue boot", DESC_CONTINUE, &DummyFunc, 0 }, + { "Continue boot", DESC_CONTINUE, &menuContinueBoot, 0 }, { "Boot menu...", DESC_BOOT_MENU, NULL, 1 }, - { "Boot from file...", DESC_BOOT_FILE, &DummyFunc, 2 }, + { "Boot from file...", DESC_BOOT_FILE, &menuLaunchFirm, 0xFF }, { "NAND tools...", DESC_NAND_TOOLS, NULL, 7 }, { "Miscellaneous...", DESC_MISC, NULL, 8 }, { "Debug...", LOREM, NULL, 9 } @@ -86,10 +86,10 @@ { // 1 "Boot Menu", 5, &menuPresetBootSlot, MENU_FLAG_SLOTS, { - { "Boot [slot 1]", DESC_BOOT_SLOT(1), &DummyFunc, 0x00 }, - { "Boot [slot 2]", DESC_BOOT_SLOT(2), &DummyFunc, 0x01 }, - { "Boot [slot 3]", DESC_BOOT_SLOT(3), &DummyFunc, 0x02 }, - { "Boot from FIRM1", DESC_BOOT_FIRM1, &DummyFunc, 0xFF }, + { "Boot [slot 1]", DESC_BOOT_SLOT(1), &menuLaunchFirm, 0x00 }, + { "Boot [slot 2]", DESC_BOOT_SLOT(2), &menuLaunchFirm, 0x01 }, + { "Boot [slot 3]", DESC_BOOT_SLOT(3), &menuLaunchFirm, 0x02 }, + { "Boot from FIRM1", DESC_BOOT_FIRM1, &menuLaunchFirm, 0xFE }, { "Boot setup...", DESC_BOOT_SETUP, NULL, 2 } } @@ -117,17 +117,17 @@ { // 7 "NAND Tools", 4, NULL, 0, { - { "Backup NAND", DESC_NAND_BACKUP, &DummyFunc, 3 }, - { "Restore NAND", DESC_NAND_RESTORE, &DummyFunc, 4 }, - { "Restore NAND (forced)", DESC_NAND_RESTORE_F, &DummyFunc, 4 }, - { "Flash firmware", DESC_FIRM_FLASH, &DummyFunc, 2 } + { "Backup NAND", DESC_NAND_BACKUP, &menuDummyFunc, 3 }, + { "Restore NAND", DESC_NAND_RESTORE, &menuDummyFunc, 4 }, + { "Restore NAND (forced)", DESC_NAND_RESTORE_F, &menuDummyFunc, 4 }, + { "Flash firmware", DESC_FIRM_FLASH, &menuDummyFunc, 2 } } }, { // 8 "Miscellaneous", 2, NULL, 0, { - { "Update fastboot3DS", DESC_UPDATE, &DummyFunc, 1 }, - { "Credits", DESC_CREDITS, &ShowCredits, 0 } + { "Update fastboot3DS", DESC_UPDATE, &menuDummyFunc, 1 }, + { "Credits", DESC_CREDITS, &menuShowCredits, 0 } } }, { // 9 diff --git a/include/arm11/menu/menu_func.h b/include/arm11/menu/menu_func.h index 91442fd..a2e4005 100644 --- a/include/arm11/menu/menu_func.h +++ b/include/arm11/menu/menu_func.h @@ -22,9 +22,13 @@ u32 menuPresetBootMode(void); u32 menuPresetBootSlot(void); + u32 menuSetBootMode(PrintConsole* con, u32 param); u32 menuSetupBootSlot(PrintConsole* con, u32 param); u32 menuSetupBootKeys(PrintConsole* con, u32 param); -u32 DummyFunc(PrintConsole* con, u32 param); +u32 menuLaunchFirm(PrintConsole* con, u32 param); +u32 menuShowCredits(PrintConsole* con, u32 param); +u32 menuContinueBoot(PrintConsole* con, u32 param); + +u32 menuDummyFunc(PrintConsole* con, u32 param); u32 SetView(PrintConsole* con, u32 param); -u32 ShowCredits(PrintConsole* con, u32 param); diff --git a/source/arm11/main.c b/source/arm11/main.c index 7624767..2d1cc6d 100644 --- a/source/arm11/main.c +++ b/source/arm11/main.c @@ -33,76 +33,94 @@ #include "arm11/config.h" -volatile bool g_poweroffAllowed = true; +volatile bool g_continueBootloader = true; volatile bool g_startFirmLaunch = false; int main(void) { + // init hardware / filesystem / load config hardwareInit(); - - 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); - - // init filesystem fsMountSdmc(); fsMountNandFilesystems(); - - // load/create config file loadConfigFile(); - - // run menu - menuProcess(&menu_con, &desc_con, menu_fb3ds); - // take over any changes to the config - writeConfigFile(); + // check keys held at boot + hidScanInput(); + u32 kHeld = hidKeysHeld(); + + // boot slot keycombo held? + if (kHeld & 0xfff) + { + for(u32 i = 0; (i < 3) && !g_startFirmLaunch; i++) + { + if(!configDataExist(KBootOption1 + i) || + !configDataExist(KBootOption1Buttons + i)) + continue; + + u32 combo = *(u32*) configGetData(KBootOption1Buttons + i); + if((kHeld & 0xfff) == combo) + { + char* path = (char*) configGetData(KBootOption1 + i); + g_startFirmLaunch = (loadVerifyFirm(path, false) >= 0); + } + } + } + + // get bootmode from config + u32 bootmode = BootModeNormal; + if(configDataExist(KBootMode)) + bootmode = *(u32*) configGetData(KBootMode); - // deinit filestesystem + // menu specific code + // HOME button detection may not work yet + // if(!g_startFirmLaunch && ((bootmode == BootModeNormal) || (kHeld & KEY_HOME))) + if(!g_startFirmLaunch) + { + // 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) + { + for(u32 i = 0; (i < 3) && !g_startFirmLaunch; i++) + { + if(!configDataExist(KBootOption1 + i)) + continue; + + char* path = (char*) configGetData(KBootOption1 + i); + g_startFirmLaunch = (loadVerifyFirm(path, false) >= 0); + } + } + + // deinit filesystem fsUnmountAll(); + // firm launch + if(g_startFirmLaunch) firmLaunch(); + // power off - if(g_poweroffAllowed) power_off(); - - /*while(!g_startFirmLaunch) - { - waitForInterrupt(); - - hidScanInput(); - const u32 kDown = hidKeysDown(); - const u32 kUp = hidKeysUp(); - - if(hidGetPowerButton(true)) - { - if(g_poweroffAllowed) power_off(); - PXI_trySendWord(PXI_RPL_POWER_PRESSED); - } - - if(kDown & KEY_HOME) PXI_trySendWord(PXI_RPL_HOME_PRESSED); - if(kDown & KEY_SHELL) i2cmcu_lcd_poweroff(); - if(kUp & KEY_SHELL) - { - i2cmcu_lcd_poweron(); - i2cmcu_lcd_backlight_poweron(); - } - - - u8 hidstate = i2cmcu_readreg_hid_held(); - - if(!(hidstate & MCU_HID_HOME_BUTTON_NOT_HELD)) - PXI_trySendWord(PXI_RPL_HOME_HELD); - } - - GFX_deinit(); // TODO: Let ARM9 decide when to deinit gfx - - firm_launch();*/ - + power_off(); + return 0; } diff --git a/source/arm11/menu/menu.c b/source/arm11/menu/menu.c index 20ef30f..c7f50f1 100644 --- a/source/arm11/menu/menu.c +++ b/source/arm11/menu/menu.c @@ -16,6 +16,8 @@ * along with this program. If not, see . */ + + #include #include #include "types.h" @@ -25,6 +27,7 @@ #include "arm11/config.h" #include "arm11/console.h" #include "arm11/fmt.h" +#include "arm11/main.h" #include "hardware/gfx.h" @@ -157,7 +160,7 @@ u32 last_index = (u32) -1; // main menu processing loop - while (true) { + while (!g_startFirmLaunch && !g_continueBootloader) { // update menu and description (on demand) if ((index != last_index) || (curr_menu != last_menu)) { menuDraw(curr_menu, menu_con, index); @@ -171,7 +174,8 @@ } GFX_waitForEvent(GFX_EVENT_PDC0, true); // VBlank - if(hidGetPowerButton(true)) // handle power button + // handle power button + if(hidGetPowerButton(true)) 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 3507650..db90912 100644 --- a/source/arm11/menu/menu_func.c +++ b/source/arm11/menu/menu_func.c @@ -16,6 +16,8 @@ * along with this program. If not, see . */ + + #include #include #include @@ -26,9 +28,29 @@ #include "arm11/console.h" #include "arm11/config.h" #include "arm11/fmt.h" -#include "arm11/power.h" +#include "arm11/firm.h" +#include "arm11/main.h" -// we need a better solution for this later (!!!) + + +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), @@ -67,7 +89,6 @@ (void) con; u32 res = (configSetKeyData(KBootMode, ¶m)) ? 0 : 1; - writeConfigFile(); return res; } @@ -80,9 +101,9 @@ // if bit4 of param is set, reset slot and return if (param & 0x10) { - u32 res = (configSetKeyData(KBootOption1Buttons + slot, NULL) && - configSetKeyData(KBootOption1 + slot, NULL)) ? 0 : 1; - return res; + configDeleteKey(KBootOption1Buttons + slot); + configDeleteKey(KBootOption1 + slot); + return 0; } if (configDataExist(KBootOption1 + slot)) @@ -90,10 +111,7 @@ u32 res = 0; if (menuFileSelector(res_path, con, start, "*.firm")) - { res = (configSetKeyData(KBootOption1 + slot, res_path)) ? 0 : 1; - writeConfigFile(); - } return res; } @@ -181,49 +199,92 @@ // if we arrive here, we have a button combo u32 res = (configSetKeyData(KBootOption1Buttons + param, &kHeld)) ? 0 : 1; - writeConfigFile(); return res; } -u32 DummyFunc(PrintConsole* con, u32 param) +u32 menuLaunchFirm(PrintConsole* con, u32 param) { + char path_store[256]; + char* path; + + if (param < 3) // loading from bootslot + { + // clear console + consoleSelect(con); + consoleClear(); + + // check if bootslot exists + ee_printf("Checking bootslot...\n"); + if (!configDataExist(KBootOption1 + param)) + { + ee_printf("Bootslot does not exist!\n"); + goto fail; + } + path = (char*) configGetData(KBootOption1 + param); + } + else if (param == 0xFE) // loading from FIRM1 + { + path = "firm1:"; + } + else if (param == 0xFF) // user decision + { + path = path_store; + if (!menuFileSelector(path, con, NULL, "*.firm")) + return 1; + } + + // clear console + if (param >= 3) + { + consoleSelect(con); + consoleClear(); + } + + // try load and verify + ee_printf("\nLoading %s...\n", path); + s32 res = loadVerifyFirm(path, false); + if (res != 0) + { + ee_printf("Firm %s error code %li!\n", (res > -8) ? "load" : "verify", res); + goto fail; + } + + ee_printf("\nFirm load success, launching firm..."); // <-- you will never see this + g_startFirmLaunch = true; + + return 0; + + fail: + + ee_printf("\nFirm launcher failed.\n\nPress B or HOME to return."); + updateScreens(); + outputEndWait(); + + return 1; +} + +u32 menuContinueBoot(PrintConsole* con, u32 param) +{ + // all the relevant stuff handled outside + (void) con; + (void) param; + g_continueBootloader = true; + return 0; +} + +u32 menuDummyFunc(PrintConsole* con, u32 param) +{ + (void) param; + // clear console consoleSelect(con); consoleClear(); // print something - ee_printf("Hello! I'm a dummy function.\nparam was %lu\n\nPress B to quit.\n\n", param); + ee_printf("\nThis is not implemented yet.\nGo look elsewhere, nothing to see here.\n\nPress B or HOME to return."); updateScreens(); - - // wait for B button - do - { - if(hidGetPowerButton(false)) // handle power button - { - ee_printf("POWER button pressed.\nPress A to confirm cancel & poweroff.\n"); - updateScreens(); - - do - { - hidScanInput(); - } - while (!(hidKeysDown() & (KEY_A|KEY_B))); - - if (hidKeysDown() & KEY_B) - { - ee_printf("POWER off canceled, continuing...\n\n"); - updateScreens(); - hidGetPowerButton(true); - } - else - { - return 1; - } - } - hidScanInput(); - } - while (!(hidKeysDown() & (KEY_B|KEY_HOME))); + outputEndWait(); return 0; } @@ -257,8 +318,9 @@ // wait for B / HOME button do { + GFX_waitForEvent(GFX_EVENT_PDC0, true); if(hidGetPowerButton(false)) // handle power button - return 1; + return 0; hidScanInput(); } @@ -267,7 +329,7 @@ return 0; } -u32 ShowCredits(PrintConsole* con, u32 param) +u32 menuShowCredits(PrintConsole* con, u32 param) { (void) param; @@ -295,18 +357,8 @@ ee_printf_line_center("... everyone who contributed to 3dbrew.org"); updateScreens(); - // wait for B button or HOME button - u32 kDown = 0; - do - { - if(hidGetPowerButton(false)) // handle power button - return 0; - - hidScanInput(); - kDown = hidKeysDown(); - if (kDown & (KEY_SHELL)) sleepmode(); - } - while (!(kDown & (KEY_B|KEY_HOME))); + // wait for user + outputEndWait(); return 0; }