fix(libSceSystemService): declare the PsmKit local process exports

Forever Launcher (PPSA99030) imports sceSystemServiceAddLocalProcessForPsmKit
and sceSystemServiceKillLocalProcessForPsmKit and stops at load without
them. AnyPS5 runs one process and starts no other, so both throw without
reading their arguments. The parameters follow the title's own firmware
probes (path, argv and a 0x90-byte parameter block; the kill takes the
returned handle), and the unknown results are recorded as technical debt.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
milescovielloandClaude Opus 5.5 committed 2026-10-17 20:43:32 +00:00
1 parent 82cad6b5fc
commit f69e6c0934
3 files changed
+30

No files matched your search

@@ -390,6 +390,16 @@ int APS5_VABI sceSystemServiceOpenTournamentOccurrence(void) {
return 0;
}
int APS5_VABI sceSystemServiceAddLocalProcessForPsmKit(const char*, const char* const*, const void*) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceSystemServiceKillLocalProcessForPsmKit(int) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceSystemServiceReenableMusicPlayer(void) {
return SYSTEM_SERVICE_OK;
}
+19
View File
@@ -8,6 +8,8 @@
extern "C" int APS5_VABI sceSystemServiceGetHdrToneMapLuminance(SystemServiceHdrToneMapLuminance* luminance);
extern "C" int APS5_VABI sceSystemServiceParamGetString(int paramId, char* buf, std::size_t bufSize);
extern "C" int APS5_VABI sceSystemServiceLaunchApp(const char* titleId, const char* const* arguments, const void* param);
extern "C" int APS5_VABI sceSystemServiceAddLocalProcessForPsmKit(const char* path, const char* const* arguments, const void* param);
extern "C" int APS5_VABI sceSystemServiceKillLocalProcessForPsmKit(int handle);
namespace {
@@ -24,6 +26,16 @@ bool ParamGetStringThrows(int paramId, char* buf, std::size_t bufSize) {
return false;
}
template<typename TCall>
bool Throws(TCall call) {
try {
static_cast<void>(call());
} catch (const std::runtime_error&) {
return true;
}
return false;
}
bool LaunchAppThrows(const char* titleId, const char* const* arguments, const void* param) {
try {
static_cast<void>(sceSystemServiceLaunchApp(titleId, arguments, param));
@@ -76,6 +88,13 @@ int main() {
Require(LaunchAppThrows("PPSA99110", launchArguments, launchParam));
for (unsigned char byte : launchParam) Require(byte == 0x5a);
Require(std::strcmp(launchArguments[0], "--backup") == 0 && launchArguments[1] == nullptr);
const char* childArguments[] = {"/app0/child.bin", nullptr};
unsigned char processParam[0x90];
std::memset(processParam, 0x5a, sizeof(processParam));
Require(Throws([&] { return sceSystemServiceAddLocalProcessForPsmKit("/app0/child.bin", childArguments, processParam); }));
for (unsigned char byte : processParam) Require(byte == 0x5a);
Require(Throws([] { return sceSystemServiceAddLocalProcessForPsmKit(nullptr, nullptr, nullptr); }));
Require(Throws([] { return sceSystemServiceKillLocalProcessForPsmKit(1); }));
Require(sceSystemServiceGetHdrToneMapLuminance(nullptr) == SYSTEM_SERVICE_ERROR_PARAMETER);
SystemServiceHdrToneMapLuminance luminance{-1.0f, -1.0f, -1.0f};
Require(sceSystemServiceGetHdrToneMapLuminance(&luminance) == SYSTEM_SERVICE_OK);
+1
View File
@@ -9,6 +9,7 @@
### Unknown function info
- [sceSystemServiceAddLocalProcessForPsmKit, sceSystemServiceKillLocalProcessForPsmKit](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - AnyPS5 runs one process and starts or stops no other, so both throw without reading their arguments. The parameters follow Forever Launcher's own firmware 5.50 probes (`ps5/probes/localproc` in [bizkut/ps5-forever](https://github.com/bizkut/ps5-forever)): a path, a null-terminated argv and a 0x90-byte parameter block in, a handle out; the kill takes that handle. Their results on the console are unknown. Forever Launcher (PPSA99030) imports both and stops at load without them.
- [sceSystemServiceLaunchApp](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - AnyPS5 runs one title and cannot start another, so every call throws without reading its arguments. The (title ID, null-terminated argv, launch parameters) signature follows [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/SystemService/SystemService.cs#L141-L148), whose `AppLauncher` Prospero Explorer (PPSA99109) and Prospero Multi Tools (PPSA99110) import it through and which passes a 0x20-byte launch context or null; the console's argument checks and errors are unknown
- [sceSystemServiceLaunchWebBrowser](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - the console's error for an unavailable web browser is unknown; it returns the kernel's `EOPNOTSUPP` (0x8002002D) for any arguments. The (uri, param) signature follows [RommPS](https://github.com/s0liton/RommPS/blob/754d4d60f25938a5136b9e2efcd074313c4386c5/platform/ps5/app/rommps/examples/rommps/kit/credits.cpp#L86-L95), which passes a URL and a null param and only tests the result for zero; the param layout and the console's argument checks are unknown
- [sceSystemServiceParamGetString](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - the system name (parameter 6) is the fixed `PS5`, not the console's name; other parameters and buffers of 1 to 64 bytes throw. PPSA26344 at `0xA87935` passes parameter 6 with a 65-byte buffer