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 <noreply@anthropic.com>
This commit is contained in:
Mohd Faour 2026-10-08 16:55:41 +02:00 committed by Mohd Faour
parent 4b005b229e
commit ce5a2136a8
2 changed files with 23 additions and 6 deletions

View File

@ -18,6 +18,8 @@
namespace {
constexpr int SCE_SYSMODULE_ERROR_UNLOADED = static_cast<int>(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<std::mutex> 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<std::mutex> 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<std::mutex> 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;

View File

@ -3,6 +3,9 @@
#include <cstdlib>
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<int>(0x80A90003);
constexpr std::uint16_t kFiberModuleId = 0x0006;
constexpr std::uint16_t kUltModuleId = 0x0007;
constexpr int kModuleUnloaded = static_cast<int>(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);
}