Rewrote config menu to allow for multiple choice settings, made the N3DS CPU patch configurable in the NTR way, changed the config.bin format to be more future-proof (settings are on the leftmost part), added more macros to read settings
This commit is contained in:
parent
4fabe1f704
commit
e9449f86bf
@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
#ifndef PATH_MAX
|
#ifndef PATH_MAX
|
||||||
#define PATH_MAX 255
|
#define PATH_MAX 255
|
||||||
|
#define CONFIG(a) ((config >> (a + 16)) & 1)
|
||||||
|
#define MULTICONFIG(a) ((config >> (a * 2 + 6)) & 3)
|
||||||
|
#define BOOTCONFIG(a, b) ((config >> a) & b)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static u32 config = 0;
|
static u32 config = 0;
|
||||||
@ -206,11 +209,11 @@ void patchCode(u64 progId, u8 *code, u32 size)
|
|||||||
case 0x0004001000027000LL: // KOR MSET
|
case 0x0004001000027000LL: // KOR MSET
|
||||||
case 0x0004001000028000LL: // TWN MSET
|
case 0x0004001000028000LL: // TWN MSET
|
||||||
{
|
{
|
||||||
if(R_SUCCEEDED(loadConfig()) && ((config >> 6) & 1))
|
if(R_SUCCEEDED(loadConfig()) && CONFIG(6))
|
||||||
{
|
{
|
||||||
static const u16 verPattern[] = u"Ver.";
|
static const u16 verPattern[] = u"Ver.";
|
||||||
const u32 currentNand = ((config >> 16) & 3);
|
const u32 currentNand = BOOTCONFIG(0, 3);
|
||||||
const u32 matchingFirm = ((config >> 18) & 1) == (currentNand != 0);
|
const u32 matchingFirm = BOOTCONFIG(2, 1) == (currentNand != 0);
|
||||||
|
|
||||||
//Patch Ver. string
|
//Patch Ver. string
|
||||||
patchMemory(code, size,
|
patchMemory(code, size,
|
||||||
@ -242,7 +245,7 @@ void patchCode(u64 progId, u8 *code, u32 size)
|
|||||||
sizeof(stopCartUpdatesPatch), 2
|
sizeof(stopCartUpdatesPatch), 2
|
||||||
);
|
);
|
||||||
|
|
||||||
if(R_SUCCEEDED(loadConfig()) && ((config >> 4) & 1))
|
if(R_SUCCEEDED(loadConfig()) && MULTICONFIG(1))
|
||||||
{
|
{
|
||||||
static const u8 cfgN3dsCpuPattern[] = {
|
static const u8 cfgN3dsCpuPattern[] = {
|
||||||
0x40, 0xA0, 0xE1, 0x07, 0x00
|
0x40, 0xA0, 0xE1, 0x07, 0x00
|
||||||
@ -254,7 +257,7 @@ void patchCode(u64 progId, u8 *code, u32 size)
|
|||||||
if(cfgN3dsCpuLoc != NULL)
|
if(cfgN3dsCpuLoc != NULL)
|
||||||
{
|
{
|
||||||
*(u32 *)(cfgN3dsCpuLoc + 3) = 0xE1A00000;
|
*(u32 *)(cfgN3dsCpuLoc + 3) = 0xE1A00000;
|
||||||
*(u32 *)(cfgN3dsCpuLoc + 0x1F) = 0xE3A00003;
|
*(u32 *)(cfgN3dsCpuLoc + 0x1F) = 0xE3A00000 + MULTICONFIG(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
212
source/config.c
212
source/config.c
@ -19,128 +19,162 @@ void configureCFW(const char *configPath)
|
|||||||
drawString(CONFIG_TITLE, 10, 10, COLOR_TITLE);
|
drawString(CONFIG_TITLE, 10, 10, COLOR_TITLE);
|
||||||
drawString("Press A to select, START to save and reboot", 10, 30, COLOR_WHITE);
|
drawString("Press A to select, START to save and reboot", 10, 30, COLOR_WHITE);
|
||||||
|
|
||||||
const char *optionsText[] = { "Screen-init brightness: 4( ) 3( ) 2( ) 1( )",
|
const char *multiOptionsText[] = { "Screen-init brightness: 4( ) 3( ) 2( ) 1( )",
|
||||||
"( ) Autoboot SysNAND",
|
"New 3DS CPU: Off( ) L2( ) Clock( ) L2+Clock( )" };
|
||||||
"( ) Updated SysNAND mode (A9LH-only)",
|
|
||||||
"( ) Force A9LH detection",
|
|
||||||
"( ) Use second EmuNAND as default",
|
|
||||||
"( ) Force max N3DS clock speed and L2 cache",
|
|
||||||
"( ) Use developer UNITINFO",
|
|
||||||
"( ) Show current NAND in System Settings",
|
|
||||||
"( ) Show GBA boot screen in patched AGB_FIRM",
|
|
||||||
"( ) Enable splash screen with no screen-init" };
|
|
||||||
|
|
||||||
u32 optionsAmount = sizeof(optionsText) / sizeof(char *);
|
const char *singleOptionsText[] = { "( ) Autoboot SysNAND",
|
||||||
|
"( ) Updated SysNAND mode (A9LH-only)",
|
||||||
|
"( ) Force A9LH detection",
|
||||||
|
"( ) Use second EmuNAND as default",
|
||||||
|
"( ) Use developer UNITINFO",
|
||||||
|
"( ) Show current NAND in System Settings",
|
||||||
|
"( ) Show GBA boot screen in patched AGB_FIRM",
|
||||||
|
"( ) Enable splash screen with no screen-init" };
|
||||||
|
|
||||||
struct option {
|
struct multiOption {
|
||||||
int posY;
|
int posY;
|
||||||
u32 enabled;
|
u32 enabled;
|
||||||
} options[optionsAmount];
|
int posXs[4];
|
||||||
|
} multiOptions[] = {
|
||||||
|
{ .posXs = {26, 31, 36, 41} },
|
||||||
|
{ .posXs = {17, 23, 32, 44} }
|
||||||
|
};
|
||||||
|
|
||||||
//Parse the existing configuration
|
//Calculate the amount of the various kinds of options and pre-select the first single one
|
||||||
options[0].enabled = CONFIG(14, 3);
|
u32 multiOptionsAmount = sizeof(multiOptions) / sizeof(struct multiOption),
|
||||||
for(u32 i = optionsAmount - 1; i; i--)
|
singleOptionsAmount = sizeof(singleOptionsText) / sizeof(char *),
|
||||||
options[i].enabled = CONFIG((i - 1), 1);
|
totalOptions = multiOptionsAmount + singleOptionsAmount,
|
||||||
|
selectedOption = multiOptionsAmount;
|
||||||
|
|
||||||
//Pre-select the first configuration option
|
struct singleOption {
|
||||||
u32 selectedOption = 1,
|
int posY;
|
||||||
oldSelectedOption = 0,
|
u32 enabled;
|
||||||
optionChanged = 0;
|
} 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
|
//Character to display a selected option
|
||||||
char selected = 'x';
|
char selected = 'x';
|
||||||
|
|
||||||
//Starting position
|
int endPos = 42;
|
||||||
options[0].posY = 52;
|
|
||||||
|
|
||||||
//Display all the normal options in white, brightness will be displayed later
|
//Display all the normal options in white
|
||||||
for(u32 i = 1; i < optionsAmount; i++)
|
for(u32 i = 0; i < multiOptionsAmount; i++)
|
||||||
{
|
{
|
||||||
static int endPos = 59;
|
multiOptions[i].posY = endPos + SPACING_Y;
|
||||||
options[i].posY = endPos + SPACING_Y;
|
endPos = drawString(multiOptionsText[i], 10, multiOptions[i].posY, COLOR_WHITE);
|
||||||
endPos = drawString(optionsText[i], 10, options[i].posY, COLOR_WHITE);
|
drawCharacter(selected, 10 + multiOptions[i].posXs[multiOptions[i].enabled] * SPACING_X, multiOptions[i].posY, COLOR_WHITE);
|
||||||
if(options[i].enabled) drawCharacter(selected, 10 + SPACING_X, options[i].posY, COLOR_WHITE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Boring configuration menu
|
//Display the first normal option in red
|
||||||
while(1)
|
singleOptions[0].posY = endPos + SPACING_Y + SPACING_Y / 2;
|
||||||
|
endPos = drawString(singleOptionsText[0], 10, singleOptions[0].posY, COLOR_RED);
|
||||||
|
|
||||||
|
//Display all the multiple choice options in white except for the first
|
||||||
|
for(u32 i = 1; i < singleOptionsAmount; i++)
|
||||||
{
|
{
|
||||||
u32 pressed = 0;
|
singleOptions[i].posY = endPos + SPACING_Y;
|
||||||
|
endPos = drawString(singleOptionsText[i], 10, singleOptions[i].posY, COLOR_WHITE);
|
||||||
|
if(singleOptions[i].enabled) drawCharacter(selected, 10 + SPACING_X, singleOptions[i].posY, COLOR_WHITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 pressed = 0;
|
||||||
|
|
||||||
|
//Boring configuration menu
|
||||||
|
while(pressed != BUTTON_START)
|
||||||
|
{
|
||||||
|
pressed = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
//The status of the selected option changed, black out the previously visible 'x' if needed
|
//In any case, if the current option is enabled (or a multiple choice option is selected) we must display a red 'x'
|
||||||
if(optionChanged)
|
if(selectedOption < multiOptionsAmount)
|
||||||
{
|
drawCharacter(selected, 10 + multiOptions[selectedOption].posXs[multiOptions[selectedOption].enabled] * SPACING_X, multiOptions[selectedOption].posY, COLOR_RED);
|
||||||
if(!selectedOption)
|
else if(singleOptions[selectedOption - multiOptionsAmount].enabled)
|
||||||
drawCharacter(selected, 10 + (26 + 5 * (optionChanged - 1)) * SPACING_X, options[0].posY, COLOR_BLACK);
|
drawCharacter(selected, 10 + SPACING_X, singleOptions[selectedOption - multiOptionsAmount].posY, COLOR_RED);
|
||||||
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();
|
pressed = waitInput();
|
||||||
}
|
}
|
||||||
while(!(pressed & MENU_BUTTONS));
|
while(!(pressed & MENU_BUTTONS));
|
||||||
|
|
||||||
//Remember the previously selected option
|
//Remember the previously selected option
|
||||||
|
static u32 oldSelectedOption;
|
||||||
oldSelectedOption = selectedOption;
|
oldSelectedOption = selectedOption;
|
||||||
|
|
||||||
switch(pressed)
|
if(pressed != BUTTON_A)
|
||||||
{
|
{
|
||||||
case BUTTON_UP:
|
switch(pressed)
|
||||||
selectedOption = !selectedOption ? optionsAmount - 1 : selectedOption - 1;
|
{
|
||||||
break;
|
case BUTTON_UP:
|
||||||
case BUTTON_DOWN:
|
selectedOption = !selectedOption ? totalOptions - 1 : selectedOption - 1;
|
||||||
selectedOption = selectedOption == (optionsAmount - 1) ? 1 : selectedOption + 1;
|
break;
|
||||||
break;
|
case BUTTON_DOWN:
|
||||||
case BUTTON_LEFT:
|
selectedOption = selectedOption == (totalOptions - 1) ? 0 : selectedOption + 1;
|
||||||
selectedOption = 1;
|
break;
|
||||||
break;
|
case BUTTON_LEFT:
|
||||||
case BUTTON_RIGHT:
|
if(!selectedOption) continue;
|
||||||
selectedOption = optionsAmount - 1;
|
selectedOption = 0;
|
||||||
break;
|
break;
|
||||||
case BUTTON_A:
|
case BUTTON_RIGHT:
|
||||||
optionChanged = 1;
|
if(selectedOption == totalOptions - 1) continue;
|
||||||
if(selectedOption) options[selectedOption].enabled = !options[selectedOption].enabled;
|
selectedOption = totalOptions - 1;
|
||||||
else
|
break;
|
||||||
{
|
default:
|
||||||
optionChanged += options[0].enabled;
|
continue;
|
||||||
options[0].enabled = options[0].enabled == 3 ? 0 : options[0].enabled + 1;
|
}
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pressed == BUTTON_START) break;
|
//The user moved to a different option, print the old option in white and the new one in white. 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Preserve the last-used boot options (last 12 bits)
|
//Preserve the last-used boot options (last 12 bits)
|
||||||
config &= 0xFF0000;
|
config &= 0x3F;
|
||||||
|
|
||||||
//Parse and write the new configuration
|
//Parse and write the new configuration
|
||||||
config |= options[0].enabled << 14;
|
for(u32 i = 0; i < multiOptionsAmount; i++)
|
||||||
for(u32 i = optionsAmount - 1; i; i--)
|
config |= multiOptions[i].enabled << (i * 2 + 6);
|
||||||
config |= options[i].enabled << (i - 1);
|
for(u32 i = 0; i < singleOptionsAmount; i++)
|
||||||
|
config |= singleOptions[i].enabled << (i + 16);
|
||||||
|
|
||||||
fileWrite(&config, configPath, 3);
|
fileWrite(&config, configPath, 4);
|
||||||
|
|
||||||
//Zero the last booted FIRM flag
|
//Zero the last booted FIRM flag
|
||||||
CFG_BOOTENV = 0;
|
CFG_BOOTENV = 0;
|
||||||
|
@ -9,7 +9,10 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define CFG_BOOTENV (*(vu32 *)0x10010000)
|
#define CFG_BOOTENV (*(vu32 *)0x10010000)
|
||||||
#define CONFIG(a, b) ((config >> a) & b)
|
|
||||||
|
#define CONFIG(a) ((config >> (a + 16)) & 1)
|
||||||
|
#define MULTICONFIG(a) ((config >> (a * 2 + 6)) & 3)
|
||||||
|
#define BOOTCONFIG(a, b) ((config >> a) & b)
|
||||||
|
|
||||||
extern u32 config;
|
extern u32 config;
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ void main(void)
|
|||||||
|
|
||||||
//Attempt to read the configuration file
|
//Attempt to read the configuration file
|
||||||
const char configPath[] = "/aurei/config.bin";
|
const char configPath[] = "/aurei/config.bin";
|
||||||
if(fileRead(&config, configPath, 3)) needConfig = 1;
|
if(fileRead(&config, configPath, 4)) needConfig = 1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
config = 0;
|
config = 0;
|
||||||
@ -63,10 +63,10 @@ void main(void)
|
|||||||
//'0' = NATIVE_FIRM, '1' = TWL_FIRM, '2' = AGB_FIRM
|
//'0' = NATIVE_FIRM, '1' = TWL_FIRM, '2' = AGB_FIRM
|
||||||
firmType = *(vu8 *)0x23F00005 - '0';
|
firmType = *(vu8 *)0x23F00005 - '0';
|
||||||
|
|
||||||
nandType = CONFIG(16, 3);
|
nandType = BOOTCONFIG(0, 3);
|
||||||
firmSource = CONFIG(18, 1);
|
firmSource = BOOTCONFIG(2, 1);
|
||||||
a9lhInstalled = CONFIG(19, 1);
|
a9lhInstalled = BOOTCONFIG(3, 1);
|
||||||
updatedSys = (a9lhInstalled && CONFIG(1, 1)) ? 1 : 0;
|
updatedSys = (a9lhInstalled && CONFIG(1)) ? 1 : 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -83,10 +83,10 @@ void main(void)
|
|||||||
u32 pressed = HID_PAD;
|
u32 pressed = HID_PAD;
|
||||||
|
|
||||||
//Determine if we need to autoboot sysNAND
|
//Determine if we need to autoboot sysNAND
|
||||||
u32 autoBootSys = CONFIG(0, 1);
|
u32 autoBootSys = CONFIG(0);
|
||||||
|
|
||||||
//Determine if A9LH is installed and the user has an updated sysNAND
|
//Determine if A9LH is installed and the user has an updated sysNAND
|
||||||
if(a9lhBoot || CONFIG(2, 1))
|
if(a9lhBoot || CONFIG(2))
|
||||||
{
|
{
|
||||||
if(pressed == SAFE_MODE)
|
if(pressed == SAFE_MODE)
|
||||||
error("Using Safe Mode would brick you, or remove A9LH!");
|
error("Using Safe Mode would brick you, or remove A9LH!");
|
||||||
@ -94,7 +94,7 @@ void main(void)
|
|||||||
a9lhInstalled = 1;
|
a9lhInstalled = 1;
|
||||||
|
|
||||||
//Check setting for > 9.2 sysNAND
|
//Check setting for > 9.2 sysNAND
|
||||||
updatedSys = CONFIG(1, 1);
|
updatedSys = CONFIG(1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -102,7 +102,7 @@ void main(void)
|
|||||||
updatedSys = 0;
|
updatedSys = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
newConfig = a9lhInstalled << 19;
|
newConfig = a9lhInstalled << 3;
|
||||||
|
|
||||||
/* If booting with A9LH, it's a MCU reboot and a previous configuration exists,
|
/* If booting with A9LH, it's a MCU reboot and a previous configuration exists,
|
||||||
try to force boot options */
|
try to force boot options */
|
||||||
@ -112,18 +112,18 @@ void main(void)
|
|||||||
if(previousFirm == 7)
|
if(previousFirm == 7)
|
||||||
{
|
{
|
||||||
nandType = 0;
|
nandType = 0;
|
||||||
firmSource = updatedSys ? 0 : CONFIG(18, 1);
|
firmSource = updatedSys ? 0 : BOOTCONFIG(0, 3);
|
||||||
needConfig = 0;
|
needConfig = 0;
|
||||||
|
|
||||||
//Flag to prevent multiple boot options-forcing
|
//Flag to prevent multiple boot options-forcing
|
||||||
newConfig |= 1 << 20;
|
newConfig |= 1 << 4;
|
||||||
}
|
}
|
||||||
/* Else, force the last used boot options unless a payload button or A/L/R are pressed
|
/* Else, force the last used boot options unless a payload button or A/L/R are pressed
|
||||||
or the no-forcing flag is set */
|
or the no-forcing flag is set */
|
||||||
else if(!(pressed & OVERRIDE_BUTTONS) && !CONFIG(20, 1))
|
else if(!(pressed & OVERRIDE_BUTTONS) && !BOOTCONFIG(4, 1))
|
||||||
{
|
{
|
||||||
nandType = CONFIG(16, 3);
|
nandType = BOOTCONFIG(0, 3);
|
||||||
firmSource = CONFIG(18, 1);
|
firmSource = BOOTCONFIG(2, 1);
|
||||||
needConfig = 0;
|
needConfig = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,14 +142,14 @@ void main(void)
|
|||||||
configureCFW(configPath);
|
configureCFW(configPath);
|
||||||
|
|
||||||
//If screens are inited or the corresponding option is set, load splash screen
|
//If screens are inited or the corresponding option is set, load splash screen
|
||||||
if(PDN_GPU_CNT != 1 || CONFIG(8, 1)) loadSplash();
|
if(PDN_GPU_CNT != 1 || CONFIG(7)) loadSplash();
|
||||||
|
|
||||||
//Determine if we need to boot an emuNAND or sysNAND
|
//Determine if we need to boot an emuNAND or sysNAND
|
||||||
nandType = (pressed & BUTTON_L1) ? autoBootSys : ((pressed & BUTTON_R1) ? updatedSys : !autoBootSys);
|
nandType = (pressed & BUTTON_L1) ? autoBootSys : ((pressed & BUTTON_R1) ? updatedSys : !autoBootSys);
|
||||||
|
|
||||||
/* If we're booting emuNAND the second emuNAND is set as default and B isn't pressed,
|
/* If we're booting emuNAND the second emuNAND is set as default and B isn't pressed,
|
||||||
or vice-versa, boot the second emuNAND */
|
or vice-versa, boot the second emuNAND */
|
||||||
if(nandType && ((!(pressed & BUTTON_B)) == CONFIG(3, 1))) nandType++;
|
if(nandType && ((!(pressed & BUTTON_B)) == CONFIG(3))) nandType++;
|
||||||
|
|
||||||
//Determine the NAND we should take the FIRM from
|
//Determine the NAND we should take the FIRM from
|
||||||
firmSource = (pressed & BUTTON_R1) ? !nandType : (nandType != 0);
|
firmSource = (pressed & BUTTON_R1) ? !nandType : (nandType != 0);
|
||||||
@ -169,16 +169,16 @@ void main(void)
|
|||||||
|
|
||||||
if(!bootType)
|
if(!bootType)
|
||||||
{
|
{
|
||||||
newConfig |= (nandType << 16) | (firmSource << 18);
|
newConfig |= nandType | (firmSource << 2);
|
||||||
|
|
||||||
/* If the boot configuration is different from previously, overwrite it.
|
/* If the boot configuration is different from previously, overwrite it.
|
||||||
Just the no-forcing flag being set is not enough */
|
Just the no-forcing flag being set is not enough */
|
||||||
if((newConfig & 0xEF0000) != (config & 0xFF0000))
|
if((newConfig & 0x2F) != (config & 0xFF))
|
||||||
{
|
{
|
||||||
//Preserve user settings (first 2 bytes)
|
//Preserve user settings (first 2 bytes)
|
||||||
newConfig |= config & 0xFFFF;
|
newConfig |= config & 0xFFFFFFC0;
|
||||||
|
|
||||||
fileWrite(&newConfig, configPath, 3);
|
fileWrite(&newConfig, configPath, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,7 +271,7 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhInstalle
|
|||||||
*(u16 *)sigOffset2 = sigPatch[0];
|
*(u16 *)sigOffset2 = sigPatch[0];
|
||||||
*((u16 *)sigOffset2 + 1) = sigPatch[1];
|
*((u16 *)sigOffset2 + 1) = sigPatch[1];
|
||||||
|
|
||||||
if(CONFIG(5, 1))
|
if(CONFIG(4))
|
||||||
{
|
{
|
||||||
//Apply UNITINFO patch
|
//Apply UNITINFO patch
|
||||||
u8 *unitInfoOffset = getUnitInfoValueSet(arm9Section, section[2].size);
|
u8 *unitInfoOffset = getUnitInfoValueSet(arm9Section, section[2].size);
|
||||||
@ -383,7 +383,7 @@ static inline void patchTwlAgbFirm(u32 firmType)
|
|||||||
|
|
||||||
/* Calculate the amount of patches to apply. Only count the boot screen patch for AGB_FIRM
|
/* Calculate the amount of patches to apply. Only count the boot screen patch for AGB_FIRM
|
||||||
if the matching option was enabled (keep it as last) */
|
if the matching option was enabled (keep it as last) */
|
||||||
u32 numPatches = firmType == 1 ? (sizeof(twlPatches) / sizeof(patchData)) : (sizeof(agbPatches) / sizeof(patchData) - !CONFIG(7, 1));
|
u32 numPatches = firmType == 1 ? (sizeof(twlPatches) / sizeof(patchData)) : (sizeof(agbPatches) / sizeof(patchData) - !CONFIG(6));
|
||||||
const patchData *patches = firmType == 1 ? twlPatches : agbPatches;
|
const patchData *patches = firmType == 1 ? twlPatches : agbPatches;
|
||||||
|
|
||||||
//Patch
|
//Patch
|
||||||
|
11
source/fs.c
11
source/fs.c
@ -96,8 +96,8 @@ void firmRead(void *dest, const char *firmFolder)
|
|||||||
u32 tempId = 0;
|
u32 tempId = 0;
|
||||||
for(char *tmp = info.fname; (*tmp) != '.'; tmp++)
|
for(char *tmp = info.fname; (*tmp) != '.'; tmp++)
|
||||||
{
|
{
|
||||||
if((*tmp) > '9') tempId = (tempId << 4) + ((*tmp) - 'A') + 9;
|
tempId <<= 4;
|
||||||
else tempId = (tempId << 4) + (*tmp) - '0';
|
tempId += *tmp > '9' ? (*tmp - 'A') + 9 : (*tmp) - '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
//Found a newer cxi
|
//Found a newer cxi
|
||||||
@ -116,13 +116,10 @@ void firmRead(void *dest, const char *firmFolder)
|
|||||||
while(id > 15)
|
while(id > 15)
|
||||||
{
|
{
|
||||||
u32 remainder = (id % 16);
|
u32 remainder = (id % 16);
|
||||||
if(remainder > 9) path[i] = remainder - 9 + 'A';
|
path[i--] = remainder > 9 ? remainder - 9 + 'A' : remainder + '0';
|
||||||
else path[i] = remainder + '0';
|
|
||||||
id /= 16;
|
id /= 16;
|
||||||
i--;
|
|
||||||
}
|
}
|
||||||
if(id > 9) path[i] = id - 9 + 'A';
|
path[i] = id > 9 ? id - 9 + 'A' : id + '0';
|
||||||
else path[i] = id + '0';
|
|
||||||
|
|
||||||
fileRead(dest, path, 0);
|
fileRead(dest, path, 0);
|
||||||
}
|
}
|
@ -54,7 +54,7 @@ void initScreens(void)
|
|||||||
memcpy((void *)SCREENINIT_ADDRESS, screeninit, screeninit_size);
|
memcpy((void *)SCREENINIT_ADDRESS, screeninit, screeninit_size);
|
||||||
|
|
||||||
//Write brightness level for the stub to pick up
|
//Write brightness level for the stub to pick up
|
||||||
*(vu32 *)(SCREENINIT_ADDRESS + 8) = CONFIG(14, 3);
|
*(vu32 *)(SCREENINIT_ADDRESS + 8) = MULTICONFIG(0);
|
||||||
|
|
||||||
*arm11Entry = SCREENINIT_ADDRESS;
|
*arm11Entry = SCREENINIT_ADDRESS;
|
||||||
while(*arm11Entry);
|
while(*arm11Entry);
|
||||||
|
Reference in New Issue
Block a user