From 17d7dcdd6c04438f1dd1276ddb73bbf3f4f04132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 15 Mar 2025 17:40:24 +0100 Subject: [PATCH] Make sceUtilityLoadAvModule work correctly --- Core/HLE/sceAtrac.cpp | 13 +++++- Core/HLE/sceAtrac.h | 4 +- Core/HLE/sceKernelModule.cpp | 13 +++--- Core/HLE/sceUtility.cpp | 80 +++++++++++++++++++++++------------- 4 files changed, 73 insertions(+), 37 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index c3b0a3c5dd..e488cb360c 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -95,7 +95,11 @@ const AtracBase *__AtracGetCtx(int i, u32 *type) { void __AtracInit() { _assert_(sizeof(SceAtracContext) == 256); - atracInited = true; + atracLibVersion = 0; + atracLibCrc = 0; + + atracInited = true; // TODO: This should probably only happen in __AtracNotifyLoadModule. + memset(atracContexts, 0, sizeof(atracContexts)); // Start with 2 of each in this order. @@ -114,13 +118,18 @@ void __AtracShutdown() { } } -void __AtracLoadModule(int version, u32 crc, u32 bssAddr, int bssSize) { +void __AtracNotifyLoadModule(int version, u32 crc, u32 bssAddr, int bssSize) { atracLibVersion = version; atracLibCrc = crc; INFO_LOG(Log::ME, "Atrac module loaded: atracLibVersion 0x%0x, atracLibcrc %x, bss: %x (%x bytes)", atracLibVersion, atracLibCrc, bssAddr, bssSize); // Later, save bssAddr/bssSize and use them to return context addresses. } +void __AtracNotifyUnloadModule() { + atracLibVersion = 0; + atracLibCrc = 0; +} + void __AtracDoState(PointerWrap &p) { auto s = p.Section("sceAtrac", 1, 2); if (!s) diff --git a/Core/HLE/sceAtrac.h b/Core/HLE/sceAtrac.h index e77bac86c7..ad776f25e3 100644 --- a/Core/HLE/sceAtrac.h +++ b/Core/HLE/sceAtrac.h @@ -25,7 +25,9 @@ void Register_sceAtrac3plus(); void __AtracInit(); void __AtracDoState(PointerWrap &p); void __AtracShutdown(); -void __AtracLoadModule(int version, u32 crc, u32 bssAddr, int bssSize); + +void __AtracNotifyLoadModule(int version, u32 crc, u32 bssAddr, int bssSize); +void __AtracNotifyUnloadModule(); enum AtracStatus : u8 { ATRAC_STATUS_NO_DATA = 1, diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 511e969a71..e5ffc05b8b 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -277,8 +277,9 @@ public: const char *GetTypeName() override { return GetStaticTypeName(); } static const char *GetStaticTypeName() { return "Module"; } void GetQuickInfo(char *ptr, int size) override { - snprintf(ptr, size, "%sname=%s gp=%08x entry=%08x", + snprintf(ptr, size, "%s %d.%d name=%s gp=%08x entry=%08x", isFake ? "faked " : "", + nm.version[0], nm.version[1], nm.name, nm.gp_value, nm.entry_addr); @@ -480,7 +481,8 @@ public: void PSPModule::GetLongInfo(char *ptr, int bufSize) const { StringWriter w(ptr, bufSize); - w.F("%s: Version %d.%d. %d segments", nm.name, nm.version[0], nm.version[1], nm.nsegment).endl(); + w.F("%s: Version %d.%d. %d segments", nm.name, nm.version[1], nm.version[0], nm.nsegment).endl(); + w.F("Memory block: %08x (%08x/%d bytes)", memoryBlockAddr, memoryBlockSize, memoryBlockSize).endl(); for (int i = 0; i < nm.nsegment; i++) { w.F(" %08x (%08x bytes)\n", nm.segmentaddr[i], nm.segmentsize[i]); } @@ -1340,7 +1342,6 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load strncpy(module->nm.name, head->modname, ARRAY_SIZE(module->nm.name)); module->nm.entry_addr = -1; module->nm.gp_value = -1; - module->nm.bss_size = head->bss_size; // Let's still try to allocate it. It may use user memory. u32 totalSize = 0; @@ -1367,6 +1368,8 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load module->memoryBlockAddr = addr; module->memoryBlockSize = totalSize; module->nm.text_addr = addr; + module->nm.bss_size = head->bss_size; + module->nm.nsegment = head->nsegments; module->nm.version[0] = head->module_ver_hi; module->nm.version[1] = head->module_ver_lo; @@ -1389,7 +1392,7 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load __PsmfPlayerLoadModule(devkitVersion, module->crc); } if (!strcmp(head->modname, "sceATRAC3plus_Library")) { - __AtracLoadModule(ver, module->crc, module->GetBSSAddr(), head->bss_size); + __AtracNotifyLoadModule(ver, module->crc, module->GetBSSAddr(), head->bss_size); } return module; @@ -1775,7 +1778,7 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load __PsmfPlayerLoadModule(devkitVersion, module->crc); } if (!strcmp(modinfo->name, "sceATRAC3plus_Library")) { - __AtracLoadModule(modinfo->moduleVersion, module->crc, module->GetBSSAddr(), module->nm.bss_size); + __AtracNotifyLoadModule(modinfo->moduleVersion, module->crc, module->GetBSSAddr(), module->nm.bss_size); } } diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index f9d7334c7c..75c18d8340 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -87,7 +87,10 @@ static void NotifyLoadStatusAtrac(int state, u32 loadAddr, u32 totalSize) { constexpr int version = 0x103; constexpr int bssSize = 0x67C; _dbg_assert_(bssSize <= totalSize); - __AtracLoadModule(version, 0, loadAddr, bssSize); + __AtracNotifyLoadModule(version, 0, loadAddr, bssSize); + } else if (state == -1) { + // Unload. + __AtracNotifyUnloadModule(); } } @@ -508,6 +511,9 @@ bool __UtilityModuleGetMemoryRange(int moduleID, u32 *startPtr, u32 *sizePtr) { return true; } +static int LoadModuleInternal(u32 module); +static int UnloadModuleInternal(u32 module); + // Same as sceUtilityLoadModule, just limited in categories. // It seems this just loads module 0x300 + module & 0xFF.. static u32 sceUtilityLoadAvModule(u32 module) { @@ -516,30 +522,54 @@ static u32 sceUtilityLoadAvModule(u32 module) { return hleLogError(Log::sceUtility, SCE_ERROR_AV_MODULE_BAD_ID); } - if (module == 0) - JpegNotifyLoadStatus(1); - return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility av module loaded", 25000); + int result = LoadModuleInternal(0x300 | module); + return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility av module loaded", 25000); } static u32 sceUtilityUnloadAvModule(u32 module) { - if (module == 0) - JpegNotifyLoadStatus(-1); - return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility av module unloaded", 800); + if (module > 7) { + ERROR_LOG_REPORT(Log::sceUtility, "sceUtilityLoadAvModule(%i): invalid module id", module); + return hleLogError(Log::sceUtility, SCE_ERROR_AV_MODULE_BAD_ID); + } + + int result = UnloadModuleInternal(0x300 | module); + return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility av module unloaded", 800); } static u32 sceUtilityLoadModule(u32 module) { + int result = LoadModuleInternal(module); + // TODO: Each module has its own timing, technically, but this is a low-end. + if (module == 0x3FF) { + return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility module loaded", 130); + } else { + return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility module loaded", 25000); + } +} + +static u32 sceUtilityUnloadModule(u32 module) { + int result = UnloadModuleInternal(module); + // TODO: Each module has its own timing, technically, but this is a low-end. + if (module == 0x3FF) { + return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility module unloaded", 110); + } else { + return hleDelayResult(hleLogDebugOrError(Log::sceUtility, result), "utility module unloaded", 400); + } +} + +static int LoadModuleInternal(u32 module) { const ModuleLoadInfo *info = __UtilityModuleInfo(module); if (!info) { - return hleReportError(Log::sceUtility, SCE_ERROR_MODULE_BAD_ID, "invalid module id"); + return SCE_ERROR_MODULE_BAD_ID; } + if (currentlyLoadedModules.find(module) != currentlyLoadedModules.end()) { - return hleLogError(Log::sceUtility, SCE_ERROR_MODULE_ALREADY_LOADED, "already loaded"); + return SCE_ERROR_MODULE_ALREADY_LOADED; } // Some games, like Kamen Rider Climax Heroes OOO, require an error if dependencies aren't loaded yet. for (const int *dep = info->dependencies; *dep != 0; ++dep) { if (currentlyLoadedModules.find(*dep) == currentlyLoadedModules.end()) { - return hleDelayResult(hleLogError(Log::sceUtility, SCE_KERNEL_ERROR_LIBRARY_NOTFOUND, "dependent module %04x not loaded", *dep), "utility module load attempt", 25000); + return SCE_KERNEL_ERROR_LIBRARY_NOTFOUND; } } @@ -554,36 +584,28 @@ static u32 sceUtilityLoadModule(u32 module) { if (info->notify) { info->notify(1, address, allocSize); } - - // TODO: Each module has its own timing, technically, but this is a low-end. - if (module == 0x3FF) - return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility module loaded", 130); - else - return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility module loaded", 25000); + return 0; } -static u32 sceUtilityUnloadModule(u32 module) { +static int UnloadModuleInternal(u32 module) { const ModuleLoadInfo *info = __UtilityModuleInfo(module); if (!info) { - return hleReportError(Log::sceUtility, SCE_ERROR_MODULE_BAD_ID, "invalid module id"); + return SCE_ERROR_MODULE_BAD_ID; } - if (currentlyLoadedModules.find(module) == currentlyLoadedModules.end()) { - return hleLogWarning(Log::sceUtility, SCE_ERROR_MODULE_NOT_LOADED, "not yet loaded"); + auto iter = currentlyLoadedModules.find(module); + if (iter == currentlyLoadedModules.end()) { + return SCE_ERROR_MODULE_NOT_LOADED; } - if (currentlyLoadedModules[module] != 0) { - userMemory.Free(currentlyLoadedModules[module]); + if (iter->second != 0) { + userMemory.Free(iter->second); } currentlyLoadedModules.erase(module); - if (info->notify) + if (info->notify) { info->notify(-1, 0, 0); - - // TODO: Each module has its own timing, technically, but this is a low-end. - if (module == 0x3FF) - return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility module unloaded", 110); - else - return hleDelayResult(hleLogInfo(Log::sceUtility, 0), "utility module unloaded", 400); + } + return 0; } static int sceUtilityMsgDialogInitStart(u32 paramAddr) {