From 1a3f14acd040143b65edc58f55fd6229bcf29e91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 10 Sep 2026 10:48:32 -0600 Subject: [PATCH] HLE: add the 5.xx NIDs the VSH of that era imports sceKernelLoadModuleVSH, sceKernelGetModel, and four of sceImpose_driver's calls already have implementations; 5.xx just asks for them under different NIDs, so the 5.50 shell got nothing back. Each one was identified by disassembling that firmware's own module and comparing the body against 6.61's, where the same function is exported under a name - the pairs are instruction-for-instruction identical apart from context-struct offsets. GetModel was the one that mattered most: unresolved, vshbridge handed the shell a garbage model number, and it went looking for PSP-3000 resources on a dump that has none. Co-Authored-By: Claude Opus 5 (1M context) --- Core/HLE/sceImpose.cpp | 10 ++++++++++ Core/HLE/sceKernelHeap.cpp | 6 ++++++ Core/HLE/sceKernelModule.cpp | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/Core/HLE/sceImpose.cpp b/Core/HLE/sceImpose.cpp index 1b47edf3cc..e2a4adf3a7 100644 --- a/Core/HLE/sceImpose.cpp +++ b/Core/HLE/sceImpose.cpp @@ -271,6 +271,16 @@ const HLEFunction sceImpose_driver[] = { // NOTE: new entries go at the end - the syscall opcode in a savestate is an index into this array. {0X531C9778, &WrapI_I, "sceImposeGetParam", 'i', "i" }, {0XB415FC59, &WrapI_V, "sceImposeChanges", 'i', "" }, + // And the 5.xx NIDs for four of them, identified the same way against 6.61's impose_02g.prx: + // each body is instruction-for-instruction the same, differing only in the offset of the field + // it touches in the impose context (Changes reads-and-clears +0xB4 here where 6.61 uses +0xBC, + // SetStatus works on +0x9C where 6.61 uses +0xA4). They sit in the same order at almost the + // same addresses in both modules. Unresolved, GetParam and Changes were most of the 5.50 VSH + // boot log, since it calls them every frame. + {0XC860DB52, &WrapI_I, "sceImposeSetStatus", 'i', "i" }, + {0X4B02F047, &WrapI_I, "sceImposeGetParam", 'i', "i" }, + {0XD1E9019F, &WrapI_II, "sceImposeSetParam", 'i', "ii"}, + {0X0BBCA0BF, &WrapI_V, "sceImposeChanges", 'i', "" }, }; void Register_sceImpose_driver() { diff --git a/Core/HLE/sceKernelHeap.cpp b/Core/HLE/sceKernelHeap.cpp index 7b382124e9..639c1e01f4 100644 --- a/Core/HLE/sceKernelHeap.cpp +++ b/Core/HLE/sceKernelHeap.cpp @@ -202,6 +202,12 @@ const HLEFunction SysMemForKernel[] = { { 0XEB7A74DB, &WrapI_IUU, "sceKernelAllocHeapMemoryWithOption", 'i', "ixp" , HLE_KERNEL_SYSCALL }, { 0x6373995d, &WrapI_V, "sceKernelGetModel", 'i', "", HLE_KERNEL_SYSCALL}, // 220 { 0x07C586A1, &WrapI_V, "sceKernelGetModel", 'i', "", HLE_KERNEL_SYSCALL }, // 220 + // The 5.xx NID for the same call. vshbridge wraps it in a user-level check and re-exports it, + // and 6.61's vshbridge wraps sceKernelGetModel with an identical body - that pairing is how + // this NID was identified. Unresolved, the 5.50 VSH read a garbage model number and went + // looking for PSP-3000 resources on a dump that is a 1000. + // NOTE: new entries go at the end - the syscall opcode in a savestate is an index into this array. + { 0xDA07DC6E, &WrapI_V, "sceKernelGetModel", 'i', "", HLE_KERNEL_SYSCALL }, }; void Register_SysMemForKernel() { diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 44c7030e20..ccc6c7116d 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -3196,6 +3196,10 @@ const HLEFunction ModuleMgrForKernel[] = { // module id 0 back and the sceKernelStartModule after it failed with UNKNOWN_MODULE. // NOTE: new entries go at the end - the syscall opcode in a savestate is an index into this array. {0xA4370E7C, &WrapU_CUU, "sceKernelLoadModuleVSH", 'x', "sxx", HLE_KERNEL_SYSCALL }, + // And the 5.x NID for it, confirmed the same way: in 5.50's modulemgr.prx this NID has the + // identical callee set to 6.61's 0xD5DDAB1F. Without it 5.50's vshbridge couldn't load the + // XMB plugins (opening_plugin, impose_plugin, ...) and the VSH stopped at a black screen. + {0xCCDE84A8, &WrapU_CUU, "sceKernelLoadModuleVSH", 'x', "sxx", HLE_KERNEL_SYSCALL }, }; void Register_ModuleMgrForUser() {