diff --git a/arm9/source/firm.c b/arm9/source/firm.c index 2829a8b..a2281c8 100755 --- a/arm9/source/firm.c +++ b/arm9/source/firm.c @@ -269,6 +269,8 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo u32 srcModuleSize, nbModules = 0; + bool isLgyFirm = firmType == TWL_FIRM || firmType == AGB_FIRM; + struct { char name[8]; @@ -311,7 +313,7 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo u8 *dst = firm->section[0].address; const char *extModuleSizeError = "The external FIRM modules are too large."; // SAFE_FIRM only for N3DS and only if ENABLESAFEFIRMROSALINA is on - u32 maxModuleSize = (firmType == NATIVE_FIRM || firmType == SAFE_FIRM) ? 0x80000 : 0x600000; + u32 maxModuleSize = !isLgyFirm ? 0x80000 : 0x600000; for(u32 i = 0, dstModuleSize; i < nbModules; i++, dst += dstModuleSize, maxModuleSize -= dstModuleSize) { if(loadFromStorage) @@ -344,11 +346,20 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo memcpy(dst, moduleList[i].src, dstModuleSize); } - //4) Patch NATIVE_FIRM/SAFE_FIRM (N3DS) if necessary - if(nbModules == 6) + //4) Patch kernel to take module size into account + u32 newKipSectionSize = dst - firm->section[0].address; + u32 oldKipSectionSize = firm->section[0].size; + u8 *kernel11Addr = (u8 *)firm + firm->section[1].offset; + u32 kernel11Size = firm->section[1].size; + if (isLgyFirm) { - if(patchK11ModuleLoading(firm->section[0].size, dst - firm->section[0].address, (u8 *)firm + firm->section[1].offset, firm->section[1].size) != 0) - error("Failed to inject custom sysmodule"); + if (patchK11ModuleLoadingLgy(newKipSectionSize, kernel11Addr, kernel11Size) != 0) + error("Failed to load sysmodules"); + } + else + { + if (patchK11ModuleLoading(oldKipSectionSize, newKipSectionSize, nbModules, kernel11Addr, kernel11Size) != 0) + error("Failed to load sysmodules"); } } diff --git a/arm9/source/patches.c b/arm9/source/patches.c index e01a631..5a179ff 100644 --- a/arm9/source/patches.c +++ b/arm9/source/patches.c @@ -463,7 +463,7 @@ u32 patchCheckForDevCommonKey(u8 *pos, u32 size) return 0; } -u32 patchK11ModuleLoading(u32 section0size, u32 modulesSize, u8 *pos, u32 size) +u32 patchK11ModuleLoading(u32 oldKipSectionSize, u32 newKipSectionSize, u32 numKips, u8 *pos, u32 size) { static const u8 moduleLoadingPattern[] = {0xE2, 0x05, 0x00, 0x57}, modulePidPattern[] = {0x06, 0xA0, 0xE1, 0xF2}; //GetSystemInfo @@ -472,20 +472,44 @@ u32 patchK11ModuleLoading(u32 section0size, u32 modulesSize, u8 *pos, u32 size) if(off == NULL) return 1; - off[1]++; + off[1] = (u8)numKips; u32 *off32; for(off32 = (u32 *)(off - 3); *off32 != 0xE59F0000; off32++); off32 += 2; - off32[1] = off32[0] + modulesSize; - for(; *off32 != section0size; off32++); - *off32 = ((modulesSize + 0x1FF) >> 9) << 9; + off32[1] = off32[0] + newKipSectionSize; + for(; *off32 != oldKipSectionSize; off32++); + *off32 = ((newKipSectionSize + 0x1FF) >> 9) << 9; off = memsearch(pos, modulePidPattern, size, 4); if(off == NULL) return 1; - off[0xB] = 6; + off[0xB] = (u8)numKips; + + return 0; +} + +u32 patchK11ModuleLoadingLgy(u32 newKipSectionSize, u8 *pos, u32 size) +{ + // Patch the function where TwlBg/AgbBg is copied from 18000000 (VRAM) to 21000000 (FCRAM). + // This is where we can also automatically obtain the section size + + u16 *off = (u16 *)pos; + for (; (u8 *)off < pos + size && (off[0] != 0x06C9 || off[1] != 0x0600); off++); + if ((u8 *)off >= pos + size) + return 3; + + off += 7; + u32 oldKipSectionSize = *(u32 *)off; + *(u32 *)off = newKipSectionSize; + off += 2; + + u32 *off2 = (u32 *)off; + for (; (u8 *)off2 < pos + size && *off2 != oldKipSectionSize; off2++); + if ((u8 *)off2 >= pos + size) + return 4; + *off2 = newKipSectionSize; return 0; } diff --git a/arm9/source/patches.h b/arm9/source/patches.h index dae3598..a612165 100644 --- a/arm9/source/patches.h +++ b/arm9/source/patches.h @@ -50,7 +50,8 @@ u32 patchTitleInstallMinVersionChecks(u8 *pos, u32 size, u32 firmVersion); u32 patchZeroKeyNcchEncryptionCheck(u8 *pos, u32 size); u32 patchNandNcchEncryptionCheck(u8 *pos, u32 size); u32 patchCheckForDevCommonKey(u8 *pos, u32 size); -u32 patchK11ModuleLoading(u32 section0size, u32 modulesSize, u8 *startPos, u32 size); +u32 patchK11ModuleLoading(u32 oldKipSectionSize, u32 newKipSectionSize, u32 numKips, u8 *pos, u32 size); +u32 patchK11ModuleLoadingLgy(u32 newKipSectionSize, u8 *pos, u32 size); u32 patchArm9ExceptionHandlersInstall(u8 *pos, u32 size); u32 patchSvcBreak9(u8 *pos, u32 size, u32 kernel9Address); u32 patchKernel9Panic(u8 *pos, u32 size);