diff --git a/sysmodules/loader/source/ifile.c b/sysmodules/loader/source/ifile.c index c7052ad..10418f5 100644 --- a/sysmodules/loader/source/ifile.c +++ b/sysmodules/loader/source/ifile.c @@ -11,6 +11,16 @@ Result IFile_Open(IFile *file, FS_ArchiveID archiveId, FS_Path archivePath, FS_P return res; } +Result IFile_OpenFromArchive(IFile *file, FS_Archive archive, FS_Path filePath, u32 flags) +{ + Result res; + + res = FSUSER_OpenFile(&file->handle, archive, filePath, flags, 0); + file->pos = 0; + file->size = 0; + return res; +} + Result IFile_Close(IFile *file) { return FSFILE_Close(file->handle); @@ -21,7 +31,16 @@ Result IFile_GetSize(IFile *file, u64 *size) Result res; res = FSFILE_GetSize(file->handle, size); - file->size = *size; + if (R_SUCCEEDED(res)) file->size = *size; + return res; +} + +Result IFile_SetSize(IFile *file, u64 size) +{ + Result res; + + res = FSFILE_SetSize(file->handle, size); + if (R_SUCCEEDED(res)) file->size = size; return res; } @@ -45,7 +64,7 @@ Result IFile_Read(IFile *file, u64 *total, void *buffer, u32 len) while (1) { res = FSFILE_Read(file->handle, &read, file->pos, buf, left); - if (R_FAILED(res)) + if (R_FAILED(res) || read == 0) { break; } @@ -63,3 +82,42 @@ Result IFile_Read(IFile *file, u64 *total, void *buffer, u32 len) *total = cur; return res; } + +Result IFile_Write(IFile *file, u64 *total, const void *buffer, u32 len, u32 flags) +{ + u32 written; + u32 left; + char *buf; + u64 cur; + Result res; + + if (len == 0) + { + *total = 0; + return 0; + } + + buf = (char *)buffer; + cur = 0; + left = len; + while (1) + { + res = FSFILE_Write(file->handle, &written, file->pos, buf, left, flags); + if (R_FAILED(res)) + { + break; + } + + cur += written; + file->pos += written; + if (written == left) + { + break; + } + buf += written; + left -= written; + } + + *total = cur; + return res; +} diff --git a/sysmodules/loader/source/ifile.h b/sysmodules/loader/source/ifile.h index f939547..e184777 100644 --- a/sysmodules/loader/source/ifile.h +++ b/sysmodules/loader/source/ifile.h @@ -2,14 +2,19 @@ #include <3ds/types.h> +#define PATH_MAX 255 + typedef struct { - Handle handle; - u64 pos; - u64 size; + Handle handle; + u64 pos; + u64 size; } IFile; Result IFile_Open(IFile *file, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 flags); +Result IFile_OpenFromArchive(IFile *file, FS_Archive archive, FS_Path filePath, u32 flags); Result IFile_Close(IFile *file); Result IFile_GetSize(IFile *file, u64 *size); -Result IFile_Read(IFile *file, u64 *total, void *buffer, u32 len); \ No newline at end of file +Result IFile_SetSize(IFile *file, u64 size); +Result IFile_Read(IFile *file, u64 *total, void *buffer, u32 len); +Result IFile_Write(IFile *file, u64 *total, const void *buffer, u32 len, u32 flags); diff --git a/sysmodules/rosalina/include/ifile.h b/sysmodules/rosalina/include/ifile.h index 4683a12..515296b 100644 --- a/sysmodules/rosalina/include/ifile.h +++ b/sysmodules/rosalina/include/ifile.h @@ -41,5 +41,6 @@ Result IFile_Open(IFile *file, FS_ArchiveID archiveId, FS_Path archivePath, FS_P Result IFile_OpenFromArchive(IFile *file, FS_Archive archive, FS_Path filePath, u32 flags); Result IFile_Close(IFile *file); Result IFile_GetSize(IFile *file, u64 *size); +Result IFile_SetSize(IFile *file, u64 size); Result IFile_Read(IFile *file, u64 *total, void *buffer, u32 len); -Result IFile_Write(IFile *file, u64 *total, void *buffer, u32 len, u32 flags); +Result IFile_Write(IFile *file, u64 *total, const void *buffer, u32 len, u32 flags); diff --git a/sysmodules/rosalina/include/process_patches.h b/sysmodules/rosalina/include/process_patches.h index 4ecec3c..2bd0e9c 100644 --- a/sysmodules/rosalina/include/process_patches.h +++ b/sysmodules/rosalina/include/process_patches.h @@ -29,5 +29,7 @@ #include <3ds/types.h> #include "menu.h" +typedef Result(* OperateOnProcessCb)(Handle processHandle, u32 textSz, u32 roSz, u32 rwSz); + Result OpenProcessByName(const char *name, Handle *h); -Result PatchProcessByName(const char *name, Result (*func)(u32 size)); +Result OperateOnProcessByName(const char *name, OperateOnProcessCb func); // doesn't operate on the heap diff --git a/sysmodules/rosalina/source/ifile.c b/sysmodules/rosalina/source/ifile.c index 7ede5c4..515fa91 100644 --- a/sysmodules/rosalina/source/ifile.c +++ b/sysmodules/rosalina/source/ifile.c @@ -57,7 +57,16 @@ Result IFile_GetSize(IFile *file, u64 *size) Result res; res = FSFILE_GetSize(file->handle, size); - file->size = *size; + if (R_SUCCEEDED(res)) file->size = *size; + return res; +} + +Result IFile_SetSize(IFile *file, u64 size) +{ + Result res; + + res = FSFILE_SetSize(file->handle, size); + if (R_SUCCEEDED(res)) file->size = size; return res; } @@ -100,7 +109,7 @@ Result IFile_Read(IFile *file, u64 *total, void *buffer, u32 len) return res; } -Result IFile_Write(IFile *file, u64 *total, void *buffer, u32 len, u32 flags) +Result IFile_Write(IFile *file, u64 *total, const void *buffer, u32 len, u32 flags) { u32 written; u32 left; diff --git a/sysmodules/rosalina/source/process_patches.c b/sysmodules/rosalina/source/process_patches.c index 8ba7843..77191eb 100644 --- a/sysmodules/rosalina/source/process_patches.c +++ b/sysmodules/rosalina/source/process_patches.c @@ -59,20 +59,32 @@ Result OpenProcessByName(const char *name, Handle *h) return 0; } -Result PatchProcessByName(const char *name, Result (*func)(u32 size)) +Result OperateOnProcessByName(const char *name, OperateOnProcessCb func) { Result res; Handle processHandle; - OpenProcessByName(name, &processHandle); + res = OpenProcessByName(name, &processHandle); - s64 textTotalRoundedSize = 0, startAddress = 0; - svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text - svcGetProcessInfo(&startAddress, processHandle, 0x10005); - if(R_FAILED(res = svcMapProcessMemoryEx(processHandle, 0x00100000, (u32) startAddress, textTotalRoundedSize))) + if (R_FAILED(res)) return res; - res = func(textTotalRoundedSize); + s64 startAddress, textSize, roSize, rwSize; - svcUnmapProcessMemoryEx(processHandle, 0x00100000, textTotalRoundedSize); + svcGetProcessInfo(&textSize, processHandle, 0x10002); // rounded sizes + svcGetProcessInfo(&roSize, processHandle, 0x10003); + svcGetProcessInfo(&rwSize, processHandle, 0x10004); // data and bss + svcGetProcessInfo(&startAddress, processHandle, 0x10005); + + // NOTE: we suppose .text, .rodata, .data+.bss are contiguous & in that order + u32 totalSize = (u32)(textSize + roSize + rwSize); + if (R_FAILED(res = svcMapProcessMemoryEx(processHandle, 0x00100000, (u32) startAddress, totalSize))) + { + svcCloseHandle(processHandle); + return res; + } + + res = func(processHandle, (u32)textSize, (u32)roSize, (u32)rwSize); + + svcUnmapProcessMemoryEx(processHandle, 0x00100000, totalSize); return res; }