LayeredFS
This commit is contained in:
parent
28e6ad3372
commit
5b6bd048a9
@ -1,80 +1,107 @@
|
|||||||
; Code from delebile
|
|
||||||
|
|
||||||
.arm.little
|
.arm.little
|
||||||
.create "build/romfsredir.bin", 0
|
.create "build/romfsredir.bin", 0
|
||||||
|
|
||||||
|
.macro addr, reg, func
|
||||||
|
add reg, pc, #func-.-8
|
||||||
|
.endmacro
|
||||||
.macro load, reg, func
|
.macro load, reg, func
|
||||||
ldr reg, [pc, #func-.-8]
|
ldr reg, [pc, #func-.-8]
|
||||||
.endmacro
|
.endmacro
|
||||||
|
.macro svc, svcnum
|
||||||
|
.word 0xef000000 + svcnum
|
||||||
|
.endmacro
|
||||||
|
|
||||||
|
; Patch by delebile
|
||||||
|
|
||||||
.arm
|
.arm
|
||||||
; fsOpenFileDirectly function will be redirected here.
|
_start:
|
||||||
; If the requested archive is not ROMFS, we'll return
|
|
||||||
; to the original function.
|
; Jumps here before the fsOpenFileDirectly call
|
||||||
openFileDirectlyHook:
|
_mountSd:
|
||||||
|
b mountSd
|
||||||
|
.word 0xdead0000 ; Substituted opcode
|
||||||
|
.word 0xdead0001 ; Branch to hooked function
|
||||||
|
|
||||||
|
; Jumps here before every iFileOpen call
|
||||||
|
_fsRedir:
|
||||||
|
b fsRedir
|
||||||
|
.word 0xdead0002 ; Substituted opcode
|
||||||
|
.word 0xdead0003 ; Branch to hooked function
|
||||||
|
|
||||||
|
; Mounts SDMC and registers the archive as 'sdmc:'
|
||||||
|
mountSd:
|
||||||
cmp r3, #3
|
cmp r3, #3
|
||||||
beq openRomfs
|
bne _mountSd+4
|
||||||
load r12, fsOpenFileDirectly
|
stmfd sp!, {r0-r4, lr}
|
||||||
nop ; Will be replaced with the original function opcode
|
sub sp, sp, #4
|
||||||
bx r12
|
mov r1, #9
|
||||||
|
mov r0, sp
|
||||||
|
load r4, fsMountArchive
|
||||||
|
blx r4
|
||||||
|
mov r3, #0
|
||||||
|
mov r2, #0
|
||||||
|
ldr r1, [sp]
|
||||||
|
addr r0, sdmcArchiveName
|
||||||
|
load r4, fsRegisterArchive
|
||||||
|
blx r4
|
||||||
|
add sp, sp, #4
|
||||||
|
ldmfd sp!, {r0-r4, lr}
|
||||||
|
b _mountSd+4
|
||||||
|
|
||||||
; We redirect ROMFS file opening by changing the parameters and call
|
; Check the path passed to iFileOpen.
|
||||||
; the fsOpenFileDirectly function recursively. The parameter format:
|
; If it is trying to access a RomFS file, we try to
|
||||||
; r0 : fsUserHandle
|
; open it from the title folder on the sdcard.
|
||||||
; r1 : Output FileHandle
|
; If the file cannot be opened from the sdcard, we just open
|
||||||
; r2 : Transaction (usually 0)
|
; it from its original archive like nothing happened
|
||||||
; r3 : Archive ID
|
fsRedir:
|
||||||
; [sp, #0x00] : Archive PathType
|
stmfd sp!, {r0-r12, lr}
|
||||||
; [sp, #0x04] : Archive DataPointer
|
ldrb r12, [r1]
|
||||||
; [sp, #0x08] : Archive PathSize
|
cmp r12, #0x72 ; 'r', should include "rom:" and "rom2:"
|
||||||
; [sp, #0x0C] : File PathType
|
bne endRedir
|
||||||
; [sp, #0x10] : File DataPointer
|
sub sp, sp, #0x400
|
||||||
; [sp, #0x14] : File PathSize
|
pathRedir:
|
||||||
; [sp, #0x18] : File OpenFlags
|
stmfd sp!, {r0-r3}
|
||||||
; [sp, #0x1C] : Attributes (usually 0)
|
add r0, sp, #0x10
|
||||||
openRomfs:
|
addr r3, sdmcCustomPath
|
||||||
sub sp, sp, #0x50
|
pathRedir_1:
|
||||||
stmfd sp!, {r0, r1, lr}
|
ldrb r2, [r3], #1
|
||||||
add sp, sp, #0x5C
|
strh r2, [r0], #2
|
||||||
str r3, [sp, #0x0C] ; File PathType (ASCII = 3)
|
cmp r2, #0
|
||||||
load r12, romfsFileName
|
bne pathRedir_1
|
||||||
str r12, [sp, #0x10] ; File DataPointer
|
sub r0, r0, #2
|
||||||
load r12, romfsFileNameSize
|
pathRedir_2:
|
||||||
str r12, [sp, #0x14] ; File PathSize
|
ldrh r2, [r1], #2
|
||||||
load r3, archive
|
cmp r2, #0x3A ; ':'
|
||||||
bl openFileDirectlyHook
|
bne pathRedir_2
|
||||||
sub sp, sp, #0x5C
|
pathRedir_3:
|
||||||
ldmfd sp!, {r0, r1, lr}
|
ldrh r2, [r1], #2
|
||||||
add sp, sp, #0x50
|
strh r2, [r0], #2
|
||||||
mov r0, r1 ; Substitute fsUserHandle with the fileHandle
|
cmp r2, #0
|
||||||
|
bne pathRedir_3
|
||||||
|
ldmfd sp!, {r0-r3}
|
||||||
|
mov r1, sp
|
||||||
|
bl _fsRedir+4
|
||||||
|
add sp, sp, #0x400
|
||||||
|
cmp r0, #0
|
||||||
|
|
||||||
; Once we have the sd romfs file opened, we'll open a subfile
|
endRedir:
|
||||||
; in order to skip the useless data.
|
ldmfd sp!, {r0-r12, lr}
|
||||||
stmfd sp!, {r1, r3-r11}
|
moveq r0, #0
|
||||||
mrc p15, 0, r4, c13, c0, 3
|
beq panic
|
||||||
add r4, r4, #0x80
|
bxeq lr
|
||||||
mov r1, r4
|
b _fsRedir+4
|
||||||
add r3, pc, #fsOpenSubFileCmd-.-8
|
|
||||||
ldmia r3!, {r5-r9}
|
panic:
|
||||||
stmia r1!, {r5-r9}
|
swi 0x3C
|
||||||
ldr r0, [r0]
|
b panic
|
||||||
swi 0x32
|
|
||||||
ldr r0, [r4, #0x0C]
|
|
||||||
ldmfd sp!, {r1, r3-r11}
|
|
||||||
str r0, [r1]
|
|
||||||
mov r0, #0
|
|
||||||
bx lr
|
|
||||||
|
|
||||||
.pool
|
.pool
|
||||||
.align 4
|
.align 4
|
||||||
; Part of these symbols will be set from outside
|
sdmcArchiveName : .dcb "sdmc:", 0
|
||||||
fsOpenFileDirectly : .word 0
|
.align 4
|
||||||
fsOpenSubFileCmd : .word 0x08010100
|
fsMountArchive : .word 0xdead0005
|
||||||
.word 0 ; File Offset
|
fsRegisterArchive : .word 0xdead0006
|
||||||
.word 0
|
sdmcCustomPath : .word 0xdead0004
|
||||||
.word 0 ; File Size
|
|
||||||
.word 0
|
|
||||||
archive : .word 0
|
|
||||||
romfsFileNameSize : .word 0
|
|
||||||
romfsFileName : .word 0 ; File DataPointer
|
|
||||||
.close
|
.close
|
||||||
|
|
||||||
|
@ -107,3 +107,75 @@ Result FSLDR_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archi
|
|||||||
|
|
||||||
return cmdbuf[1];
|
return cmdbuf[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result FSLDR_OpenArchive(FS_Archive* archive, FS_ArchiveID id, FS_Path path)
|
||||||
|
{
|
||||||
|
if(!archive) return -2;
|
||||||
|
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(0x80C,3,2); // 0x80C00C2
|
||||||
|
cmdbuf[1] = id;
|
||||||
|
cmdbuf[2] = path.type;
|
||||||
|
cmdbuf[3] = path.size;
|
||||||
|
cmdbuf[4] = IPC_Desc_StaticBuffer(path.size, 0);
|
||||||
|
cmdbuf[5] = (u32) path.data;
|
||||||
|
|
||||||
|
Result ret = 0;
|
||||||
|
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
|
||||||
|
|
||||||
|
if(archive) *archive = cmdbuf[2] | ((u64) cmdbuf[3] << 32);
|
||||||
|
|
||||||
|
return cmdbuf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Result FSLDR_CloseArchive(FS_Archive archive)
|
||||||
|
{
|
||||||
|
if(!archive) return -2;
|
||||||
|
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(0x80E,2,0); // 0x80E0080
|
||||||
|
cmdbuf[1] = (u32) archive;
|
||||||
|
cmdbuf[2] = (u32) (archive >> 32);
|
||||||
|
|
||||||
|
Result ret = 0;
|
||||||
|
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
|
||||||
|
|
||||||
|
return cmdbuf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Result FSLDR_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path)
|
||||||
|
{
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(0x80B,4,2); // 0x80B0102
|
||||||
|
cmdbuf[1] = (u32) archive;
|
||||||
|
cmdbuf[2] = (u32) (archive >> 32);
|
||||||
|
cmdbuf[3] = path.type;
|
||||||
|
cmdbuf[4] = path.size;
|
||||||
|
cmdbuf[5] = IPC_Desc_StaticBuffer(path.size, 0);
|
||||||
|
cmdbuf[6] = (u32) path.data;
|
||||||
|
|
||||||
|
Result ret = 0;
|
||||||
|
if(R_FAILED(ret = svcSendSyncRequest(fsldrHandle))) return ret;
|
||||||
|
|
||||||
|
if(out) *out = cmdbuf[3];
|
||||||
|
|
||||||
|
return cmdbuf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Result FSDIRLDR_Close(Handle handle)
|
||||||
|
{
|
||||||
|
u32 *cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
|
cmdbuf[0] = IPC_MakeHeader(0x802,0,0); // 0x8020000
|
||||||
|
|
||||||
|
Result ret = 0;
|
||||||
|
if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
|
||||||
|
|
||||||
|
ret = cmdbuf[1];
|
||||||
|
if(R_SUCCEEDED(ret)) ret = svcCloseHandle(handle);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
@ -7,3 +7,7 @@ void fsldrExit(void);
|
|||||||
Result FSLDR_InitializeWithSdkVersion(Handle session, u32 version);
|
Result FSLDR_InitializeWithSdkVersion(Handle session, u32 version);
|
||||||
Result FSLDR_SetPriority(u32 priority);
|
Result FSLDR_SetPriority(u32 priority);
|
||||||
Result FSLDR_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 openFlags, u32 attributes);
|
Result FSLDR_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 openFlags, u32 attributes);
|
||||||
|
Result FSLDR_OpenArchive(FS_Archive* archive, FS_ArchiveID id, FS_Path path);
|
||||||
|
Result FSLDR_CloseArchive(FS_Archive archive);
|
||||||
|
Result FSLDR_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path);
|
||||||
|
Result FSDIRLDR_Close(Handle handle);
|
@ -2,6 +2,7 @@
|
|||||||
#include "patcher.h"
|
#include "patcher.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "strings.h"
|
#include "strings.h"
|
||||||
|
#include "fsldr.h"
|
||||||
#include "ifile.h"
|
#include "ifile.h"
|
||||||
#include "CFWInfo.h"
|
#include "CFWInfo.h"
|
||||||
#include "../build/bundled.h"
|
#include "../build/bundled.h"
|
||||||
@ -39,6 +40,25 @@ static Result fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, in
|
|||||||
return IFile_Open(file, archiveId, archivePath, filePath, flags);
|
return IFile_Open(file, archiveId, archivePath, filePath, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool dirCheck(FS_ArchiveID archiveId, const char *path)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
Handle handle;
|
||||||
|
FS_Archive archive;
|
||||||
|
FS_Path dirPath = {PATH_ASCII, strnlen(path, 255) + 1, path},
|
||||||
|
archivePath = {PATH_EMPTY, 1, (u8 *)""};
|
||||||
|
|
||||||
|
if(R_FAILED(FSLDR_OpenArchive(&archive, archiveId, archivePath))) ret = false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = R_SUCCEEDED(FSLDR_OpenDirectory(&handle, archive, dirPath));
|
||||||
|
if(ret) FSDIRLDR_Close(handle);
|
||||||
|
FSLDR_CloseArchive(archive);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static u32 openLumaFile(IFile *file, const char *path)
|
static u32 openLumaFile(IFile *file, const char *path)
|
||||||
{
|
{
|
||||||
Result res = fileOpen(file, ARCHIVE_SDMC, path, FS_OPEN_READ);
|
Result res = fileOpen(file, ARCHIVE_SDMC, path, FS_OPEN_READ);
|
||||||
@ -49,6 +69,11 @@ static u32 openLumaFile(IFile *file, const char *path)
|
|||||||
return (u32)res == 0xC88044AB && R_SUCCEEDED(fileOpen(file, ARCHIVE_NAND_RW, path, FS_OPEN_READ)) ? ARCHIVE_NAND_RW : 0;
|
return (u32)res == 0xC88044AB && R_SUCCEEDED(fileOpen(file, ARCHIVE_NAND_RW, path, FS_OPEN_READ)) ? ARCHIVE_NAND_RW : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool checkLumaDir(const char *path)
|
||||||
|
{
|
||||||
|
return dirCheck(ARCHIVE_SDMC, path);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void loadCFWInfo(void)
|
static inline void loadCFWInfo(void)
|
||||||
{
|
{
|
||||||
static bool infoLoaded = false;
|
static bool infoLoaded = false;
|
||||||
@ -249,7 +274,7 @@ static inline void patchCfgGetRegion(u8 *code, u32 size, u8 regionId, u32 CFGUHa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 findNearestStmfd(u8* code, u32 pos)
|
static u32 findStart(u8* code, u32 pos)
|
||||||
{
|
{
|
||||||
while(pos >= 4)
|
while(pos >= 4)
|
||||||
{
|
{
|
||||||
@ -260,36 +285,82 @@ static u32 findNearestStmfd(u8* code, u32 pos)
|
|||||||
return 0xFFFFFFFF;
|
return 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 findFunctionCommand(u8* code, u32 size, u32 command)
|
static bool findSymbols(u8* code, u32 size, u32 *fsMountArchive, u32 *fsRegisterArchive, u32 *fsTryOpenFile, u32 *fsOpenFileDirectly, u32 *throwFatalError)
|
||||||
{
|
{
|
||||||
u32 func;
|
u32 svcConnectToPort = 0xFFFFFFFF;
|
||||||
|
|
||||||
for(func = 4; *(u32 *)(code + func) != command; func += 4)
|
for(u32 addr = 0; addr <= size - 4; addr += 4)
|
||||||
if(func > size - 8) return 0xFFFFFFFF;
|
{
|
||||||
|
if(*fsMountArchive == 0xFFFFFFFF)
|
||||||
|
{
|
||||||
|
if(addr <= size - 12 && *(u32 *)(code + addr) == 0xE5970010)
|
||||||
|
{
|
||||||
|
if((*(u32 *)(code + addr + 4) == 0xE1CD20D8) && ((*(u32 *)(code + addr + 8) & 0xFFFFFF) == 0x008D0000))
|
||||||
|
*fsMountArchive = findStart(code, addr);
|
||||||
|
}
|
||||||
|
else if(addr <= size - 16 && *(u32 *)(code + addr) == 0xE24DD028)
|
||||||
|
{
|
||||||
|
if((*(u32 *)(code + addr + 4) == 0xE1A04000) && (*(u32 *)(code + addr + 8) == 0xE59F60A8) && (*(u32 *)(code + addr + 0xC) == 0xE3A0C001))
|
||||||
|
*fsMountArchive = findStart(code, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return findNearestStmfd(code, func);
|
if(*fsRegisterArchive == 0xFFFFFFFF && addr <= size - 8)
|
||||||
}
|
{
|
||||||
|
if(*(u32 *)(code + addr) == 0xC82044B4)
|
||||||
|
{
|
||||||
|
if(*(u32 *)(code + addr + 4) == 0xD8604659)
|
||||||
|
*fsRegisterArchive = findStart(code, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline u32 findThrowFatalError(u8* code, u32 size)
|
if(*fsTryOpenFile == 0xFFFFFFFF && addr <= size - 12)
|
||||||
{
|
{
|
||||||
u32 connectToPort;
|
if(*(u32 *)(code + addr + 0xC) == 0xE12FFF3C)
|
||||||
|
{
|
||||||
|
if(((*(u32 *)(code + addr) == 0xE1A0100D) || (*(u32 *)(code + addr) == 0xE28D1010)) &&
|
||||||
|
(*(u32 *)(code + addr + 4) == 0xE590C000) && ((*(u32 *)(code + addr + 8) == 0xE1A00004) || (*(u32 *)(code + addr + 8) == 0xE1A00005)))
|
||||||
|
{
|
||||||
|
*fsTryOpenFile = findStart(code, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(connectToPort = 0; *(u32 *)(code + connectToPort + 4) != 0xEF00002D; connectToPort += 4)
|
if(*fsOpenFileDirectly == 0xFFFFFFFF)
|
||||||
if(connectToPort > size - 12) return 0xFFFFFFFF;
|
{
|
||||||
|
if(*(u32 *)(code + addr) == 0x08030204)
|
||||||
|
{
|
||||||
|
*fsOpenFileDirectly = findStart(code, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(svcConnectToPort == 0xFFFFFFFF && addr >= 4)
|
||||||
|
{
|
||||||
|
if(*(u32 *)(code + addr) == 0xEF00002D)
|
||||||
|
svcConnectToPort = addr - 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(svcConnectToPort != 0xFFFFFFFF && *fsMountArchive != 0xFFFFFFFF && *fsRegisterArchive != 0xFFFFFFFF && *fsTryOpenFile != 0xFFFFFFFF && *fsOpenFileDirectly != 0xFFFFFFFF)
|
||||||
|
{
|
||||||
u32 func = 0xFFFFFFFF;
|
u32 func = 0xFFFFFFFF;
|
||||||
|
|
||||||
for(u32 i = 4; func == 0xFFFFFFFF && i <= size - 4; i += 4)
|
for(u32 i = 4; func == 0xFFFFFFFF && i <= size - 4; i += 4)
|
||||||
{
|
{
|
||||||
if(*(u32 *)(code + i) != MAKE_BRANCH_LINK(i, connectToPort)) continue;
|
if(*(u32 *)(code + i) != MAKE_BRANCH_LINK(i, svcConnectToPort)) continue;
|
||||||
|
|
||||||
func = findNearestStmfd(code, i);
|
func = findStart(code, i);
|
||||||
|
|
||||||
for(u32 pos = func + 4; func != 0xFFFFFFFF && pos <= size - 4 && *(u16 *)(code + pos + 2) != 0xE92D; pos += 4)
|
for(u32 pos = func + 4; func != 0xFFFFFFFF && pos <= size - 4 && *(u16 *)(code + pos + 2) != 0xE92D; pos += 4)
|
||||||
if(*(u32 *)(code + pos) == 0xE200167E) func = 0xFFFFFFFF;
|
if(*(u32 *)(code + pos) == 0xE200167E) func = 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
return func;
|
*throwFatalError = func;
|
||||||
|
|
||||||
|
if(func != 0xFFFFFFFF) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool applyCodeIpsPatch(u64 progId, u8 *code, u32 size)
|
static inline bool applyCodeIpsPatch(u64 progId, u8 *code, u32 size)
|
||||||
@ -442,57 +513,56 @@ static inline bool patchRomfsRedirection(u64 progId, u8* code, u32 size)
|
|||||||
char path[] = "/luma/titles/0000000000000000/romfs";
|
char path[] = "/luma/titles/0000000000000000/romfs";
|
||||||
progIdToStr(path + 28, progId);
|
progIdToStr(path + 28, progId);
|
||||||
|
|
||||||
IFile file;
|
if(!checkLumaDir(path)) return true;
|
||||||
u32 archive = openLumaFile(&file, path);
|
|
||||||
|
|
||||||
if(!archive) return true;
|
u32 fsMountArchive = 0xFFFFFFFF,
|
||||||
|
fsRegisterArchive = 0xFFFFFFFF,
|
||||||
|
fsTryOpenFile = 0xFFFFFFFF,
|
||||||
|
fsOpenFileDirectly = 0xFFFFFFFF,
|
||||||
|
throwFatalError;
|
||||||
|
|
||||||
bool ret = false;
|
if(!findSymbols(code, size, &fsMountArchive, &fsRegisterArchive, &fsTryOpenFile, &fsOpenFileDirectly, &throwFatalError)) return false;
|
||||||
u64 romfsSize;
|
|
||||||
|
|
||||||
if(R_FAILED(IFile_GetSize(&file, &romfsSize))) goto exit;
|
|
||||||
|
|
||||||
u64 total;
|
|
||||||
u32 magic;
|
|
||||||
|
|
||||||
if(R_FAILED(IFile_Read(&file, &total, &magic, 4)) || total != 4 || magic != 0x43465649) goto exit;
|
|
||||||
|
|
||||||
u32 fsOpenFileDirectly = findFunctionCommand(code, size, 0x08030204),
|
|
||||||
throwFatalError = findThrowFatalError(code, size);
|
|
||||||
|
|
||||||
if(fsOpenFileDirectly == 0xFFFFFFFF || throwFatalError == 0xFFFFFFFF) goto exit;
|
|
||||||
|
|
||||||
//Setup the payload
|
//Setup the payload
|
||||||
u8 *payload = code + throwFatalError;
|
u8 *payload = code + throwFatalError;
|
||||||
memcpy(payload, romfsredir_bin, romfsredir_bin_size);
|
memcpy(payload, romfsredir_bin, romfsredir_bin_size);
|
||||||
memcpy(payload + romfsredir_bin_size, path, sizeof(path));
|
|
||||||
*(u32 *)(payload + 0xC) = *(u32 *)(code + fsOpenFileDirectly);
|
|
||||||
|
|
||||||
u32 *payloadSymbols = (u32 *)(payload + romfsredir_bin_size - 0x24);
|
//Insert symbols in the payload
|
||||||
payloadSymbols[0] = 0x100000 + fsOpenFileDirectly + 4;
|
u32 *payload32 = (u32 *)payload;
|
||||||
*(u64 *)(payloadSymbols + 2) = 0x1000ULL;
|
for(u32 i = 0; i < romfsredir_bin_size / 4; i++)
|
||||||
*(u64 *)(payloadSymbols + 4) = romfsSize - 0x1000ULL;
|
{
|
||||||
payloadSymbols[6] = archive;
|
switch (payload32[i])
|
||||||
payloadSymbols[7] = sizeof(path);
|
{
|
||||||
payloadSymbols[8] = 0x100000 + throwFatalError + romfsredir_bin_size; //String pointer
|
case 0xdead0000:
|
||||||
|
payload32[i] = *(u32 *)(code + fsOpenFileDirectly);
|
||||||
|
break;
|
||||||
|
case 0xdead0001:
|
||||||
|
payload32[i] = MAKE_BRANCH(throwFatalError + i * 4, fsOpenFileDirectly + 4);
|
||||||
|
break;
|
||||||
|
case 0xdead0002:
|
||||||
|
payload32[i] = *(u32 *)(code + fsTryOpenFile);
|
||||||
|
break;
|
||||||
|
case 0xdead0003:
|
||||||
|
payload32[i] = MAKE_BRANCH(throwFatalError + i * 4, fsTryOpenFile + 4);
|
||||||
|
break;
|
||||||
|
case 0xdead0004:
|
||||||
|
memcpy(payload32 + i, "sdmc:", 5);
|
||||||
|
memcpy((u8 *)(payload32 + i) + 5, path, sizeof(path));
|
||||||
|
break;
|
||||||
|
case 0xdead0005:
|
||||||
|
payload32[i] = 0x100000 + fsMountArchive;
|
||||||
|
break;
|
||||||
|
case 0xdead0006:
|
||||||
|
payload32[i] = 0x100000 + fsRegisterArchive;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Place the hooks
|
//Place the hooks
|
||||||
*(u32 *)(code + fsOpenFileDirectly) = MAKE_BRANCH(fsOpenFileDirectly, throwFatalError);
|
*(u32 *)(code + fsOpenFileDirectly) = MAKE_BRANCH(fsOpenFileDirectly, throwFatalError);
|
||||||
|
*(u32 *)(code + fsTryOpenFile) = MAKE_BRANCH(fsTryOpenFile, throwFatalError + 12);
|
||||||
|
|
||||||
u32 fsOpenLinkFile = findFunctionCommand(code, size, 0x80C0000);
|
return true;
|
||||||
|
|
||||||
if(fsOpenLinkFile != 0xFFFFFFFF)
|
|
||||||
{
|
|
||||||
*(u32 *)(code + fsOpenLinkFile) = 0xE3A03003; //mov r3, #3
|
|
||||||
*(u32 *)(code + fsOpenLinkFile + 4) = MAKE_BRANCH(fsOpenLinkFile + 4, throwFatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = true;
|
|
||||||
|
|
||||||
exit:
|
|
||||||
IFile_Close(&file);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
|
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user