From f78dd5365c93f51f3ad0d5ef51b052511907bebf Mon Sep 17 00:00:00 2001 From: TuxSH Date: Sun, 5 Jun 2016 20:43:49 +0200 Subject: [PATCH] External .code section loading for titles and some refactoring --- injector/source/patcher.c | 50 ++++++++++++++++++++++++++++++------- source/config.c | 2 +- source/start.s | 52 +++++++++++++++++++-------------------- source/utils.c | 14 +++++------ source/utils.h | 4 ++- 5 files changed, 77 insertions(+), 45 deletions(-) diff --git a/injector/source/patcher.c b/injector/source/patcher.c index b78ddf8..3b3d4a5 100644 --- a/injector/source/patcher.c +++ b/injector/source/patcher.c @@ -125,21 +125,50 @@ static u32 loadConfig(void) return config; } +static void progIdToStr(char *strEnd, u64 progId) +{ + while(progId) + { + static const char hexDigits[] = "0123456789ABCDEF"; + *strEnd-- = hexDigits[(u32)(progId & 0xF)]; + progId >>= 4; + } +} + +static int loadTitleCodeSection(u64 progId, u8 *code, u32 size) +{ + /* Here we look for "/luma/code_sections/[u64 titleID in hex, uppercase].bin" + If it exists it should be a decompressed binary code file */ + + char path[] = "/luma/code_sections/0000000000000000.bin"; + progIdToStr(path + 35, progId); + + IFile file; + Result ret = fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ); + + if(R_SUCCEEDED(ret)) + { + u64 fileSize, total; + + ret = IFile_GetSize(&file, &fileSize); + if(!R_SUCCEEDED(ret) || fileSize > size) return -1; + + ret = IFile_Read(&file, &total, code, fileSize); + IFile_Close(&file); + if(!R_SUCCEEDED(ret)) return -1; + else if(total < fileSize) return -2; //Shouldn't happen + } + + return ret; +} + static int loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageId) { /* Here we look for "/luma/locales/[u64 titleID in hex, uppercase].txt" If it exists it should contain, for example, "EUR IT" */ char path[] = "/luma/locales/0000000000000000.txt"; - - u32 i = 29; - - while(progId) - { - static const char hexDigits[] = "0123456789ABCDEF"; - path[i--] = hexDigits[(u32)(progId & 0xF)]; - progId >>= 4; - } + progIdToStr(path + 29, progId); IFile file; Result ret = fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ); @@ -522,6 +551,9 @@ void patchCode(u64 progId, u8 *code, u32 size) if(tidHigh == 0x0004000) { + //External .code section loading + if(loadTitleCodeSection(progId, code, size) == -2) svcBreak(USERBREAK_ASSERT); + //Language emulation u8 regionId = 0xFF, languageId = 0xFF; diff --git a/source/config.c b/source/config.c index fb1c1cc..07ce486 100644 --- a/source/config.c +++ b/source/config.c @@ -24,7 +24,7 @@ void configureCFW(const char *configPath) "( ) SysNAND is updated (A9LH-only)", "( ) Force A9LH detection", "( ) Use second EmuNAND as default", - "( ) Enable region/language emulation", + "( ) Enable region/language emu. and external .code loading", "( ) Show current NAND in System Settings", "( ) Show GBA boot screen in patched AGB_FIRM", "( ) Enable splash screen with no screen-init" }; diff --git a/source/start.s b/source/start.s index cd73a4e..d446a4f 100644 --- a/source/start.s +++ b/source/start.s @@ -11,16 +11,16 @@ start: mov sp, #0x27000000 @ Disable caches / mpu - mrc p15, 0, r4, c1, c0, 0 @ read control register - bic r4, #(1<<12) @ - instruction cache disable - bic r4, #(1<<2) @ - data cache disable - bic r4, #(1<<0) @ - mpu disable - mcr p15, 0, r4, c1, c0, 0 @ write control register + mrc p15, 0, r0, c1, c0, 0 @ read control register + bic r0, #(1<<12) @ - instruction cache disable + bic r0, #(1<<2) @ - data cache disable + bic r0, #(1<<0) @ - mpu disable + mcr p15, 0, r0, c1, c0, 0 @ write control register @ Give read/write access to all the memory regions - ldr r5, =0x33333333 - mcr p15, 0, r5, c5, c0, 2 @ write data access - mcr p15, 0, r5, c5, c0, 3 @ write instruction access + ldr r0, =0x33333333 + mcr p15, 0, r0, c5, c0, 2 @ write data access + mcr p15, 0, r0, c5, c0, 3 @ write instruction access @ Sets MPU permissions and cache settings ldr r0, =0xFFFF001D @ ffff0000 32k | bootrom (unprotected part) @@ -31,9 +31,7 @@ start: ldr r5, =0x20000037 @ 20000000 256M | fcram (O3DS / N3DS) ldr r6, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram ldr r7, =0x1800002D @ 18000000 8M | vram (+ 2MB) - mov r10, #0x25 - mov r11, #0x25 - mov r12, #0x25 + mov r8, #0x25 mcr p15, 0, r0, c6, c0, 0 mcr p15, 0, r1, c6, c1, 0 mcr p15, 0, r2, c6, c2, 0 @@ -42,28 +40,28 @@ start: mcr p15, 0, r5, c6, c5, 0 mcr p15, 0, r6, c6, c6, 0 mcr p15, 0, r7, c6, c7, 0 - mcr p15, 0, r10, c3, c0, 0 @ Write bufferable 0, 2, 5 - mcr p15, 0, r11, c2, c0, 0 @ Data cacheable 0, 2, 5 - mcr p15, 0, r12, c2, c0, 1 @ Inst cacheable 0, 2, 5 + mcr p15, 0, r8, c3, c0, 0 @ Write bufferable 0, 2, 5 + mcr p15, 0, r8, c2, c0, 0 @ Data cacheable 0, 2, 5 + mcr p15, 0, r8, c2, c0, 1 @ Inst cacheable 0, 2, 5 @ Enable dctm - ldr r1, =0x3000800A @ set dtcm - mcr p15, 0, r1, c9, c1, 0 @ set the dtcm Region Register + ldr r0, =0x3000800A @ set dtcm + mcr p15, 0, r0, c9, c1, 0 @ set the dtcm Region Register @ Enable caches - mrc p15, 0, r4, c1, c0, 0 @ read control register - orr r4, r4, #(1<<18) @ - itcm enable - orr r4, r4, #(1<<16) @ - dtcm enable - orr r4, r4, #(1<<12) @ - instruction cache enable - orr r4, r4, #(1<<2) @ - data cache enable - orr r4, r4, #(1<<0) @ - mpu enable - mcr p15, 0, r4, c1, c0, 0 @ write control register + mrc p15, 0, r0, c1, c0, 0 @ read control register + orr r0, r0, #(1<<18) @ - itcm enable + orr r0, r0, #(1<<16) @ - dtcm enable + orr r0, r0, #(1<<12) @ - instruction cache enable + orr r0, r0, #(1<<2) @ - data cache enable + orr r0, r0, #(1<<0) @ - mpu enable + mcr p15, 0, r0, c1, c0, 0 @ write control register @ Flush caches - mov r5, #0 - mcr p15, 0, r5, c7, c5, 0 @ flush I-cache - mcr p15, 0, r5, c7, c6, 0 @ flush D-cache - mcr p15, 0, r5, c7, c10, 4 @ drain write buffer + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ flush I-cache + mcr p15, 0, r0, c7, c6, 0 @ flush D-cache + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer @ Fixes mounting of SDMC ldr r0, =0x10000020 diff --git a/source/utils.c b/source/utils.c index e62c8dc..5497437 100644 --- a/source/utils.c +++ b/source/utils.c @@ -44,13 +44,13 @@ static inline void startChrono(u64 initialTicks) { //Based on a NATIVE_FIRM disassembly - *(vu16 *)0x10003002 = 0; //67MHz - for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) = 4; //Count-up + REG_TIMER_CNT(0) = 0; //67MHz + for(u32 i = 1; i < 4; i++) REG_TIMER_CNT(i) = 4; //Count-up - for(u32 i = 0; i < 4; i++) *(vu16 *)(0x10003000 + 4 * i) = (u16)(initialTicks >> (16 * i)); + for(u32 i = 0; i < 4; i++) REG_TIMER_VAL(i) = (u16)(initialTicks >> (16 * i)); - *(vu16 *)0x10003002 = 0x80; //67MHz; enabled - for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) = 0x84; //Count-up; enabled + REG_TIMER_CNT(0) = 0x80; //67MHz; enabled + for(u32 i = 1; i < 4; i++) REG_TIMER_CNT(i) = 0x84; //Count-up; enabled } void chrono(u32 seconds) @@ -64,7 +64,7 @@ void chrono(u32 seconds) do { res = 0; - for(u32 i = 0; i < 4; i++) res |= *(vu16 *)(0x10003000 + 4 * i) << (16 * i); + for(u32 i = 0; i < 4; i++) res |= REG_TIMER_VAL(i) << (16 * i); } while(res - startingTicks < seconds * TICKS_PER_SEC); @@ -73,5 +73,5 @@ void chrono(u32 seconds) void stopChrono(void) { - for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) &= ~0x80; + for(u32 i = 0; i < 4; i++) REG_TIMER_CNT(i) &= ~0x80; } \ No newline at end of file diff --git a/source/utils.h b/source/utils.h index 236b048..25a3f5f 100644 --- a/source/utils.h +++ b/source/utils.h @@ -9,7 +9,9 @@ u32 waitInput(void); void mcuReboot(void); -#define TICKS_PER_SEC 67027964ULL +#define TICKS_PER_SEC 67027964ULL +#define REG_TIMER_CNT(i) *(vu16 *)(0x10003002 + 4 * i) +#define REG_TIMER_VAL(i) *(vu16 *)(0x10003000 + 4 * i) void chrono(u32 seconds); void stopChrono(void); \ No newline at end of file