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<