mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-02 19:08:03 -06:00
* Replace sysmodule enums with table
Dumped this from the 12.52 module, using a script I created.
* Better documentation
* Separate from system libraries
That system folder is going to be getting quite large if I left all the sysmodule stuff in there.
* More arrays from library
* Found another preload list
Ghidra really hates decompiling libSceSysmodule, so I didn't notice this one at first.
Also documented specific versions tied to each preload list.
* Start work on implementation
* Some basic implementations
* Initial stub for module loading
Just enough to see if the logic functions appropriately.
* Clang
* sceSysmoduleLoadModule
Now I need to get sceSysmodulePreloadModuleForLibkernel done so that we don't have bugs from not loading internal LLEs.
* sceSysmoduleLoadModuleInternal
* sceSysmodulePreloadModuleForLibkernel
I have successfully broken quite literally everything.
I shall debug this tomorrow.
* Slight fix
* Maybe fix?
* Change log
Enjoy the log spam 😄
* Increased defined stub count
Now that libc and libSceLibcInternal loads later, all the auto stubs are getting consumed by it.
* sceSysmoduleUnloadModule stub
Also a couple fixes. Sysmodule does pass argc and argv to game modules, but only after loading them once to check binaries.
Shouldn't matter for the most part.
* Clang
* Less stubs
2 thousand is seemingly enough.
* sceSysmoduleLoadModuleInternalWithArg
Doesn't hurt to have, since Apex Legends calls it.
* Oops
* Oops 2
* Rename isModuleLoaded to getModuleHandle
Review comment
* Remove debug game module loads
These cases only trigger when specific sceRegMgr key values are set, and for our purposes, we can treat that case as false.
* Allow preloading to fail
For kalaposfos
* Clang
205 lines
6.9 KiB
C++
205 lines
6.9 KiB
C++
// SPDX-FileCopyrightText: Copyright 2025-2026 shadPS4 Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include <mutex>
|
|
|
|
#include "common/elf_info.h"
|
|
#include "common/logging/log.h"
|
|
#include "core/libraries/error_codes.h"
|
|
#include "core/libraries/kernel/orbis_error.h"
|
|
#include "core/libraries/kernel/process.h"
|
|
#include "core/libraries/libs.h"
|
|
#include "core/libraries/sysmodule/sysmodule.h"
|
|
#include "core/libraries/sysmodule/sysmodule_error.h"
|
|
#include "core/libraries/sysmodule/sysmodule_internal.h"
|
|
#include "core/linker.h"
|
|
|
|
namespace Libraries::SysModule {
|
|
|
|
static std::mutex g_mutex{};
|
|
|
|
s32 PS4_SYSV_ABI sceSysmoduleGetModuleHandleInternal(OrbisSysModuleInternal id, s32* handle) {
|
|
LOG_INFO(Lib_SysModule, "called");
|
|
if ((id & 0x7fffffff) == 0) {
|
|
return ORBIS_SYSMODULE_INVALID_ID;
|
|
}
|
|
|
|
std::scoped_lock lk{g_mutex};
|
|
return getModuleHandle(id, handle);
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceSysmoduleGetModuleInfoForUnwind(VAddr addr, s32 flags,
|
|
Kernel::OrbisModuleInfoForUnwind* info) {
|
|
LOG_TRACE(Lib_SysModule, "sceSysmoduleGetModuleInfoForUnwind called");
|
|
s32 res = Kernel::sceKernelGetModuleInfoForUnwind(addr, flags, info);
|
|
if (res != ORBIS_OK) {
|
|
return res;
|
|
}
|
|
|
|
if (shouldHideName(info->name.data())) {
|
|
std::ranges::fill(info->name, '\0');
|
|
}
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceSysmoduleIsCalledFromSysModule() {
|
|
LOG_ERROR(Lib_SysModule, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceSysmoduleIsCameraPreloaded() {
|
|
LOG_ERROR(Lib_SysModule, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceSysmoduleIsLoaded(OrbisSysModule id) {
|
|
if (id == 0) {
|
|
return ORBIS_SYSMODULE_INVALID_ID;
|
|
}
|
|
|
|
std::scoped_lock lk{g_mutex};
|
|
return getModuleHandle(id, nullptr);
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceSysmoduleIsLoadedInternal(OrbisSysModuleInternal id) {
|
|
if ((id & 0x7fffffff) == 0) {
|
|
return ORBIS_SYSMODULE_INVALID_ID;
|
|
}
|
|
|
|
std::scoped_lock lk{g_mutex};
|
|
return getModuleHandle(id, nullptr);
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceSysmoduleLoadModule(OrbisSysModule id) {
|
|
LOG_INFO(Lib_SysModule, "called, id = {:#x}", id);
|
|
s32 result = validateModuleId(id);
|
|
if (result < ORBIS_OK) {
|
|
return result;
|
|
}
|
|
|
|
// Only locks for internal loadModule call.
|
|
{
|
|
std::scoped_lock lk{g_mutex};
|
|
result = loadModule(id, 0, nullptr, nullptr);
|
|
}
|
|
|
|
if (result == ORBIS_KERNEL_ERROR_ESTART) {
|
|
s32 sdk_ver = 0;
|
|
result = Kernel::sceKernelGetCompiledSdkVersion(&sdk_ver);
|
|
if (sdk_ver < Common::ElfInfo::FW_115 || result != ORBIS_OK) {
|
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
|
} else {
|
|
return ORBIS_KERNEL_ERROR_ESTART;
|
|
}
|
|
}
|
|
|
|
// The real library has some weird workaround for CUSA01478 and CUSA01495 here.
|
|
// Unless this is proven necessary, I don't plan to handle this.
|
|
return result;
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceSysmoduleLoadModuleByNameInternal() {
|
|
LOG_ERROR(Lib_SysModule, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceSysmoduleLoadModuleInternal(OrbisSysModuleInternal id) {
|
|
LOG_INFO(Lib_SysModule, "called, id = {:#x}", id);
|
|
s32 result = validateModuleId(id);
|
|
if (result < ORBIS_OK) {
|
|
return result;
|
|
}
|
|
|
|
// This specific module ID is loaded unlocked.
|
|
if (id == 0x80000039) {
|
|
return loadModule(id, 0, nullptr, nullptr);
|
|
}
|
|
std::scoped_lock lk{g_mutex};
|
|
return loadModule(id, 0, nullptr, nullptr);
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceSysmoduleLoadModuleInternalWithArg(OrbisSysModuleInternal id, s32 argc,
|
|
const void* argv, u64 unk, s32* res_out) {
|
|
LOG_INFO(Lib_SysModule, "called, id = {:#x}", id);
|
|
s32 result = validateModuleId(id);
|
|
if (result < ORBIS_OK) {
|
|
return result;
|
|
}
|
|
|
|
if (unk != 0) {
|
|
return ORBIS_SYSMODULE_INVALID_ID;
|
|
}
|
|
|
|
std::scoped_lock lk{g_mutex};
|
|
return loadModule(id, argc, argv, res_out);
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceSysmoduleMapLibcForLibkernel() {
|
|
LOG_ERROR(Lib_SysModule, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceSysmodulePreloadModuleForLibkernel() {
|
|
LOG_DEBUG(Lib_SysModule, "called");
|
|
return preloadModulesForLibkernel();
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceSysmoduleUnloadModule(OrbisSysModule id) {
|
|
LOG_ERROR(Lib_SysModule, "(STUBBED) called, id = {:#x}", id);
|
|
if (id == 0) {
|
|
return ORBIS_SYSMODULE_INVALID_ID;
|
|
}
|
|
|
|
std::scoped_lock lk{g_mutex};
|
|
return unloadModule(id, 0, nullptr, nullptr, false);
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceSysmoduleUnloadModuleByNameInternal() {
|
|
LOG_ERROR(Lib_SysModule, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceSysmoduleUnloadModuleInternal() {
|
|
LOG_ERROR(Lib_SysModule, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
s32 PS4_SYSV_ABI sceSysmoduleUnloadModuleInternalWithArg() {
|
|
LOG_ERROR(Lib_SysModule, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
|
LIB_FUNCTION("D8cuU4d72xM", "libSceSysmodule", 1, "libSceSysmodule",
|
|
sceSysmoduleGetModuleHandleInternal);
|
|
LIB_FUNCTION("4fU5yvOkVG4", "libSceSysmodule", 1, "libSceSysmodule",
|
|
sceSysmoduleGetModuleInfoForUnwind);
|
|
LIB_FUNCTION("ctfO7dQ7geg", "libSceSysmodule", 1, "libSceSysmodule",
|
|
sceSysmoduleIsCalledFromSysModule);
|
|
LIB_FUNCTION("no6T3EfiS3E", "libSceSysmodule", 1, "libSceSysmodule",
|
|
sceSysmoduleIsCameraPreloaded);
|
|
LIB_FUNCTION("fMP5NHUOaMk", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleIsLoaded);
|
|
LIB_FUNCTION("ynFKQ5bfGks", "libSceSysmodule", 1, "libSceSysmodule",
|
|
sceSysmoduleIsLoadedInternal);
|
|
LIB_FUNCTION("g8cM39EUZ6o", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleLoadModule);
|
|
LIB_FUNCTION("CU8m+Qs+HN4", "libSceSysmodule", 1, "libSceSysmodule",
|
|
sceSysmoduleLoadModuleByNameInternal);
|
|
LIB_FUNCTION("39iV5E1HoCk", "libSceSysmodule", 1, "libSceSysmodule",
|
|
sceSysmoduleLoadModuleInternal);
|
|
LIB_FUNCTION("hHrGoGoNf+s", "libSceSysmodule", 1, "libSceSysmodule",
|
|
sceSysmoduleLoadModuleInternalWithArg);
|
|
LIB_FUNCTION("lZ6RvVl0vo0", "libSceSysmodule", 1, "libSceSysmodule",
|
|
sceSysmoduleMapLibcForLibkernel);
|
|
LIB_FUNCTION("DOO+zuW1lrE", "libSceSysmodule", 1, "libSceSysmodule",
|
|
sceSysmodulePreloadModuleForLibkernel);
|
|
LIB_FUNCTION("eR2bZFAAU0Q", "libSceSysmodule", 1, "libSceSysmodule", sceSysmoduleUnloadModule);
|
|
LIB_FUNCTION("vpTHmA6Knvg", "libSceSysmodule", 1, "libSceSysmodule",
|
|
sceSysmoduleUnloadModuleByNameInternal);
|
|
LIB_FUNCTION("vXZhrtJxkGc", "libSceSysmodule", 1, "libSceSysmodule",
|
|
sceSysmoduleUnloadModuleInternal);
|
|
LIB_FUNCTION("aKa6YfBKZs4", "libSceSysmodule", 1, "libSceSysmodule",
|
|
sceSysmoduleUnloadModuleInternalWithArg);
|
|
};
|
|
|
|
} // namespace Libraries::SysModule
|