From 33b6229a6ff9eb7b744afd53592fbffca7abb088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 21 Oct 2026 06:42:49 +0200 Subject: [PATCH] HLE: Add sceKernelQueryLoadCoreCB The firmware's semawm.prx (6.61), which PMP Mod and psp-me-bench load, decrypts code that walks LoadCore's registered-library hash buckets at the start of this block, looking for libraries a custom firmware would add. We don't keep those structures, so it gets an empty table in kernel memory, made on first use and kept in the savestate. Co-Authored-By: Claude Opus 5.5 (1M context) --- Core/HLE/HLETables.cpp | 3 ++- Core/HLE/sceKernelModule.cpp | 27 ++++++++++++++++++++++++++- Core/HLE/sceKernelModule.h | 1 + 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Core/HLE/HLETables.cpp b/Core/HLE/HLETables.cpp index d680f04039..38ef766c76 100644 --- a/Core/HLE/HLETables.cpp +++ b/Core/HLE/HLETables.cpp @@ -149,7 +149,7 @@ static const HLEFunction LoadCoreForKernel[] = { {0X0E760DBA, nullptr, "sceKernelLinkLibraryEntries", '?', "" }, {0X0DE1F600, nullptr, "sceKernelLinkLibraryEntriesForUser", '?', "" }, {0XDA1B09AA, nullptr, "sceKernelUnLinkLibraryEntries", '?', "" }, - {0XC99DD47A, nullptr, "sceKernelQueryLoadCoreCB", '?', "" }, + {0XC99DD47A, &WrapU_V, "sceKernelQueryLoadCoreCB", 'x', "", HLE_KERNEL_SYSCALL }, {0X616FCCCD, nullptr, "sceKernelSetBootCallbackLevel", '?', "" }, {0XF32A2940, nullptr, "sceKernelModuleFromUID", '?', "" }, {0XCD0F3BAC, nullptr, "sceKernelCreateModule", '?', "" }, @@ -165,6 +165,7 @@ static const HLEFunction LoadCoreForKernel[] = { {0XC0584F0C, nullptr, "sceKernelGetModuleList", '?', "" }, {0XCF8A41B1, &WrapU_C, "sceKernelFindModuleByName", 'x', "s", HLE_KERNEL_SYSCALL }, {0XB95FA50D, nullptr, "LoadCoreForKernel_B95FA50D", '?', "" }, + {0x696594C8, &WrapU_V, "sceKernelQueryLoadCoreCB660", 'x', "", HLE_KERNEL_SYSCALL }, }; diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 236312e6d3..c87bec6599 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -152,6 +152,9 @@ static void UnexportFuncSymbol(const FuncSymbolExport &func); // Chinese-patch loaders (see sctrlHENSetStartModuleHandler below). static u32 g_startModuleHandler = 0; +// LoadCore's control block, for sceKernelQueryLoadCoreCB. Made on first use. +static u32 g_loadCoreCB = 0; + static bool KernelImportModuleFuncs(PSPModule *module, u32 *firstImportStubAddr, bool reimporting = false); // by QueryModuleInfo @@ -563,7 +566,7 @@ std::vector> __KernelModuleCodeRanges() { } void __KernelModuleDoState(PointerWrap &p) { - auto s = p.Section("sceKernelModule", 1, 6); + auto s = p.Section("sceKernelModule", 1, 7); if (!s) return; @@ -612,6 +615,12 @@ void __KernelModuleDoState(PointerWrap &p) { g_vshModuleStarting = 0; } + if (s >= 7) { + Do(p, g_loadCoreCB); + } else if (p.mode == p.MODE_READ) { + g_loadCoreCB = 0; + } + if (p.mode == p.MODE_READ) { u32 error; // We process these late, since they depend on loadedModules for interlinking. @@ -652,6 +661,7 @@ void __KernelModuleShutdown() { g_pendingModuleLoads.clear(); g_vshModulesToStart.clear(); g_vshModuleStarting = 0; + g_loadCoreCB = 0; MIPSAnalyst::Reset(); HLEPlugins::Unload(); } @@ -3360,6 +3370,21 @@ u32 sceKernelFindModuleByUID(u32 uid) return hleLogInfo(Log::sceModule, module->modulePtr.ptr); } +// The firmware's semawm.prx walks the first 0x200 bytes, the registered libraries' 128 hash buckets, +// for libraries a custom firmware adds (decrypted from semawm 6.61, run by PMP Mod and psp-me-bench). +// We don't keep LoadCore's structures, so every bucket is empty. +u32 sceKernelQueryLoadCoreCB() { + if (!g_loadCoreCB) { + u32 size = 0x400; + const u32 addr = kernelMemory.Alloc(size, false, "LoadCoreCB"); + if (addr == (u32)-1) + return hleLogError(Log::sceModule, 0, "out of kernel memory"); + Memory::Memset(addr, 0, size, "LoadCoreCB"); + g_loadCoreCB = addr; + } + return hleLogInfo(Log::sceModule, g_loadCoreCB); +} + u32 sceKernelFindModuleByName(const char *name) { u32 error; diff --git a/Core/HLE/sceKernelModule.h b/Core/HLE/sceKernelModule.h index 812e85f7d5..9fe57c7973 100644 --- a/Core/HLE/sceKernelModule.h +++ b/Core/HLE/sceKernelModule.h @@ -270,6 +270,7 @@ bool KernelUnloadModuleByID(SceUID moduleId); 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); +u32 sceKernelQueryLoadCoreCB(); void Register_ModuleMgrForUser(); void Register_ModuleMgrForKernel();