182 lines
7.2 KiB
C
182 lines
7.2 KiB
C
/*
|
|
* config.c
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "utils.h"
|
|
#include "screeninit.h"
|
|
#include "draw.h"
|
|
#include "fs.h"
|
|
#include "buttons.h"
|
|
|
|
void configureCFW(const char *configPath)
|
|
{
|
|
initScreens();
|
|
|
|
drawString(CONFIG_TITLE, 10, 10, COLOR_TITLE);
|
|
drawString("Press A to select, START to save and reboot", 10, 30, COLOR_WHITE);
|
|
|
|
const char *multiOptionsText[] = { "Screen-init brightness: 4( ) 3( ) 2( ) 1( )",
|
|
"New 3DS CPU: Off( ) Clock( ) L2( ) Clock+L2( )" };
|
|
|
|
const char *singleOptionsText[] = { "( ) Autoboot SysNAND",
|
|
"( ) SysNAND is updated (A9LH-only)",
|
|
"( ) Force A9LH detection",
|
|
"( ) Use second EmuNAND as default",
|
|
"( ) Enable region/language emulation",
|
|
"( ) Enable developer features",
|
|
"( ) Show current NAND in System Settings",
|
|
"( ) Show GBA boot screen in patched AGB_FIRM",
|
|
"( ) Enable splash screen with no screen-init" };
|
|
|
|
struct multiOption {
|
|
int posXs[4];
|
|
int posY;
|
|
u32 enabled;
|
|
} multiOptions[] = {
|
|
{ .posXs = {26, 31, 36, 41} },
|
|
{ .posXs = {17, 26, 32, 44} }
|
|
};
|
|
|
|
//Calculate the amount of the various kinds of options and pre-select the first single one
|
|
u32 multiOptionsAmount = sizeof(multiOptions) / sizeof(struct multiOption),
|
|
singleOptionsAmount = sizeof(singleOptionsText) / sizeof(char *),
|
|
totalIndexes = multiOptionsAmount + singleOptionsAmount - 1,
|
|
selectedOption = multiOptionsAmount;
|
|
|
|
struct singleOption {
|
|
int posY;
|
|
u32 enabled;
|
|
} singleOptions[singleOptionsAmount];
|
|
|
|
//Parse the existing options
|
|
for(u32 i = 0; i < multiOptionsAmount; i++)
|
|
multiOptions[i].enabled = MULTICONFIG(i);
|
|
for(u32 i = 0; i < singleOptionsAmount; i++)
|
|
singleOptions[i].enabled = CONFIG(i);
|
|
|
|
//Character to display a selected option
|
|
char selected = 'x';
|
|
|
|
int endPos = 42;
|
|
|
|
//Display all the multiple choice options in white
|
|
for(u32 i = 0; i < multiOptionsAmount; i++)
|
|
{
|
|
multiOptions[i].posY = endPos + SPACING_Y;
|
|
endPos = drawString(multiOptionsText[i], 10, multiOptions[i].posY, COLOR_WHITE);
|
|
drawCharacter(selected, 10 + multiOptions[i].posXs[multiOptions[i].enabled] * SPACING_X, multiOptions[i].posY, COLOR_WHITE);
|
|
}
|
|
|
|
endPos += SPACING_Y / 2;
|
|
u32 color = COLOR_RED;
|
|
|
|
//Display all the normal options in white except for the first one
|
|
for(u32 i = 0; i < singleOptionsAmount; i++)
|
|
{
|
|
singleOptions[i].posY = endPos + SPACING_Y;
|
|
endPos = drawString(singleOptionsText[i], 10, singleOptions[i].posY, color);
|
|
if(singleOptions[i].enabled) drawCharacter(selected, 10 + SPACING_X, singleOptions[i].posY, color);
|
|
color = COLOR_WHITE;
|
|
}
|
|
|
|
u32 pressed = 0;
|
|
|
|
//Boring configuration menu
|
|
while(pressed != BUTTON_START)
|
|
{
|
|
do
|
|
{
|
|
pressed = waitInput();
|
|
}
|
|
while(!(pressed & MENU_BUTTONS));
|
|
|
|
if(pressed != BUTTON_A)
|
|
{
|
|
//Remember the previously selected option
|
|
u32 oldSelectedOption = selectedOption;
|
|
|
|
switch(pressed)
|
|
{
|
|
case BUTTON_UP:
|
|
selectedOption = !selectedOption ? totalIndexes : selectedOption - 1;
|
|
break;
|
|
case BUTTON_DOWN:
|
|
selectedOption = selectedOption == totalIndexes ? 0 : selectedOption + 1;
|
|
break;
|
|
case BUTTON_LEFT:
|
|
selectedOption = 0;
|
|
break;
|
|
case BUTTON_RIGHT:
|
|
selectedOption = totalIndexes;
|
|
break;
|
|
default:
|
|
continue;
|
|
}
|
|
|
|
if(selectedOption == oldSelectedOption) continue;
|
|
|
|
//The user moved to a different option, print the old option in white and the new one in red. Only print 'x's if necessary
|
|
if(oldSelectedOption < multiOptionsAmount)
|
|
{
|
|
drawString(multiOptionsText[oldSelectedOption], 10, multiOptions[oldSelectedOption].posY, COLOR_WHITE);
|
|
drawCharacter(selected, 10 + multiOptions[oldSelectedOption].posXs[multiOptions[oldSelectedOption].enabled] * SPACING_X, multiOptions[oldSelectedOption].posY, COLOR_WHITE);
|
|
}
|
|
else
|
|
{
|
|
u32 singleOldSelected = oldSelectedOption - multiOptionsAmount;
|
|
drawString(singleOptionsText[singleOldSelected], 10, singleOptions[singleOldSelected].posY, COLOR_WHITE);
|
|
if(singleOptions[singleOldSelected].enabled) drawCharacter(selected, 10 + SPACING_X, singleOptions[singleOldSelected].posY, COLOR_WHITE);
|
|
}
|
|
|
|
if(selectedOption < multiOptionsAmount)
|
|
drawString(multiOptionsText[selectedOption], 10, multiOptions[selectedOption].posY, COLOR_RED);
|
|
else
|
|
{
|
|
u32 singleSelected = selectedOption - multiOptionsAmount;
|
|
drawString(singleOptionsText[singleSelected], 10, singleOptions[singleSelected].posY, COLOR_RED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//The selected option's status changed, print the 'x's accordingly
|
|
if(selectedOption < multiOptionsAmount)
|
|
{
|
|
u32 oldEnabled = multiOptions[selectedOption].enabled;
|
|
drawCharacter(selected, 10 + multiOptions[selectedOption].posXs[oldEnabled] * SPACING_X, multiOptions[selectedOption].posY, COLOR_BLACK);
|
|
multiOptions[selectedOption].enabled = oldEnabled == 3 ? 0 : oldEnabled + 1;
|
|
}
|
|
else
|
|
{
|
|
u32 oldEnabled = singleOptions[selectedOption - multiOptionsAmount].enabled;
|
|
singleOptions[selectedOption - multiOptionsAmount].enabled = !oldEnabled;
|
|
if(oldEnabled) drawCharacter(selected, 10 + SPACING_X, singleOptions[selectedOption - multiOptionsAmount].posY, COLOR_BLACK);
|
|
}
|
|
}
|
|
|
|
//In any case, if the current option is enabled (or a multiple choice option is selected) we must display a red 'x'
|
|
if(selectedOption < multiOptionsAmount)
|
|
drawCharacter(selected, 10 + multiOptions[selectedOption].posXs[multiOptions[selectedOption].enabled] * SPACING_X, multiOptions[selectedOption].posY, COLOR_RED);
|
|
else
|
|
{
|
|
u32 singleSelected = selectedOption - multiOptionsAmount;
|
|
if(singleOptions[singleSelected].enabled) drawCharacter(selected, 10 + SPACING_X, singleOptions[singleSelected].posY, COLOR_RED);
|
|
}
|
|
}
|
|
|
|
//Preserve the last-used boot options (last 12 bits)
|
|
config &= 0x3F;
|
|
|
|
//Parse and write the new configuration
|
|
for(u32 i = 0; i < multiOptionsAmount; i++)
|
|
config |= multiOptions[i].enabled << (i * 2 + 6);
|
|
for(u32 i = 0; i < singleOptionsAmount; i++)
|
|
config |= singleOptions[i].enabled << (i + 16);
|
|
|
|
fileWrite(&config, configPath, 4);
|
|
|
|
//Zero the last booted FIRM flag
|
|
CFG_BOOTENV = 0;
|
|
|
|
mcuReboot();
|
|
} |