Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e99fb3aa0 | ||
|
|
060d8e9945 | ||
|
|
1026471842 | ||
|
|
645208ec82 | ||
|
|
f4c48a64ca | ||
|
|
c80ac985fe |
@@ -70,7 +70,7 @@ static int file_open(IFile *file, FS_ArchiveID id, const char *path, int flags){
|
|||||||
return IFile_Open(file, archive, ppath, flags);
|
return IFile_Open(file, archive, ppath, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int patch_secureinfo(){
|
static int load_secureinfo(){
|
||||||
IFile file;
|
IFile file;
|
||||||
Result ret;
|
Result ret;
|
||||||
u64 total;
|
u64 total;
|
||||||
@@ -78,20 +78,6 @@ static int patch_secureinfo(){
|
|||||||
if(secureinfo[0] == 0xFF)
|
if(secureinfo[0] == 0xFF)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = file_open(&file, ARCHIVE_SDMC, "/SecureInfo_A", FS_OPEN_READ);
|
|
||||||
if(R_SUCCEEDED(ret)){
|
|
||||||
ret = IFile_Read(&file, &total, secureinfo, sizeof(secureinfo));
|
|
||||||
IFile_Close(&file);
|
|
||||||
if(R_SUCCEEDED(ret) && total == sizeof(secureinfo)){
|
|
||||||
ret = file_open(&file, ARCHIVE_NAND_RW, "/sys/SecureInfo_C", FS_OPEN_WRITE | FS_OPEN_CREATE);
|
|
||||||
if(R_SUCCEEDED(ret)){
|
|
||||||
ret = IFile_Write(&file, &total, secureinfo, sizeof(secureinfo), FS_WRITE_FLUSH);
|
|
||||||
IFile_Close(&file);
|
|
||||||
}
|
|
||||||
secureinfo[0] = 0xFF; // we repurpose this byte as status
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { // get file from NAND
|
|
||||||
ret = file_open(&file, ARCHIVE_NAND_RW, "/sys/SecureInfo_C", FS_OPEN_READ);
|
ret = file_open(&file, ARCHIVE_NAND_RW, "/sys/SecureInfo_C", FS_OPEN_READ);
|
||||||
if(R_SUCCEEDED(ret)){
|
if(R_SUCCEEDED(ret)){
|
||||||
ret = IFile_Read(&file, &total, secureinfo, sizeof(secureinfo));
|
ret = IFile_Read(&file, &total, secureinfo, sizeof(secureinfo));
|
||||||
@@ -99,12 +85,11 @@ static int patch_secureinfo(){
|
|||||||
if(R_SUCCEEDED(ret) && total == sizeof(secureinfo))
|
if(R_SUCCEEDED(ret) && total == sizeof(secureinfo))
|
||||||
secureinfo[0] = 0xFF;
|
secureinfo[0] = 0xFF;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int open_config(){
|
static int load_config(){
|
||||||
IFile file;
|
IFile file;
|
||||||
Result ret;
|
Result ret;
|
||||||
u64 total;
|
u64 total;
|
||||||
@@ -122,13 +107,15 @@ static int open_config(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 patch_code(u64 progid, u8 *code, u32 size){
|
u32 patch_code(u64 progid, u8 *code, u32 size){
|
||||||
if( progid == 0x0004003000008F02LL || // USA Menu
|
switch(progid){
|
||||||
progid == 0x0004003000008202LL || // JPN Menu
|
|
||||||
progid == 0x0004003000009802LL || // EUR Menu
|
case 0x0004003000008F02LL: // USA Menu
|
||||||
progid == 0x000400300000A102LL || // CHN Menu
|
case 0x0004003000008202LL: // EUR Menu
|
||||||
progid == 0x000400300000A902LL || // KOR Menu
|
case 0x0004003000009802LL: // JPN Menu
|
||||||
progid == 0x000400300000B102LL // TWN Menu
|
case 0x000400300000A102LL: // CHN Menu
|
||||||
){
|
case 0x000400300000A902LL: // KOR Menu
|
||||||
|
case 0x000400300000B102LL: // TWN Menu
|
||||||
|
{
|
||||||
static const u8 regionFreePattern[] = {
|
static const u8 regionFreePattern[] = {
|
||||||
0x00, 0x00, 0x55, 0xE3, 0x01, 0x10, 0xA0, 0xE3
|
0x00, 0x00, 0x55, 0xE3, 0x01, 0x10, 0xA0, 0xE3
|
||||||
};
|
};
|
||||||
@@ -142,8 +129,11 @@ u32 patch_code(u64 progid, u8 *code, u32 size){
|
|||||||
regionFreePatch,
|
regionFreePatch,
|
||||||
sizeof(regionFreePatch), 1
|
sizeof(regionFreePatch), 1
|
||||||
);
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if(progid == 0x0004013000002C02LL){ // NIM
|
|
||||||
|
case 0x0004013000002C02LL: // NIM
|
||||||
|
{
|
||||||
static const u8 blockAutoUpdatesPattern[] = {
|
static const u8 blockAutoUpdatesPattern[] = {
|
||||||
0x25, 0x79, 0x0B, 0x99
|
0x25, 0x79, 0x0B, 0x99
|
||||||
};
|
};
|
||||||
@@ -156,15 +146,6 @@ u32 patch_code(u64 progid, u8 *code, u32 size){
|
|||||||
static const u8 blockEShopUpdateCheckPatch[] = {
|
static const u8 blockEShopUpdateCheckPatch[] = {
|
||||||
0x00, 0x20, 0x08, 0x60, 0x70, 0x47
|
0x00, 0x20, 0x08, 0x60, 0x70, 0x47
|
||||||
};
|
};
|
||||||
static const u8 countryRespPattern[] = {
|
|
||||||
0x01, 0x20, 0x01, 0x90, 0x22, 0x46, 0x06, 0x9B
|
|
||||||
};
|
|
||||||
static const char countryRespPatchModel[] = {
|
|
||||||
0x06, 0x9A, 0x03, 0x20, 0x90, 0x47, 0x55, 0x21, 0x01, 0x70, 0x53, 0x21, 0x41, 0x70, 0x00, 0x21,
|
|
||||||
0x81, 0x70, 0x60, 0x61, 0x00, 0x20
|
|
||||||
};
|
|
||||||
const char *country;
|
|
||||||
char countryRespPatch[sizeof(countryRespPatchModel)];
|
|
||||||
|
|
||||||
patch_memory(code, size,
|
patch_memory(code, size,
|
||||||
blockAutoUpdatesPattern,
|
blockAutoUpdatesPattern,
|
||||||
@@ -178,7 +159,18 @@ u32 patch_code(u64 progid, u8 *code, u32 size){
|
|||||||
blockEShopUpdateCheckPatch,
|
blockEShopUpdateCheckPatch,
|
||||||
sizeof(blockEShopUpdateCheckPatch), 1
|
sizeof(blockEShopUpdateCheckPatch), 1
|
||||||
);
|
);
|
||||||
if(R_SUCCEEDED(patch_secureinfo())){
|
|
||||||
|
if(R_SUCCEEDED(load_secureinfo())){
|
||||||
|
static const char countryRespPattern[] = {
|
||||||
|
0x01, 0x20, 0x01, 0x90, 0x22, 0x46, 0x06, 0x9B
|
||||||
|
};
|
||||||
|
static const char countryRespPatchModel[] = {
|
||||||
|
0x06, 0x9A, 0x03, 0x20, 0x90, 0x47, 0x55, 0x21, 0x01, 0x70, 0x53, 0x21, 0x41, 0x70, 0x00, 0x21,
|
||||||
|
0x81, 0x70, 0x60, 0x61, 0x00, 0x20
|
||||||
|
};
|
||||||
|
const char *country;
|
||||||
|
char countryRespPatch[sizeof(countryRespPatchModel)];
|
||||||
|
|
||||||
switch(secureinfo[0x100]){
|
switch(secureinfo[0x100]){
|
||||||
case 1: country = "US"; break;
|
case 1: country = "US"; break;
|
||||||
case 2: country = "GB"; break; // sorry rest-of-Europe, you have to change this
|
case 2: country = "GB"; break; // sorry rest-of-Europe, you have to change this
|
||||||
@@ -188,7 +180,6 @@ u32 patch_code(u64 progid, u8 *code, u32 size){
|
|||||||
case 6: country = "TW"; break;
|
case 6: country = "TW"; break;
|
||||||
default: case 0: country = "JP"; break;
|
default: case 0: country = "JP"; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// patch XML response Country
|
// patch XML response Country
|
||||||
memcpy(countryRespPatch,
|
memcpy(countryRespPatch,
|
||||||
countryRespPatchModel,
|
countryRespPatchModel,
|
||||||
@@ -203,30 +194,34 @@ u32 patch_code(u64 progid, u8 *code, u32 size){
|
|||||||
sizeof(countryRespPatch), 1
|
sizeof(countryRespPatch), 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if(
|
|
||||||
progid == 0x0004001000021000LL || // USA MSET
|
case 0x0004001000021000LL: // USA MSET
|
||||||
progid == 0x0004001000020000LL || // JPN MSET
|
case 0x0004001000020000LL: // JPN MSET
|
||||||
progid == 0x0004001000022000LL || // EUR MSET
|
case 0x0004001000022000LL: // EUR MSET
|
||||||
progid == 0x0004001000026000LL || // CHN MSET
|
case 0x0004001000026000LL: // CHN MSET
|
||||||
progid == 0x0004001000027000LL || // KOR MSET
|
case 0x0004001000027000LL: // KOR MSET
|
||||||
progid == 0x0004001000028000LL // TWN MSET
|
case 0x0004001000028000LL: // TWN MSET
|
||||||
){
|
{
|
||||||
if(R_SUCCEEDED(open_config()) && ((config >> 5) & 0x1)){
|
if(R_SUCCEEDED(load_config()) && ((config >> 5) & 1)){
|
||||||
static const u16 VerPattern[] = u"Ver.";
|
static const u16 verPattern[] = u"Ver.";
|
||||||
const u32 currentFirm = ((config >> 12) & 0x1);
|
const u32 currentFirm = ((config >> 12) & 1);
|
||||||
const u32 currentNand = ((config >> 13) & 0x3);
|
const u32 currentNand = ((config >> 13) & 3);
|
||||||
|
|
||||||
patch_memory(code, size,
|
patch_memory(code, size,
|
||||||
VerPattern,
|
verPattern,
|
||||||
sizeof(VerPattern) - sizeof(u16), 0,
|
sizeof(verPattern) - sizeof(u16), 0,
|
||||||
currentNand ? ((currentNand == 1) ? ((currentFirm == 1) ? u" Emu" : u"Emu9") : u"Emu2") :
|
currentNand ? ((currentNand == 1) ? ((currentFirm == 1) ? u" Emu" : u"Emu9") : u"Emu2") :
|
||||||
((currentFirm == 1) ? u" Sys" : u"Sys9"),
|
((currentFirm == 1) ? u" Sys" : u"Sys9"),
|
||||||
sizeof(VerPattern) - sizeof(u16), 1
|
sizeof(verPattern) - sizeof(u16), 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (progid == 0x0004013000008002LL){ // NS
|
|
||||||
|
case 0x0004013000008002LL: // NS
|
||||||
|
{
|
||||||
static const u8 stopCartUpdatesPattern[] = {
|
static const u8 stopCartUpdatesPattern[] = {
|
||||||
0x0C, 0x18, 0xE1, 0xD8
|
0x0C, 0x18, 0xE1, 0xD8
|
||||||
};
|
};
|
||||||
@@ -240,16 +235,17 @@ u32 patch_code(u64 progid, u8 *code, u32 size){
|
|||||||
stopCartUpdatesPatch,
|
stopCartUpdatesPatch,
|
||||||
sizeof(stopCartUpdatesPatch), 2
|
sizeof(stopCartUpdatesPatch), 2
|
||||||
);
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if(progid == 0x0004013000001702LL){ // CFG
|
|
||||||
|
case 0x0004013000001702LL: // CFG
|
||||||
|
{
|
||||||
static const u8 secureinfoSigCheckPattern[] = {
|
static const u8 secureinfoSigCheckPattern[] = {
|
||||||
0x06, 0x46, 0x10, 0x48, 0xFC
|
0x06, 0x46, 0x10, 0x48, 0xFC
|
||||||
};
|
};
|
||||||
static const u8 secureinfoSigCheckPatch[] = {
|
static const u8 secureinfoSigCheckPatch[] = {
|
||||||
0x00, 0x26
|
0x00, 0x26
|
||||||
};
|
};
|
||||||
static const u16 secureinfoFilenamePattern[] = u"SecureInfo_";
|
|
||||||
static const u16 secureinfoFilenamePatch[] = u"C";
|
|
||||||
|
|
||||||
// disable SecureInfo signature check
|
// disable SecureInfo signature check
|
||||||
patch_memory(code, size,
|
patch_memory(code, size,
|
||||||
@@ -258,7 +254,11 @@ u32 patch_code(u64 progid, u8 *code, u32 size){
|
|||||||
secureinfoSigCheckPatch,
|
secureinfoSigCheckPatch,
|
||||||
sizeof(secureinfoSigCheckPatch), 1
|
sizeof(secureinfoSigCheckPatch), 1
|
||||||
);
|
);
|
||||||
if(R_SUCCEEDED(patch_secureinfo())){
|
|
||||||
|
if(R_SUCCEEDED(load_secureinfo())){
|
||||||
|
static const u16 secureinfoFilenamePattern[] = u"SecureInfo_";
|
||||||
|
static const u16 secureinfoFilenamePatch[] = u"C";
|
||||||
|
|
||||||
// use SecureInfo_C
|
// use SecureInfo_C
|
||||||
patch_memory(code, size,
|
patch_memory(code, size,
|
||||||
secureinfoFilenamePattern,
|
secureinfoFilenamePattern,
|
||||||
@@ -268,6 +268,8 @@ u32 patch_code(u64 progid, u8 *code, u32 size){
|
|||||||
sizeof(secureinfoFilenamePatch) - sizeof(u16), 2
|
sizeof(secureinfoFilenamePatch) - sizeof(u16), 2
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define HID_PAD (*(vu16 *)0x10146000 ^ 0xFFF)
|
#define HID_PAD (*(vu16 *)0x10146000 ^ 0xFFF)
|
||||||
#define BUTTON_B (1 << 1)
|
|
||||||
#define BUTTON_X (1 << 10)
|
#define BUTTON_X (1 << 10)
|
||||||
#define BUTTON_Y (1 << 11)
|
#define BUTTON_Y (1 << 11)
|
||||||
#define BUTTON_SELECT (1 << 2)
|
#define BUTTON_SELECT (1 << 2)
|
||||||
|
|||||||
@@ -25,8 +25,7 @@ void main(void){
|
|||||||
//Get pressed buttons
|
//Get pressed buttons
|
||||||
u16 pressed = HID_PAD;
|
u16 pressed = HID_PAD;
|
||||||
|
|
||||||
if(((pressed & BUTTON_B) && loadPayload("/aurei/payloads/b.bin")) ||
|
if(((pressed & BUTTON_X) && loadPayload("/aurei/payloads/x.bin")) ||
|
||||||
((pressed & BUTTON_X) && loadPayload("/aurei/payloads/x.bin")) ||
|
|
||||||
((pressed & BUTTON_Y) && loadPayload("/aurei/payloads/y.bin")) ||
|
((pressed & BUTTON_Y) && loadPayload("/aurei/payloads/y.bin")) ||
|
||||||
((pressed & BUTTON_SELECT) && loadPayload("/aurei/payloads/select.bin")) ||
|
((pressed & BUTTON_SELECT) && loadPayload("/aurei/payloads/select.bin")) ||
|
||||||
((pressed & BUTTON_START) && loadPayload("/aurei/payloads/start.bin")) ||
|
((pressed & BUTTON_START) && loadPayload("/aurei/payloads/start.bin")) ||
|
||||||
|
|||||||
@@ -21,6 +21,6 @@
|
|||||||
#define BUTTON_DOWN (1 << 7)
|
#define BUTTON_DOWN (1 << 7)
|
||||||
#define BUTTON_L1R1 ((1 << 8) | (1 << 9))
|
#define BUTTON_L1R1 ((1 << 8) | (1 << 9))
|
||||||
#define SAFE_MODE (BUTTON_L1R1 | BUTTON_A | BUTTON_UP)
|
#define SAFE_MODE (BUTTON_L1R1 | BUTTON_A | BUTTON_UP)
|
||||||
#define OPTION_BUTTONS (BUTTON_L1R1 | BUTTON_A)
|
#define OPTION_BUTTONS (BUTTON_L1R1 | BUTTON_A | BUTTON_SELECT)
|
||||||
#define PAYLOAD_BUTTONS ((BUTTON_L1 | BUTTON_A) ^ 0xFFF)
|
#define PAYLOAD_BUTTONS ((BUTTON_L1 | BUTTON_A | BUTTON_B) ^ 0xFFF)
|
||||||
#define MENU_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_A | BUTTON_START)
|
#define MENU_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_A | BUTTON_START)
|
||||||
@@ -20,7 +20,7 @@ static const struct fb {
|
|||||||
u8 *bottom;
|
u8 *bottom;
|
||||||
} *const fb = (struct fb *)0x23FFFE00;
|
} *const fb = (struct fb *)0x23FFFE00;
|
||||||
|
|
||||||
static int strlen(const char *string){
|
static inline int strlen(const char *string){
|
||||||
char *stringEnd = (char *)string;
|
char *stringEnd = (char *)string;
|
||||||
while(*stringEnd) stringEnd++;
|
while(*stringEnd) stringEnd++;
|
||||||
return stringEnd - string;
|
return stringEnd - string;
|
||||||
|
|||||||
@@ -8,11 +8,11 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "fatfs/sdmmc/sdmmc.h"
|
#include "fatfs/sdmmc/sdmmc.h"
|
||||||
|
|
||||||
void getEmunandSect(u32 *off, u32 *head, u32 emuNAND){
|
void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND){
|
||||||
u8 *const temp = (u8 *)0x24300000;
|
u8 *const temp = (u8 *)0x24300000;
|
||||||
|
|
||||||
u32 nandSize = getMMCDevice(0)->total_size;
|
const u32 nandSize = getMMCDevice(0)->total_size;
|
||||||
u32 nandOffset = emuNAND == 1 ? 0 :
|
u32 nandOffset = *emuNAND == 1 ? 0 :
|
||||||
(nandSize > 0x200000 ? 0x400000 : 0x200000);
|
(nandSize > 0x200000 ? 0x400000 : 0x200000);
|
||||||
|
|
||||||
//Check for RedNAND
|
//Check for RedNAND
|
||||||
@@ -28,7 +28,11 @@ void getEmunandSect(u32 *off, u32 *head, u32 emuNAND){
|
|||||||
*head = nandOffset + nandSize;
|
*head = nandOffset + nandSize;
|
||||||
}
|
}
|
||||||
//Fallback to the first emuNAND if there's no second one
|
//Fallback to the first emuNAND if there's no second one
|
||||||
else if(emuNAND == 2) getEmunandSect(off, head, 1);
|
else if(*emuNAND == 2){
|
||||||
|
*emuNAND = 1;
|
||||||
|
getEmunandSect(off, head, emuNAND);
|
||||||
|
}
|
||||||
|
else *emuNAND = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#define NCSD_MAGIC (0x4453434E)
|
#define NCSD_MAGIC (0x4453434E)
|
||||||
|
|
||||||
void getEmunandSect(u32 *off, u32 *head, u32 emuNAND);
|
void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND);
|
||||||
u32 getSDMMC(u8 *pos, u32 size);
|
u32 getSDMMC(u8 *pos, u32 size);
|
||||||
void getEmuRW(u8 *pos, u32 size, u32 *readOff, u32 *writeOff);
|
void getEmuRW(u8 *pos, u32 size, u32 *readOff, u32 *writeOff);
|
||||||
u32 *getMPU(u8 *pos, u32 size);
|
u32 *getMPU(u8 *pos, u32 size);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#include "../build/patches.h"
|
#include "../build/patches.h"
|
||||||
|
|
||||||
//FIRM patches version
|
//FIRM patches version
|
||||||
#define PATCH_VER 2
|
#define PATCH_VER 3
|
||||||
|
|
||||||
static firmHeader *const firm = (firmHeader *)0x24000000;
|
static firmHeader *const firm = (firmHeader *)0x24000000;
|
||||||
static const firmSectionHeader *section;
|
static const firmSectionHeader *section;
|
||||||
@@ -27,13 +27,16 @@ static const char *patchedFirms[] = { "/aurei/patched_firmware_sys.bin",
|
|||||||
"/aurei/patched_firmware_emu.bin",
|
"/aurei/patched_firmware_emu.bin",
|
||||||
"/aurei/patched_firmware_em2.bin",
|
"/aurei/patched_firmware_em2.bin",
|
||||||
"/aurei/patched_firmware90.bin" };
|
"/aurei/patched_firmware90.bin" };
|
||||||
|
|
||||||
static u32 firmSize,
|
static u32 firmSize,
|
||||||
console,
|
console,
|
||||||
mode,
|
mode,
|
||||||
emuNAND,
|
emuNAND,
|
||||||
a9lhSetup,
|
a9lhSetup,
|
||||||
selectedFirm,
|
selectedFirm,
|
||||||
usePatchedFirm;
|
usePatchedFirm,
|
||||||
|
emuOffset,
|
||||||
|
emuHeader;
|
||||||
|
|
||||||
void setupCFW(void){
|
void setupCFW(void){
|
||||||
|
|
||||||
@@ -48,36 +51,41 @@ void setupCFW(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";
|
||||||
u32 config = 0;
|
u32 config = 0,
|
||||||
u32 needConfig = fileRead(&config, configPath, 3) ? 1 : 2;
|
needConfig = fileRead(&config, configPath, 3) ? 1 : 2;
|
||||||
|
|
||||||
//Determine if A9LH is installed and the user has an updated sysNAND
|
//Determine if A9LH is installed and the user has an updated sysNAND
|
||||||
u32 updatedSys;
|
u32 updatedSys;
|
||||||
|
|
||||||
if(a9lhBoot || (config >> 2) & 0x1){
|
if(a9lhBoot || (config >> 2) & 1){
|
||||||
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!");
|
||||||
|
|
||||||
a9lhSetup = 1;
|
a9lhSetup = 1;
|
||||||
//Check setting for > 9.2 sysNAND
|
//Check setting for > 9.2 sysNAND
|
||||||
updatedSys = config & 0x1;
|
updatedSys = config & 1;
|
||||||
} else{
|
} else{
|
||||||
a9lhSetup = 0;
|
a9lhSetup = 0;
|
||||||
updatedSys = 0;
|
updatedSys = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 tempConfig = (PATCH_VER << 17) | (a9lhSetup << 16);
|
||||||
|
|
||||||
/* 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 */
|
||||||
if(a9lhBoot && previousFirm && needConfig == 1){
|
if(a9lhBoot && previousFirm && needConfig == 1){
|
||||||
//Always force a sysNAND boot when quitting AGB_FIRM
|
//Always force a sysNAND boot when quitting AGB_FIRM
|
||||||
if(previousFirm == 0x7){
|
if(previousFirm == 7){
|
||||||
mode = updatedSys ? 1 : (config >> 12) & 0x1;
|
mode = updatedSys ? 1 : (config >> 12) & 1;
|
||||||
emuNAND = 0;
|
emuNAND = 0;
|
||||||
|
//Flag to prevent multiple boot options-forcing
|
||||||
|
tempConfig |= 1 << 15;
|
||||||
needConfig = 0;
|
needConfig = 0;
|
||||||
//Else, force the last used boot options unless A, L or R are pressed
|
/* Else, force the last used boot options unless A, L or R are pressed
|
||||||
} else if(!(pressed & OPTION_BUTTONS)){
|
or the no-forcing flag is set */
|
||||||
mode = (config >> 12) & 0x1;
|
} else if(!(pressed & OPTION_BUTTONS) && !((config >> 15) & 1)){
|
||||||
emuNAND = (config >> 13) & 0x3;
|
mode = (config >> 12) & 1;
|
||||||
|
emuNAND = (config >> 13) & 3;
|
||||||
needConfig = 0;
|
needConfig = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,10 +102,10 @@ void setupCFW(void){
|
|||||||
configureCFW(configPath, patchedFirms[3]);
|
configureCFW(configPath, patchedFirms[3]);
|
||||||
|
|
||||||
//If screens are inited, load splash screen
|
//If screens are inited, load splash screen
|
||||||
if(PDN_GPU_CNT != 0x1) loadSplash();
|
if(PDN_GPU_CNT != 1) loadSplash();
|
||||||
|
|
||||||
/* If L is pressed, boot 9.0 FIRM */
|
/* If L is pressed, boot 9.0 FIRM */
|
||||||
mode = ((config >> 3) & 0x1) ? ((!(pressed & BUTTON_L1R1)) ? 0 : 1) :
|
mode = ((config >> 3) & 1) ? ((!(pressed & BUTTON_L1R1)) ? 0 : 1) :
|
||||||
((pressed & BUTTON_L1) ? 0 : 1);
|
((pressed & BUTTON_L1) ? 0 : 1);
|
||||||
|
|
||||||
/* If L or R aren't pressed on a 9.0/9.2 sysNAND, or the 9.0 FIRM is selected
|
/* If L or R aren't pressed on a 9.0/9.2 sysNAND, or the 9.0 FIRM is selected
|
||||||
@@ -105,31 +113,46 @@ void setupCFW(void){
|
|||||||
if((updatedSys && (!mode || (pressed & BUTTON_R1))) ||
|
if((updatedSys && (!mode || (pressed & BUTTON_R1))) ||
|
||||||
(!updatedSys && mode && !(pressed & BUTTON_R1))){
|
(!updatedSys && mode && !(pressed & BUTTON_R1))){
|
||||||
//If not 9.0 FIRM and B is pressed, attempt booting the second emuNAND
|
//If not 9.0 FIRM and B is pressed, attempt booting the second emuNAND
|
||||||
emuNAND = (mode && ((!(pressed & BUTTON_B)) == ((config >> 4) & 0x1))) ? 2 : 1;
|
emuNAND = (mode && ((!(pressed & BUTTON_B)) == ((config >> 4) & 1))) ? 2 : 1;
|
||||||
} else emuNAND = 0;
|
} else emuNAND = 0;
|
||||||
|
|
||||||
u32 tempConfig = (PATCH_VER << 17) | (a9lhSetup << 16) | (emuNAND << 13) | (mode << 12);
|
|
||||||
|
|
||||||
/* If tha FIRM patches version is different or user switched to/from A9LH,
|
/* If tha FIRM patches version is different or user switched to/from A9LH,
|
||||||
delete all patched FIRMs */
|
delete all patched FIRMs */
|
||||||
if((tempConfig & 0xFF0000) != (config & 0xFF0000))
|
if((tempConfig & 0xFF0000) != (config & 0xFF0000))
|
||||||
deleteFirms(patchedFirms, sizeof(patchedFirms) / sizeof(char *));
|
deleteFirms(patchedFirms, sizeof(patchedFirms) / sizeof(char *));
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 usePatchedFirmSet = ((config >> 1) & 1);
|
||||||
|
|
||||||
|
while(1){
|
||||||
|
/* Determine which patched FIRM we need to write or attempt to use (if any).
|
||||||
|
Patched 9.0 FIRM is only needed if "Use pre-patched FIRMs" is set */
|
||||||
|
selectedFirm = mode ? (emuNAND ? (emuNAND == 1 ? 2 : 3) : 1) :
|
||||||
|
(usePatchedFirmSet ? 4 : 0);
|
||||||
|
|
||||||
|
//If "Use pre-patched FIRMs" is set and the appropriate FIRM exists, use it
|
||||||
|
if(usePatchedFirmSet && fileExists(patchedFirms[selectedFirm - 1]))
|
||||||
|
usePatchedFirm = 1;
|
||||||
|
//Detect EmuNAND
|
||||||
|
else if(emuNAND){
|
||||||
|
getEmunandSect(&emuOffset, &emuHeader, &emuNAND);
|
||||||
|
//If none exists, force SysNAND + 9.6/10.x FIRM and re-detect patched FIRMs
|
||||||
|
if(!emuNAND){
|
||||||
|
mode = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tempConfig |= (emuNAND << 13) | (mode << 12);
|
||||||
|
|
||||||
//If the boot configuration is different from previously, overwrite it
|
//If the boot configuration is different from previously, overwrite it
|
||||||
if((tempConfig & 0xFFF000) != (config & 0xFFF000)){
|
if(tempConfig != (config & 0xFFF000)){
|
||||||
//Preserve user settings (first 12 bits)
|
//Preserve user settings (first 12 bits)
|
||||||
tempConfig |= config & 0xFFF;
|
tempConfig |= config & 0xFFF;
|
||||||
fileWrite(&tempConfig, configPath, 3);
|
fileWrite(&tempConfig, configPath, 3);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Determine which patched FIRM we need to write or attempt to use (if any).
|
|
||||||
Patched 9.0 FIRM is only needed if "Use pre-patched FIRMs" is set */
|
|
||||||
selectedFirm = mode ? (emuNAND ? (emuNAND == 1 ? 2 : 3) : 1) :
|
|
||||||
(((config >> 1) & 0x1) ? 4 : 0);
|
|
||||||
|
|
||||||
//If "Use pre-patched FIRMs" is set and the appropriate FIRM exists, use it
|
|
||||||
usePatchedFirm = (((config >> 1) & 0x1) && fileExists(patchedFirms[selectedFirm - 1])) ? 1 : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Load FIRM into FCRAM
|
//Load FIRM into FCRAM
|
||||||
@@ -165,18 +188,7 @@ void loadFirm(void){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//NAND redirection
|
//NAND redirection
|
||||||
static void loadEmu(u8 *proc9Offset){
|
static inline void loadEmu(u8 *proc9Offset){
|
||||||
|
|
||||||
u32 emuOffset,
|
|
||||||
emuHeader = 0,
|
|
||||||
emuRead,
|
|
||||||
emuWrite;
|
|
||||||
|
|
||||||
//Look for emuNAND
|
|
||||||
getEmunandSect(&emuOffset, &emuHeader, emuNAND);
|
|
||||||
|
|
||||||
//No emuNAND detected
|
|
||||||
if(!emuHeader) error("No emuNAND has been detected");
|
|
||||||
|
|
||||||
//Copy emuNAND code
|
//Copy emuNAND code
|
||||||
void *emuCodeOffset = getEmuCode(proc9Offset);
|
void *emuCodeOffset = getEmuCode(proc9Offset);
|
||||||
@@ -197,6 +209,9 @@ static void loadEmu(u8 *proc9Offset){
|
|||||||
section[2].offset + (u32)section[2].address;
|
section[2].offset + (u32)section[2].address;
|
||||||
|
|
||||||
//Add emunand hooks
|
//Add emunand hooks
|
||||||
|
u32 emuRead,
|
||||||
|
emuWrite;
|
||||||
|
|
||||||
getEmuRW(arm9Section, section[2].size, &emuRead, &emuWrite);
|
getEmuRW(arm9Section, section[2].size, &emuRead, &emuWrite);
|
||||||
*(u16 *)emuRead = nandRedir[0];
|
*(u16 *)emuRead = nandRedir[0];
|
||||||
*((u16 *)emuRead + 1) = nandRedir[1];
|
*((u16 *)emuRead + 1) = nandRedir[1];
|
||||||
@@ -268,9 +283,11 @@ void patchFirm(void){
|
|||||||
loaderSize;
|
loaderSize;
|
||||||
|
|
||||||
getLoader((u8 *)firm + section[0].offset, section[0].size, &loaderOffset, &loaderSize);
|
getLoader((u8 *)firm + section[0].offset, section[0].size, &loaderOffset, &loaderSize);
|
||||||
|
//Check that the injector CXI isn't larger than the original
|
||||||
if(injector_size <= (int)loaderSize){
|
if(injector_size <= (int)loaderSize){
|
||||||
memset((void *)loaderOffset, 0, loaderSize);
|
memset((void *)loaderOffset, 0, loaderSize);
|
||||||
memcpy((void *)loaderOffset, injector, injector_size);
|
memcpy((void *)loaderOffset, injector, injector_size);
|
||||||
|
//Patch content size and ExeFS size to match the repaced loader's ones
|
||||||
*((u32 *)loaderOffset + 0x41) = loaderSize / 0x200;
|
*((u32 *)loaderOffset + 0x41) = loaderSize / 0x200;
|
||||||
*((u32 *)loaderOffset + 0x69) = loaderSize / 0x200 - 5;
|
*((u32 *)loaderOffset + 0x69) = loaderSize / 0x200 - 5;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ void deinitScreens(void){
|
|||||||
((void (*)())*arm11)();
|
((void (*)())*arm11)();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(PDN_GPU_CNT != 0x1){
|
if(PDN_GPU_CNT != 1){
|
||||||
*arm11 = (u32)ARM11;
|
*arm11 = (u32)ARM11;
|
||||||
while(*arm11);
|
while(*arm11);
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ void initScreens(void){
|
|||||||
*(vu32 *)0x1040049C = 0x00000000;
|
*(vu32 *)0x1040049C = 0x00000000;
|
||||||
|
|
||||||
// Disco register
|
// Disco register
|
||||||
for(vu32 i = 0; i < 256; i++)
|
for(u32 i = 0; i < 256; i++)
|
||||||
*(vu32 *)0x10400484 = 0x10101 * i;
|
*(vu32 *)0x10400484 = 0x10101 * i;
|
||||||
|
|
||||||
// Bottom screen
|
// Bottom screen
|
||||||
@@ -116,7 +116,7 @@ void initScreens(void){
|
|||||||
*(vu32 *)0x1040059C = 0x00000000;
|
*(vu32 *)0x1040059C = 0x00000000;
|
||||||
|
|
||||||
// Disco register
|
// Disco register
|
||||||
for(vu32 i = 0; i < 256; i++)
|
for(u32 i = 0; i < 256; i++)
|
||||||
*(vu32 *)0x10400584 = 0x10101 * i;
|
*(vu32 *)0x10400584 = 0x10101 * i;
|
||||||
|
|
||||||
// Enable backlight
|
// Enable backlight
|
||||||
@@ -143,7 +143,7 @@ void initScreens(void){
|
|||||||
((void (*)())*arm11)();
|
((void (*)())*arm11)();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(PDN_GPU_CNT == 0x1){
|
if(PDN_GPU_CNT == 1){
|
||||||
*arm11 = (u32)ARM11;
|
*arm11 = (u32)ARM11;
|
||||||
while(*arm11);
|
while(*arm11);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ void configureCFW(const char *configPath, const char *firm90Path){
|
|||||||
u32 tempConfig = 0;
|
u32 tempConfig = 0;
|
||||||
fileRead(&tempConfig, configPath, 3);
|
fileRead(&tempConfig, configPath, 3);
|
||||||
for(u32 i = 0; i < optionsAmount; i++)
|
for(u32 i = 0; i < optionsAmount; i++)
|
||||||
options[i].enabled = (tempConfig >> i) & 0x1;
|
options[i].enabled = (tempConfig >> i) & 1;
|
||||||
|
|
||||||
//Pre-select the first configuration option
|
//Pre-select the first configuration option
|
||||||
u32 selectedOption = 0;
|
u32 selectedOption = 0;
|
||||||
@@ -102,8 +102,7 @@ void configureCFW(const char *configPath, const char *firm90Path){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//If the user has been using A9LH and the "Updated SysNAND" setting changed, delete the patched 9.0 FIRM
|
//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))
|
if(((tempConfig >> 16) & 1) && ((tempConfig & 1) != options[0].enabled)) fileDelete(firm90Path);
|
||||||
fileDelete(firm90Path);
|
|
||||||
|
|
||||||
//Preserve the last-used boot options (last 12 bits)
|
//Preserve the last-used boot options (last 12 bits)
|
||||||
tempConfig &= 0xFFF000;
|
tempConfig &= 0xFFF000;
|
||||||
|
|||||||
Reference in New Issue
Block a user