Add option to run rosalina on N3DS SAFE_FIRM.
Also enables a qtm error bypass
This commit is contained in:
parent
7dc2b7123b
commit
166bdbeb7d
@ -95,6 +95,7 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
|||||||
"( ) Show GBA boot screen in patched AGB_FIRM",
|
"( ) Show GBA boot screen in patched AGB_FIRM",
|
||||||
"( ) Set developer UNITINFO",
|
"( ) Set developer UNITINFO",
|
||||||
"( ) Disable Arm11 exception handlers",
|
"( ) Disable Arm11 exception handlers",
|
||||||
|
"( ) Enable Rosalina on SAFE_FIRM",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *optionsDescription[] = { "Select the default EmuNAND.\n\n"
|
static const char *optionsDescription[] = { "Select the default EmuNAND.\n\n"
|
||||||
@ -193,7 +194,16 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
|||||||
"Note: Disabling the exception handlers\n"
|
"Note: Disabling the exception handlers\n"
|
||||||
"will disqualify you from submitting\n"
|
"will disqualify you from submitting\n"
|
||||||
"issues or bug reports to the Luma3DS\n"
|
"issues or bug reports to the Luma3DS\n"
|
||||||
"GitHub repository!"
|
"GitHub repository!",
|
||||||
|
|
||||||
|
"Enables Rosalina, the kernel ext.\n"
|
||||||
|
"and sysmodule reimplementations on\n"
|
||||||
|
"SAFE_FIRM (New 3DS only).\n\n"
|
||||||
|
"Also suppresses QTM error 0xF96183FE,\n"
|
||||||
|
"allowing to use 8.1-11.3 N3DS on\n"
|
||||||
|
"New 2DS XL consoles.\n\n"
|
||||||
|
"Only select this if you know what you\n"
|
||||||
|
"are doing!",
|
||||||
};
|
};
|
||||||
|
|
||||||
FirmwareSource nandType = FIRMWARE_SYSNAND;
|
FirmwareSource nandType = FIRMWARE_SYSNAND;
|
||||||
@ -229,7 +239,8 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
|||||||
{ .visible = true },
|
{ .visible = true },
|
||||||
{ .visible = true },
|
{ .visible = true },
|
||||||
{ .visible = true },
|
{ .visible = true },
|
||||||
{ .visible = true }
|
{ .visible = true },
|
||||||
|
{ .visible = ISN3DS },
|
||||||
};
|
};
|
||||||
|
|
||||||
//Calculate the amount of the various kinds of options and pre-select the first single one
|
//Calculate the amount of the various kinds of options and pre-select the first single one
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
#define CONFIG_FILE "config.bin"
|
#define CONFIG_FILE "config.bin"
|
||||||
#define CONFIG_VERSIONMAJOR 2
|
#define CONFIG_VERSIONMAJOR 2
|
||||||
#define CONFIG_VERSIONMINOR 3
|
#define CONFIG_VERSIONMINOR 4
|
||||||
|
|
||||||
#define BOOTCFG_NAND BOOTCONFIG(0, 7)
|
#define BOOTCFG_NAND BOOTCONFIG(0, 7)
|
||||||
#define BOOTCFG_FIRM BOOTCONFIG(3, 7)
|
#define BOOTCFG_FIRM BOOTCONFIG(3, 7)
|
||||||
@ -60,7 +60,8 @@ enum singleOptions
|
|||||||
PATCHVERSTRING,
|
PATCHVERSTRING,
|
||||||
SHOWGBABOOT,
|
SHOWGBABOOT,
|
||||||
PATCHUNITINFO,
|
PATCHUNITINFO,
|
||||||
DISABLEARM11EXCHANDLERS
|
DISABLEARM11EXCHANDLERS,
|
||||||
|
ENABLESAFEFIRMROSALINA,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum ConfigurationStatus
|
typedef enum ConfigurationStatus
|
||||||
|
@ -278,7 +278,8 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo
|
|||||||
srcModuleSize = moduleList[nbModules].size = ((Cxi *)src)->ncch.contentSize * 0x200;
|
srcModuleSize = moduleList[nbModules].size = ((Cxi *)src)->ncch.contentSize * 0x200;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(firmType == NATIVE_FIRM && (ISN3DS || firmVersion >= 0x1D))
|
// SAFE_FIRM only for N3DS and only if ENABLESAFEFIRMROSALINA is on
|
||||||
|
if((firmType == NATIVE_FIRM || firmType == SAFE_FIRM) && (ISN3DS || firmVersion >= 0x1D))
|
||||||
{
|
{
|
||||||
//2) Merge that info with our own modules'
|
//2) Merge that info with our own modules'
|
||||||
for(u8 *src = (u8 *)0x18180000; memcmp(((Cxi *)src)->ncch.magic, "NCCH", 4) == 0; src += srcModuleSize)
|
for(u8 *src = (u8 *)0x18180000; memcmp(((Cxi *)src)->ncch.magic, "NCCH", 4) == 0; src += srcModuleSize)
|
||||||
@ -303,7 +304,9 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo
|
|||||||
//3) Read or copy the modules
|
//3) Read or copy the modules
|
||||||
u8 *dst = firm->section[0].address;
|
u8 *dst = firm->section[0].address;
|
||||||
const char *extModuleSizeError = "The external FIRM modules are too large.";
|
const char *extModuleSizeError = "The external FIRM modules are too large.";
|
||||||
for(u32 i = 0, dstModuleSize, maxModuleSize = firmType == NATIVE_FIRM ? 0x80000 : 0x600000; i < nbModules; i++, dst += dstModuleSize, maxModuleSize -= dstModuleSize)
|
// SAFE_FIRM only for N3DS and only if ENABLESAFEFIRMROSALINA is on
|
||||||
|
u32 maxModuleSize = (firmType == NATIVE_FIRM || firmType == SAFE_FIRM) ? 0x80000 : 0x600000;
|
||||||
|
for(u32 i = 0, dstModuleSize; i < nbModules; i++, dst += dstModuleSize, maxModuleSize -= dstModuleSize)
|
||||||
{
|
{
|
||||||
if(loadFromStorage)
|
if(loadFromStorage)
|
||||||
{
|
{
|
||||||
@ -335,7 +338,7 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo
|
|||||||
memcpy(dst, moduleList[i].src, dstModuleSize);
|
memcpy(dst, moduleList[i].src, dstModuleSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
//4) Patch NATIVE_FIRM if necessary
|
//4) Patch NATIVE_FIRM/SAFE_FIRM (N3DS) if necessary
|
||||||
if(nbModules == 6)
|
if(nbModules == 6)
|
||||||
{
|
{
|
||||||
if(patchK11ModuleLoading(firm->section[0].size, dst - firm->section[0].address, (u8 *)firm + firm->section[1].offset, firm->section[1].size) != 0)
|
if(patchK11ModuleLoading(firm->section[0].size, dst - firm->section[0].address, (u8 *)firm + firm->section[1].offset, firm->section[1].size) != 0)
|
||||||
@ -522,6 +525,31 @@ u32 patch1x2xNativeAndSafeFirm(void)
|
|||||||
ret += patchArm9ExceptionHandlersInstall(arm9Section, kernel9Size);
|
ret += patchArm9ExceptionHandlersInstall(arm9Section, kernel9Size);
|
||||||
ret += patchSvcBreak9(arm9Section, kernel9Size, (u32)firm->section[2].address);
|
ret += patchSvcBreak9(arm9Section, kernel9Size, (u32)firm->section[2].address);
|
||||||
|
|
||||||
|
if(ISN3DS && CONFIG(ENABLESAFEFIRMROSALINA))
|
||||||
|
{
|
||||||
|
u8 *arm11Section1 = (u8 *)firm + firm->section[1].offset;
|
||||||
|
//Find the Kernel11 SVC table and handler, exceptions page and free space locations
|
||||||
|
u32 baseK11VA;
|
||||||
|
u8 *freeK11Space;
|
||||||
|
u32 *arm11SvcHandler,
|
||||||
|
*arm11ExceptionsPage,
|
||||||
|
*arm11SvcTable = getKernel11Info(arm11Section1, firm->section[1].size, &baseK11VA, &freeK11Space, &arm11SvcHandler, &arm11ExceptionsPage);
|
||||||
|
|
||||||
|
ret += installK11Extension(arm11Section1, firm->section[1].size, false, baseK11VA, arm11ExceptionsPage, &freeK11Space);
|
||||||
|
ret += patchKernel11(arm11Section1, firm->section[1].size, baseK11VA, arm11SvcTable, arm11ExceptionsPage);
|
||||||
|
|
||||||
|
// Add some other patches to the mix, as we can now launch homebrew on SAFE_FIRM:
|
||||||
|
|
||||||
|
//Apply firmlaunch patches
|
||||||
|
ret += patchFirmlaunches(process9Offset, process9Size, process9MemAddr);
|
||||||
|
|
||||||
|
ret += patchKernel9Panic(arm9Section, kernel9Size);
|
||||||
|
ret += patchP9AccessChecks(process9Offset, process9Size);
|
||||||
|
|
||||||
|
mergeSection0(NATIVE_FIRM, 0x45, false); // may change in the future
|
||||||
|
firm->section[0].size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,5 +33,6 @@ enum singleOptions
|
|||||||
PATCHVERSTRING,
|
PATCHVERSTRING,
|
||||||
SHOWGBABOOT,
|
SHOWGBABOOT,
|
||||||
PATCHUNITINFO,
|
PATCHUNITINFO,
|
||||||
DISABLEARM11EXCHANDLERS
|
DISABLEARM11EXCHANDLERS,
|
||||||
|
ENABLESAFEFIRMROSALINA,
|
||||||
};
|
};
|
||||||
|
@ -246,24 +246,24 @@ bool doErrfThrowHook(u32 *cmdbuf)
|
|||||||
u8 *srcerrbuf = (u8 *)r0_to_r7_r12_usr[(spsr & 0x20) ? 4 : 6];
|
u8 *srcerrbuf = (u8 *)r0_to_r7_r12_usr[(spsr & 0x20) ? 4 : 6];
|
||||||
const char *pname = codeSetOfProcess(currentCoreContext->objectContext.currentProcess)->processName;
|
const char *pname = codeSetOfProcess(currentCoreContext->objectContext.currentProcess)->processName;
|
||||||
|
|
||||||
static const struct
|
const struct
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
Result errCode;
|
Result errCode;
|
||||||
|
bool enabled;
|
||||||
} errorCodesToIgnore[] =
|
} errorCodesToIgnore[] =
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
If you're getting this error, you have broken your head-tracking hardware,
|
If you're getting this error, you may have broken your head-tracking hardware,
|
||||||
and should uncomment the following line:
|
and you need to enable the qtm error bypass below:
|
||||||
*/
|
*/
|
||||||
//{ "qtm", (Result)0xF96183FE },
|
{ "qtm", 0xF96183FEu, CONFIG(ENABLESAFEFIRMROSALINA)},
|
||||||
|
{ "", 0, false}, // impossible case to ensure the array has at least 1 element
|
||||||
{ "", 0 }, // impossible case to ensure the array has at least 1 element
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for(u32 i = 0; i < sizeof(errorCodesToIgnore) / sizeof(errorCodesToIgnore[0]); i++)
|
for(u32 i = 0; i < sizeof(errorCodesToIgnore) / sizeof(errorCodesToIgnore[0]); i++)
|
||||||
{
|
{
|
||||||
if(strcmp(pname, errorCodesToIgnore[i].name) == 0 && (Result)cmdbuf[2] == errorCodesToIgnore[i].errCode)
|
if(errorCodesToIgnore[i].enabled && strcmp(pname, errorCodesToIgnore[i].name) == 0 && (Result)cmdbuf[2] == errorCodesToIgnore[i].errCode)
|
||||||
{
|
{
|
||||||
srcerrbuf[0] = 5;
|
srcerrbuf[0] = 5;
|
||||||
cmdbuf[0] = 0x10040;
|
cmdbuf[0] = 0x10040;
|
||||||
|
@ -35,7 +35,8 @@ enum singleOptions
|
|||||||
PATCHVERSTRING,
|
PATCHVERSTRING,
|
||||||
SHOWGBABOOT,
|
SHOWGBABOOT,
|
||||||
PATCHUNITINFO,
|
PATCHUNITINFO,
|
||||||
DISABLEARM11EXCHANDLERS
|
DISABLEARM11EXCHANDLERS,
|
||||||
|
ENABLESAFEFIRMROSALINA,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern u32 config, multiConfig, bootConfig;
|
extern u32 config, multiConfig, bootConfig;
|
||||||
|
Reference in New Issue
Block a user