void configureCFW(const char *configPath, const char *firm90Path){ initScreens(); drawString(CONFIG_TITLE, 10, 10, COLOR_TITLE); drawString("Press A to select, START to save and reboot", 10, 30, COLOR_WHITE); const char *optionsText[] = { "( ) Updated SysNAND mode (A9LH-only)", "( ) Use pre-patched FIRMs", "( ) Force A9LH detection", "( ) Use 9.0 FIRM as default", "( ) Use second EmuNAND as default", "( ) Show current NAND in System Settings" }; u32 optionsAmount = sizeof(optionsText) / sizeof(char *); struct option options[optionsAmount]; //Read and parse the existing configuration u32 tempConfig = 0; fileRead(&tempConfig, configPath, 3); for(u32 i = 0; i < optionsAmount; i++) options[i].enabled = (tempConfig >> i) & 0x1; //Pre-select the first configuration option u32 selectedOption = 0; //Boring configuration menu while(1){ u16 pressed = 0; do{ for(u32 i = 0; i < optionsAmount; i++){ options[i].posY = drawString(optionsText[i], 10, !i ? 60 : options[i - 1].posY + SPACING_Y, selectedOption == i ? COLOR_RED : COLOR_WHITE); drawCharacter('x', 10 + SPACING_X, options[i].posY, options[i].enabled ? (selectedOption == i ? COLOR_RED : COLOR_WHITE) : COLOR_BLACK); } pressed = waitInput(); } while(!(pressed & MENU_BUTTONS)); switch(pressed){ case BUTTON_UP: selectedOption = !selectedOption ? optionsAmount - 1 : selectedOption - 1; break; case BUTTON_DOWN: selectedOption = selectedOption == optionsAmount - 1 ? 0 : selectedOption + 1; break; case BUTTON_LEFT: selectedOption = 0; break; case BUTTON_RIGHT: selectedOption = optionsAmount - 1; break; case BUTTON_A: options[selectedOption].enabled = !options[selectedOption].enabled; break; } if(pressed == BUTTON_START) break; } //If the user has been using A9LH and the "Updated SysNAND" setting changed, delete the patched 9.0 FIRM if(((tempConfig >> 16) & 0x1) && ((tempConfig & 0x1) != options[0].enabled)) fileDelete(firm90Path); //Preserve the last-used boot options (last 12 bits) tempConfig &= 0xFFF000; //Parse and write the selected options for(u32 i = 0; i < optionsAmount; i++) tempConfig |= options[i].enabled << i; fileWrite(&tempConfig, configPath, 3); //Zero the last booted FIRM flag CFG_BOOTENV = 0; //Reboot i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); while(1); }
void configureCFW(const char *configPath, const char *patchedFirms[]) { initScreens(); drawString(CONFIG_TITLE, 10, 10, COLOR_TITLE); drawString("Press A to select, START to save and reboot", 10, 30, COLOR_WHITE); const char *optionsText[] = { "Screen-init brightness: 4( ) 3( ) 2( ) 1( )", "( ) Updated SysNAND mode (A9LH-only)", "( ) Use pre-patched FIRMs", "( ) Force A9LH detection", "( ) Use 9.0 FIRM as default", "( ) Use second EmuNAND as default", "( ) Show current NAND in System Settings", "( ) Show GBA boot screen in patched AGB_FIRM", "( ) Enable splash screen with no screen-init", "( ) Load loader from SD" }; u32 optionsAmount = sizeof(optionsText) / sizeof(char *); struct option { int posY; u32 enabled; } options[optionsAmount]; //Parse the existing configuration options[0].enabled = CONFIG(10, 3); for(u32 i = optionsAmount; i; i--) options[i].enabled = CONFIG((i - 1), 1); //Pre-select the first configuration option u32 selectedOption = 1, oldSelectedOption = 0, optionChanged = 0; //Character to display a selected option char selected = 'x'; //Starting position options[0].posY = 52; //Display all the normal options in white, brightness will be displayed later for(u32 i = 1; i < optionsAmount; i++) { options[i].posY = drawString(optionsText[i], 10, options[i - 1].posY + SPACING_Y + (!(1 - i) * 7), COLOR_WHITE); if(options[i].enabled) drawCharacter(selected, 10 + SPACING_X, options[i].posY, COLOR_WHITE); } //Boring configuration menu while(1) { u32 pressed = 0; do { //The status of the selected option changed, black out the previously visible 'x' if needed if(optionChanged) { if(!selectedOption) drawCharacter(selected, 10 + (26 + 5 * (optionChanged - 1)) * SPACING_X, options[0].posY, COLOR_BLACK); else if(!options[selectedOption].enabled) drawCharacter(selected, 10 + SPACING_X, options[selectedOption].posY, COLOR_BLACK); optionChanged = 0; } //The selected option changed, draw the new one in red and the old one (with its 'x') in white else if(selectedOption != oldSelectedOption) { drawString(optionsText[oldSelectedOption], 10, options[oldSelectedOption].posY, COLOR_WHITE); drawString(optionsText[selectedOption], 10, options[selectedOption].posY, COLOR_RED); if(!oldSelectedOption) drawCharacter(selected, 10 + (26 + 5 * options[0].enabled) * SPACING_X, options[0].posY, COLOR_WHITE); else if(options[oldSelectedOption].enabled) drawCharacter(selected, 10 + SPACING_X, options[oldSelectedOption].posY, COLOR_WHITE); } //In any case, if the current option is enabled (or brightness is selected) we must display a red 'x' if(!selectedOption) drawCharacter(selected, 10 + (26 + 5 * options[0].enabled) * SPACING_X, options[0].posY, COLOR_RED); else if(options[selectedOption].enabled) drawCharacter(selected, 10 + SPACING_X, options[selectedOption].posY, COLOR_RED); pressed = waitInput(); } while(!(pressed & MENU_BUTTONS)); //Remember the previously selected option oldSelectedOption = selectedOption; switch(pressed) { case BUTTON_UP: selectedOption = !selectedOption ? optionsAmount - 1 : selectedOption - 1; break; case BUTTON_DOWN: selectedOption = selectedOption == (optionsAmount - 1) ? 1 : selectedOption + 1; break; case BUTTON_LEFT: selectedOption = 1; break; case BUTTON_RIGHT: selectedOption = optionsAmount - 1; break; case BUTTON_A: optionChanged = 1; if(selectedOption) options[selectedOption].enabled = !options[selectedOption].enabled; else { optionChanged += options[0].enabled; options[0].enabled = options[0].enabled == 3 ? 0 : options[0].enabled + 1; } break; } if(pressed == BUTTON_START) break; } //If the user has been using A9LH and the "Updated SysNAND" setting changed, delete the patched 9.0 FIRM if(CONFIG(16, 1) && (CONFIG(0, 1) != options[1].enabled)) fileDelete(patchedFirms[3]); //If the "Show GBA boot screen in patched AGB_FIRM" setting changed, delete the patched AGB_FIRM if(CONFIG(6, 1) != options[7].enabled) fileDelete(patchedFirms[5]); //Preserve the last-used boot options (last 12 bits) config &= 0xFFF000; //Parse and write the new configuration config |= options[0].enabled << 10; for(u32 i = optionsAmount; i; i--) config |= options[i].enabled << (i - 1); fileWrite(&config, configPath, 3); //Zero the last booted FIRM flag CFG_BOOTENV = 0; //Reboot i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); while(1); }