diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 8abad4708b..e5979dbe57 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1921,14 +1921,14 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load return module; } -SceUID KernelLoadModule(const std::string &filename, std::string *error_string) { +SceUID KernelLoadModule(const std::string &filename, std::string *error_string, bool fromTop) { std::vector buffer; if (pspFileSystem.ReadEntireFile(filename, buffer) < 0) return SCE_KERNEL_ERROR_NOFILE; u32 error = SCE_KERNEL_ERROR_ILLEGAL_OBJECT; u32 magic; - PSPModule *module = __KernelLoadELFFromPtr(&buffer[0], buffer.size(), 0, false, error_string, &magic, filename, error); + PSPModule *module = __KernelLoadELFFromPtr(&buffer[0], buffer.size(), 0, fromTop, error_string, &magic, filename, error); if (module == nullptr) return error; diff --git a/Core/HLE/sceKernelModule.h b/Core/HLE/sceKernelModule.h index 6fcbbcfd5b..c1f0c5d359 100644 --- a/Core/HLE/sceKernelModule.h +++ b/Core/HLE/sceKernelModule.h @@ -247,7 +247,11 @@ bool KernelFindImportByStubAddr(u32 stubAddr, std::string *importModuleName, u32 bool DescribeModuleAddress(u32 address, char *buffer, size_t bufferSize); int __KernelGPUReplay(); void __KernelReturnFromModuleFunc(); -SceUID KernelLoadModule(const std::string &filename, std::string *error_string); +// fromTop puts the module at the top of the user partition instead of the bottom. Use it for +// firmware modules we inject before the game loads - taking the bottom pushes the game's own ELF +// up, which shifts every address in it and invalidates cheats and achievements, and outright +// fails for a game like Tekken 6 whose EBOOT must load at a fixed low address. +SceUID KernelLoadModule(const std::string &filename, std::string *error_string, bool fromTop = false); int __KernelStartModule(SceUID moduleId, u32 argsize, u32 argAddr, u32 returnValueAddr, SceKernelSMOption *smoption, bool *needsWait); u32 __KernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode, u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr, bool WithStatus); u32 sceKernelFindModuleByUID(u32 uid); diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 90102697cc..a6a9ba32fc 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -108,7 +108,7 @@ static void NotifyLoadStatusMp4(int state, u32 loadAddr, u32 totalSize) { continue; } std::string error; - SceUID id = KernelLoadModule(paths[i], &error); + SceUID id = KernelLoadModule(paths[i], &error, true); if (id < 0) { ERROR_LOG(Log::sceUtility, "sceMp4 HLE is disabled, but %s wouldn't load (%s) - " "the game will get unresolved imports", paths[i], error.c_str());