From ce5a2136a8231e57a80c0ba0337e11b8aba1efc7 Mon Sep 17 00:00:00 2001 From: Mohd Faour Date: Thu, 8 Oct 2026 16:55:41 +0200 Subject: [PATCH] fix(sysmodule): report a module that is not loaded as SCE_SYSMODULE_ERROR_UNLOADED sceSysmoduleIsLoaded returned 0x80A90002 and the unload calls 0x80A90003 for a module that is not loaded. Neither value exists in the SDK: the sysmodule facility is 0x5A and the error is 0x805A1001, which titles compare against (GTA V PPSA04263: cmp eax,0x805a1001 after IsLoaded) to decide whether to load and initialise the module themselves. Return that value from all three places and cover it in guest_sysmodule. Co-Authored-By: Claude Fable 5.1 --- core/libs/prx/libSceSysmodule/Export.cpp | 8 +++++--- core/libs/tests/GuestSysmodule.cpp | 21 ++++++++++++++++++--- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/core/libs/prx/libSceSysmodule/Export.cpp b/core/libs/prx/libSceSysmodule/Export.cpp index 85b64a2ed..83f56fb54 100644 --- a/core/libs/prx/libSceSysmodule/Export.cpp +++ b/core/libs/prx/libSceSysmodule/Export.cpp @@ -18,6 +18,8 @@ namespace { +constexpr int SCE_SYSMODULE_ERROR_UNLOADED = static_cast(0x805A1001); + const char* findModuleName(const std::uint32_t id) { const auto it = kModuleTable.find(id); return it != kModuleTable.end() ? it->second : nullptr; @@ -112,7 +114,7 @@ int APS5_VABI sceSysmoduleIsLoaded(std::uint16_t id) { std::lock_guard lock(gMutex); auto it = gLoadCount.find(id); if (it == gLoadCount.end() || it->second < 1) { - return 0x80A90002; + return SCE_SYSMODULE_ERROR_UNLOADED; } return 0; } @@ -160,7 +162,7 @@ int APS5_VABI sceSysmoduleUnloadModule(std::uint16_t id) { std::lock_guard lock(gMutex); auto it = gLoadCount.find(id); if (it == gLoadCount.end() || it->second < 1) { - return 0x80A90003; + return SCE_SYSMODULE_ERROR_UNLOADED; } it->second--; return 0; @@ -188,7 +190,7 @@ int APS5_VABI sceSysmoduleUnloadModuleInternal(std::uint32_t id) { std::lock_guard lock(gMutex); auto it = gLoadCount.find(id); if (it == gLoadCount.end() || it->second < 1) { - return 0x80A90003; + return SCE_SYSMODULE_ERROR_UNLOADED; } it->second--; return 0; diff --git a/core/libs/tests/GuestSysmodule.cpp b/core/libs/tests/GuestSysmodule.cpp index bf6dbaa00..f3ffdecb0 100644 --- a/core/libs/tests/GuestSysmodule.cpp +++ b/core/libs/tests/GuestSysmodule.cpp @@ -3,6 +3,9 @@ #include extern "C" { +int APS5_VABI sceSysmoduleIsLoaded(std::uint16_t id); +int APS5_VABI sceSysmoduleLoadModule(std::uint16_t id); +int APS5_VABI sceSysmoduleUnloadModule(std::uint16_t id); int APS5_VABI sceSysmoduleLoadModuleInternal(std::uint32_t id); int APS5_VABI sceSysmoduleUnloadModuleInternal(std::uint32_t id); } @@ -11,15 +14,27 @@ namespace { void Require(bool value) { if (!value) std::abort(); } -constexpr std::uint32_t kFiberModuleId = 0x00000006; -constexpr int kModuleNotLoaded = static_cast(0x80A90003); +constexpr std::uint16_t kFiberModuleId = 0x0006; +constexpr std::uint16_t kUltModuleId = 0x0007; +constexpr int kModuleUnloaded = static_cast(0x805A1001); } int main() { + Require(sceSysmoduleIsLoaded(kFiberModuleId) == kModuleUnloaded); Require(sceSysmoduleLoadModuleInternal(kFiberModuleId) == 0); + Require(sceSysmoduleIsLoaded(kFiberModuleId) == 0); Require(sceSysmoduleLoadModuleInternal(kFiberModuleId) == 0); Require(sceSysmoduleUnloadModuleInternal(kFiberModuleId) == 0); + Require(sceSysmoduleIsLoaded(kFiberModuleId) == 0); Require(sceSysmoduleUnloadModuleInternal(kFiberModuleId) == 0); - Require(sceSysmoduleUnloadModuleInternal(kFiberModuleId) == kModuleNotLoaded); + Require(sceSysmoduleIsLoaded(kFiberModuleId) == kModuleUnloaded); + Require(sceSysmoduleUnloadModuleInternal(kFiberModuleId) == kModuleUnloaded); + + Require(sceSysmoduleIsLoaded(kUltModuleId) == kModuleUnloaded); + Require(sceSysmoduleUnloadModule(kUltModuleId) == kModuleUnloaded); + Require(sceSysmoduleLoadModule(kUltModuleId) == 0); + Require(sceSysmoduleIsLoaded(kUltModuleId) == 0); + Require(sceSysmoduleUnloadModule(kUltModuleId) == 0); + Require(sceSysmoduleIsLoaded(kUltModuleId) == kModuleUnloaded); }