Added region/language emulation feature, thanks to the hard work of @TuxSH
Create a "locales" folder inside aurei, and one .txt for each game, with the title id of the game. The txt must be exactly 6 bytes long: 3 characters for the region ("JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"), a space, and two for the language ("JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"). You can enable the feature globally in the config menu. This should also make DLCs for foreign games work.
This commit is contained in:
parent
85533411c9
commit
308417a48e
35
Makefile
35
Makefile
@ -26,11 +26,12 @@ dir_out := out
|
||||
|
||||
ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te
|
||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main -O2 -flto -ffast-math
|
||||
LDFLAGS := -nostartfiles
|
||||
FLAGS := name=$(name).dat dir_out=$(abspath $(dir_out)) ICON=$(abspath icon.png) APP_DESCRIPTION="Noob-friendly 3DS CFW." APP_AUTHOR="Reisyukaku/Aurora Wright" --no-print-directory
|
||||
|
||||
objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||
|
||||
|
||||
.PHONY: all
|
||||
@ -55,10 +56,10 @@ pathchanger: $(dir_out)/pathchanger
|
||||
clean:
|
||||
@$(MAKE) $(FLAGS) -C $(dir_mset) clean
|
||||
@$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean
|
||||
@rm -rf $(dir_out) $(dir_build)
|
||||
@$(MAKE) -C $(dir_loader) clean
|
||||
@$(MAKE) -C $(dir_screeninit) clean
|
||||
@$(MAKE) -C $(dir_injector) clean
|
||||
@rm -rf $(dir_out) $(dir_build)
|
||||
|
||||
$(dir_out):
|
||||
@mkdir -p "$(dir_out)/aurei/payloads"
|
||||
@ -74,38 +75,36 @@ $(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin $(dir_out)
|
||||
@cp -a $(dir_build)/main.bin $@
|
||||
|
||||
$(dir_out)/3ds/$(name): $(dir_out)
|
||||
@mkdir -p "$(dir_out)/3ds/$(name)"
|
||||
@mkdir -p "$@"
|
||||
@$(MAKE) $(FLAGS) -C $(dir_ninjhax)
|
||||
@mv $(dir_out)/$(name).3dsx $@
|
||||
@mv $(dir_out)/$(name).smdh $@
|
||||
@mv $(dir_out)/$(name).3dsx $(dir_out)/$(name).smdh $@
|
||||
|
||||
$(dir_out)/$(name).zip: launcher a9lh ninjhax
|
||||
@cd $(dir_out) && zip -9 -r $(name) *
|
||||
@cd "$(@D)" && zip -9 -r $(name) *
|
||||
|
||||
$(dir_build)/patches.h: $(dir_patches)/emunand.s $(dir_patches)/reboot.s $(dir_injector)/Makefile
|
||||
@mkdir -p "$(dir_build)"
|
||||
@mkdir -p "$(@D)"
|
||||
@armips $<
|
||||
@armips $(word 2,$^)
|
||||
@$(MAKE) -C $(dir_injector)
|
||||
@mv emunand.bin reboot.bin $(dir_injector)/injector.cxi $(dir_build)
|
||||
@bin2c -o $@ -n emunand $(dir_build)/emunand.bin -n reboot $(dir_build)/reboot.bin -n injector $(dir_build)/injector.cxi
|
||||
@mv emunand.bin reboot.bin $(dir_injector)/injector.cxi $(@D)
|
||||
@bin2c -o $@ -n emunand $(@D)/emunand.bin -n reboot $(@D)/reboot.bin -n injector $(@D)/injector.cxi
|
||||
|
||||
$(dir_build)/loader.h: $(dir_loader)/Makefile
|
||||
@$(MAKE) -C $(dir_loader)
|
||||
@mv $(dir_loader)/loader.bin $(dir_build)
|
||||
@bin2c -o $@ -n loader $(dir_build)/loader.bin
|
||||
@mv $(dir_loader)/loader.bin $(@D)
|
||||
@bin2c -o $@ -n loader $(@D)/loader.bin
|
||||
|
||||
$(dir_build)/screeninit.h: $(dir_screeninit)/Makefile
|
||||
@$(MAKE) -C $(dir_screeninit)
|
||||
@mv $(dir_screeninit)/screeninit.bin $(dir_build)
|
||||
@bin2c -o $@ -n screeninit $(dir_build)/screeninit.bin
|
||||
@mv $(dir_screeninit)/screeninit.bin $(@D)
|
||||
@bin2c -o $@ -n screeninit $(@D)/screeninit.bin
|
||||
|
||||
$(dir_build)/main.bin: $(dir_build)/main.elf
|
||||
$(OC) -S -O binary $< $@
|
||||
|
||||
$(dir_build)/main.elf: $(objects_cfw)
|
||||
# FatFs requires libgcc for __aeabi_uidiv
|
||||
$(CC) -nostartfiles $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
$(dir_build)/main.elf: $(objects)
|
||||
$(CC) $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
|
||||
$(dir_build)/memory.o : CFLAGS += -O3
|
||||
$(dir_build)/config.o : CFLAGS += -DCONFIG_TITLE="\"$(name) $(version) configuration\""
|
||||
|
@ -11,7 +11,7 @@
|
||||
#endif
|
||||
|
||||
static u32 config = 0;
|
||||
static u8 secureinfo[0x111] = {0};
|
||||
static u8 secureInfo[0x111] = {0};
|
||||
|
||||
//Quick Search algorithm, adapted from http://igm.univ-mlv.fr/~lecroq/string/node19.html#SECTION00190
|
||||
static u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize)
|
||||
@ -79,40 +79,38 @@ static int fileOpen(IFile *file, FS_ArchiveID id, const char *path, int flags)
|
||||
return IFile_Open(file, archive, ppath, flags);
|
||||
}
|
||||
|
||||
static int loadSecureinfo()
|
||||
static int loadSecureInfo(void)
|
||||
{
|
||||
IFile file;
|
||||
Result ret;
|
||||
u64 total;
|
||||
|
||||
if(secureinfo[0] == 0xFF)
|
||||
if(secureInfo[0] == 0xFF)
|
||||
return 0;
|
||||
|
||||
ret = fileOpen(&file, ARCHIVE_NAND_RW, "/sys/SecureInfo_C", FS_OPEN_READ);
|
||||
IFile file;
|
||||
Result ret = fileOpen(&file, ARCHIVE_NAND_RW, "/sys/SecureInfo_C", FS_OPEN_READ);
|
||||
if(R_SUCCEEDED(ret))
|
||||
{
|
||||
ret = IFile_Read(&file, &total, secureinfo, sizeof(secureinfo));
|
||||
u64 total;
|
||||
|
||||
ret = IFile_Read(&file, &total, secureInfo, 0x111);
|
||||
IFile_Close(&file);
|
||||
if(R_SUCCEEDED(ret) && total == sizeof(secureinfo))
|
||||
secureinfo[0] = 0xFF;
|
||||
if(R_SUCCEEDED(ret) && total == 0x111)
|
||||
secureInfo[0] = 0xFF;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int loadConfig()
|
||||
static int loadConfig(void)
|
||||
{
|
||||
IFile file;
|
||||
Result ret;
|
||||
u64 total;
|
||||
|
||||
if(config)
|
||||
return 0;
|
||||
|
||||
ret = fileOpen(&file, ARCHIVE_SDMC, "/aurei/config.bin", FS_OPEN_READ);
|
||||
IFile file;
|
||||
Result ret = fileOpen(&file, ARCHIVE_SDMC, "/aurei/config.bin", FS_OPEN_READ);
|
||||
if(R_SUCCEEDED(ret))
|
||||
{
|
||||
ret = IFile_Read(&file, &total, &config, 3);
|
||||
u64 total;
|
||||
|
||||
ret = IFile_Read(&file, &total, &config, 4);
|
||||
IFile_Close(&file);
|
||||
if(R_SUCCEEDED(ret)) config |= 1 << 4;
|
||||
}
|
||||
@ -120,6 +118,147 @@ static int loadConfig()
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageId)
|
||||
{
|
||||
/* Here we look for "/aurei/locales/[u64 titleID in hex, uppercase].txt"
|
||||
If it exists it should contain, for example, "EUR IT" */
|
||||
|
||||
char path[] = "/aurei/locales/0000000000000000.txt";
|
||||
|
||||
u32 i = 30;
|
||||
|
||||
while(progId > 0)
|
||||
{
|
||||
static const char hexDigits[] = "0123456789ABCDEF";
|
||||
path[i--] = hexDigits[(u32)(progId & 0xF)];
|
||||
progId >>= 4;
|
||||
}
|
||||
|
||||
IFile file;
|
||||
Result ret = fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ);
|
||||
if(R_SUCCEEDED(ret))
|
||||
{
|
||||
char buf[6];
|
||||
u64 total;
|
||||
|
||||
ret = IFile_Read(&file, &total, buf, 6);
|
||||
IFile_Close(&file);
|
||||
|
||||
if(!R_SUCCEEDED(ret) || total < 6) return -1;
|
||||
|
||||
static const char *regions[] = {"JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"};
|
||||
static const char *languages[] = {"JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"};
|
||||
|
||||
for(u32 i = 0; i < 7; ++i)
|
||||
if(memcmp(buf, regions[i], 3) == 0)
|
||||
{
|
||||
*regionId = (u8)i;
|
||||
break;
|
||||
}
|
||||
|
||||
for(u32 i = 0; i < 12; ++i)
|
||||
if(memcmp(buf + 4, languages[i], 2) == 0)
|
||||
{
|
||||
*languageId = (u8)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u8 *getCfgOffsets(u8* code, u32 size, u32 *CFGUHandleOffset)
|
||||
{
|
||||
static const u8 CFGU_GetConfigInfoBlk2_endPattern[] = {
|
||||
0x10, 0x80, 0xBD, 0xE8, 0x82, 0x00, 0x01, 0x00
|
||||
};
|
||||
|
||||
u8 *CFGU_GetConfigInfoBlk2_endPos = code;
|
||||
|
||||
while((CFGU_GetConfigInfoBlk2_endPos + sizeof(CFGU_GetConfigInfoBlk2_endPattern)) < (code + size)
|
||||
&& (*CFGUHandleOffset > 0x10000000UL || ((u32)CFGU_GetConfigInfoBlk2_endPos % 4) != 0))
|
||||
{
|
||||
//There might be multiple implementations of GetConfigInfoBlk2 but let's search for the one we want
|
||||
CFGU_GetConfigInfoBlk2_endPos += sizeof(CFGU_GetConfigInfoBlk2_endPattern);
|
||||
CFGU_GetConfigInfoBlk2_endPos = memsearch(CFGU_GetConfigInfoBlk2_endPos, CFGU_GetConfigInfoBlk2_endPattern,
|
||||
size - (u32)(CFGU_GetConfigInfoBlk2_endPos - code), sizeof(CFGU_GetConfigInfoBlk2_endPattern));
|
||||
|
||||
if(CFGU_GetConfigInfoBlk2_endPos == NULL) break;
|
||||
|
||||
*CFGUHandleOffset = *(u32 *)(CFGU_GetConfigInfoBlk2_endPos + 8);
|
||||
}
|
||||
|
||||
return CFGU_GetConfigInfoBlk2_endPos;
|
||||
}
|
||||
|
||||
static void patchCfgGetLanguage(u8* code, u32 size, u8 languageId, u8 *CFGU_GetConfigInfoBlk2_endPos)
|
||||
{
|
||||
u8 *CFGU_GetConfigInfoBlk2_startPos = CFGU_GetConfigInfoBlk2_endPos; //Let's find STMFD SP (there might be a NOP before, but nevermind)
|
||||
while(*(u16 *)CFGU_GetConfigInfoBlk2_startPos != 0xE92D) CFGU_GetConfigInfoBlk2_startPos -= 2;
|
||||
CFGU_GetConfigInfoBlk2_startPos -= 2;
|
||||
|
||||
u8 *languageBlkIdPos = code;
|
||||
u32 patched = 0;
|
||||
|
||||
while((languageBlkIdPos + 4) < (code + size) && !patched)
|
||||
{
|
||||
static const u32 languageBlkId = 0xA0002;
|
||||
|
||||
languageBlkIdPos += 4;
|
||||
languageBlkIdPos = memsearch(languageBlkIdPos, &languageBlkId, size - (u32)(languageBlkIdPos - code), 4);
|
||||
|
||||
if(languageBlkIdPos == NULL) break;
|
||||
if(((u32)languageBlkIdPos % 4) != 0) continue;
|
||||
|
||||
for(u8 *instr = languageBlkIdPos - 8; instr >= languageBlkIdPos - 0x1008; instr -= 4) //Should be enough
|
||||
{
|
||||
if(*(instr + 3) != 0xEB) continue; //We're looking for BL
|
||||
u32 low24 = (*(u32 *)instr & 0x00FFFFFF) << 2;
|
||||
s32 offset = (((low24 >> 25) != 0) ? -low24 : low24) + 8; //Branch offset + 8 for prefetch
|
||||
|
||||
if((instr + offset) >= (CFGU_GetConfigInfoBlk2_startPos - 4) && (instr + offset) <= CFGU_GetConfigInfoBlk2_endPos)
|
||||
{
|
||||
*(u32 *)(instr - 4) = 0xE3A00000 | languageId; // mov r0, sp => mov r0, =languageID
|
||||
*(u32 *)instr = 0xE5CD0000; // bl CFGU_GetConfigInfoBlk2 => strb r0, [sp]
|
||||
*(u32 *)(instr + 4) = 0xE3A00000; // mov r1, pc => mov r0, 0 (result code)
|
||||
|
||||
//We're done
|
||||
patched = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void patchCfgGetRegion(u8* code, u32 size, u8 regionID, u32 *CFGUHandleOffset)
|
||||
{
|
||||
static const u8 cfgSecureInfoGetRegionCmdPattern[] = {
|
||||
0x70, 0x4F, 0x1D, 0xEE, 0x02, 0x08, 0xA0, 0xE3, 0x80, 0x00, 0xA4, 0xE5
|
||||
};
|
||||
|
||||
u8 *cmdPos = code;
|
||||
|
||||
while((cmdPos + sizeof(cfgSecureInfoGetRegionCmdPattern)) < (code + size))
|
||||
{
|
||||
cmdPos += sizeof(cfgSecureInfoGetRegionCmdPattern);
|
||||
cmdPos = memsearch(cmdPos, cfgSecureInfoGetRegionCmdPattern, size - (u32)(cmdPos - code), sizeof(cfgSecureInfoGetRegionCmdPattern));
|
||||
|
||||
if(cmdPos == NULL) break;
|
||||
if(*(u16 *)(cmdPos + 12 + 2) != 0xE59F) continue; // ldr r0, [pc, X]
|
||||
|
||||
if(*(u32 *)(cmdPos + 12 + 8 + *(u16 *)(cmdPos + 12)) == *CFGUHandleOffset)
|
||||
{
|
||||
*(u32 *)(cmdPos + 16) = 0xE3A00000 | regionID; // mov r0, =regionID
|
||||
*(u32 *)(cmdPos + 20) = 0xE5C40008; // strb r0, [r4, 8]
|
||||
*(u32 *)(cmdPos + 24) = 0xE3A00000; // mov r0, 0 (result code)
|
||||
*(u32 *)(cmdPos + 28) = 0xE5840004; // str r0, [r4, 4]
|
||||
|
||||
//The remaining, not patched, function code will do the rest for us
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void patchCode(u64 progId, u8 *code, u32 size)
|
||||
{
|
||||
switch(progId)
|
||||
@ -257,7 +396,7 @@ void patchCode(u64 progId, u8 *code, u32 size)
|
||||
if(cfgN3dsCpuLoc != NULL)
|
||||
{
|
||||
*(u32 *)(cfgN3dsCpuLoc + 3) = 0xE1A00000;
|
||||
*(u32 *)(cfgN3dsCpuLoc + 0x1F) = 0xE3A00000 + MULTICONFIG(1);
|
||||
*(u32 *)(cfgN3dsCpuLoc + 0x1F) = 0xE3A00000 | MULTICONFIG(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -281,7 +420,7 @@ void patchCode(u64 progId, u8 *code, u32 size)
|
||||
sizeof(secureinfoSigCheckPatch), 1
|
||||
);
|
||||
|
||||
if(R_SUCCEEDED(loadSecureinfo()))
|
||||
if(R_SUCCEEDED(loadSecureInfo()))
|
||||
{
|
||||
static const u16 secureinfoFilenamePattern[] = u"SecureInfo_";
|
||||
static const u16 secureinfoFilenamePatch[] = u"C";
|
||||
@ -298,5 +437,29 @@ void patchCode(u64 progId, u8 *code, u32 size)
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if((progId & 0xFFFFFFFF00000000LL) == 0x0004000000000000LL && R_SUCCEEDED(loadConfig()) && CONFIG(4))
|
||||
{
|
||||
//Language emulation
|
||||
u8 regionId = 0xFF,
|
||||
languageId = 0xFF;
|
||||
|
||||
int ret = loadTitleLocaleConfig(progId, ®ionId, &languageId);
|
||||
|
||||
if(R_SUCCEEDED(ret))
|
||||
{
|
||||
u32 CFGUHandleOffset = 0xFFFFFFFF;
|
||||
u8 *CFGU_GetConfigInfoBlk2_endPos = getCfgOffsets(code, size, &CFGUHandleOffset);
|
||||
|
||||
if(CFGU_GetConfigInfoBlk2_endPos != NULL)
|
||||
{
|
||||
if(languageId != 0xFF) patchCfgGetLanguage(code, size, languageId, CFGU_GetConfigInfoBlk2_endPos);
|
||||
if(regionId != 0xFF) patchCfgGetRegion(code, size, regionId, &CFGUHandleOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
@ -17,11 +17,12 @@ dir_source := source
|
||||
dir_build := build
|
||||
|
||||
ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te
|
||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main -O2 -flto -ffast-math -mthumb -mthumb-interwork
|
||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math -mthumb -mthumb-interwork
|
||||
LDFLAGS := -nostartfiles
|
||||
|
||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||
|
||||
.PHONY: all
|
||||
all: $(name).bin
|
||||
@ -34,8 +35,7 @@ $(name).bin: $(dir_build)/$(name).elf
|
||||
$(OC) -S -O binary $< $@
|
||||
|
||||
$(dir_build)/$(name).elf: $(objects)
|
||||
# FatFs requires libgcc for __aeabi_uidiv
|
||||
$(CC) -nostartfiles -T linker.ld $(OUTPUT_OPTION) $^
|
||||
$(CC) $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.c
|
||||
@mkdir -p "$(@D)"
|
||||
|
@ -17,11 +17,12 @@ dir_source := source
|
||||
dir_build := build
|
||||
|
||||
ASFLAGS := -mlittle-endian -mcpu=mpcore
|
||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main -O2 -flto -ffast-math -mthumb -mthumb-interwork
|
||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math -mthumb -mthumb-interwork
|
||||
LDFLAGS := -nostdlib
|
||||
|
||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
||||
|
||||
.PHONY: all
|
||||
all: $(name).bin
|
||||
@ -34,7 +35,7 @@ $(name).bin: $(dir_build)/$(name).elf
|
||||
$(OC) -S -O binary $< $@
|
||||
|
||||
$(dir_build)/$(name).elf: $(objects)
|
||||
$(CC) -nostartfiles -T linker.ld $(OUTPUT_OPTION) $^
|
||||
$(CC) $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
|
||||
$(dir_build)/%.o: $(dir_source)/%.c
|
||||
@mkdir -p "$(@D)"
|
||||
|
@ -26,6 +26,7 @@ void configureCFW(const char *configPath)
|
||||
"( ) Updated SysNAND mode (A9LH-only)",
|
||||
"( ) Force A9LH detection",
|
||||
"( ) Use second EmuNAND as default",
|
||||
"( ) Enable region/language emulation",
|
||||
"( ) Use developer UNITINFO",
|
||||
"( ) Show current NAND in System Settings",
|
||||
"( ) Show GBA boot screen in patched AGB_FIRM",
|
||||
|
@ -142,7 +142,7 @@ void main(void)
|
||||
configureCFW(configPath);
|
||||
|
||||
//If screens are inited or the corresponding option is set, load splash screen
|
||||
if(PDN_GPU_CNT != 1 || CONFIG(7)) loadSplash();
|
||||
if(PDN_GPU_CNT != 1 || CONFIG(8)) loadSplash();
|
||||
|
||||
//Determine if we need to boot an emuNAND or sysNAND
|
||||
nandType = (pressed & BUTTON_L1) ? autoBootSys : ((pressed & BUTTON_R1) ? updatedSys : !autoBootSys);
|
||||
@ -271,7 +271,7 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhInstalle
|
||||
*(u16 *)sigOffset2 = sigPatch[0];
|
||||
*((u16 *)sigOffset2 + 1) = sigPatch[1];
|
||||
|
||||
if(CONFIG(4))
|
||||
if(CONFIG(5))
|
||||
{
|
||||
//Apply UNITINFO patch
|
||||
u8 *unitInfoOffset = getUnitInfoValueSet(arm9Section, section[2].size);
|
||||
@ -381,7 +381,7 @@ static inline void patchTwlAgbFirm(u32 firmType)
|
||||
|
||||
/* 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) */
|
||||
u32 numPatches = firmType == 1 ? (sizeof(twlPatches) / sizeof(patchData)) : (sizeof(agbPatches) / sizeof(patchData) - !CONFIG(6));
|
||||
u32 numPatches = firmType == 1 ? (sizeof(twlPatches) / sizeof(patchData)) : (sizeof(agbPatches) / sizeof(patchData) - !CONFIG(7));
|
||||
const patchData *patches = firmType == 1 ? twlPatches : agbPatches;
|
||||
|
||||
//Patch
|
||||
|
Reference in New Issue
Block a user