mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-29 12:15:39 +00:00
feat(libSceSystemService): answer the running title's app ID lookups
sceLncUtilGetAppId and sceLncUtilIsAppLaunched accept the running title's ID as sceSystemServiceGetAppId does, and sceLncUtilGetAppIdOfRunningBigApp returns what sceSystemServiceGetAppIdOfRunningBigApp returns. Both big-app lists write the running title's app ID as their only entry, because AnyPS5 runs one title. Another title ID, a null pointer and a list capacity of 0 still throw.
This commit is contained in:
1 parent
38d463a6cf
commit
695041093b
5 files changed
+91
-33
No files matched your search
@@ -260,6 +260,28 @@ void CopyRunningTitleId(const std::string& caller, bool running, char* destinati
|
||||
std::memcpy(destination, titleId.c_str(), titleId.size() + 1);
|
||||
}
|
||||
|
||||
int RunningAppId(const std::string& caller, const char* titleId) {
|
||||
if (titleId == nullptr) NotImplemented_nid_no_patch((caller + ": null title ID").c_str());
|
||||
if (RunningTitleId() != titleId) NotImplemented_nid_no_patch((caller + ": title other than the running title").c_str());
|
||||
return SYSTEM_SERVICE_RUNNING_APP_ID;
|
||||
}
|
||||
|
||||
template<typename TValue>
|
||||
int AnswerForRunningApp(const std::string& caller, std::int32_t appId, TValue* destination, TValue value) {
|
||||
if (appId != SYSTEM_SERVICE_RUNNING_APP_ID) NotImplemented_nid_no_patch((caller + ": application other than the running title").c_str());
|
||||
if (destination == nullptr) NotImplemented_nid_no_patch((caller + ": null output").c_str());
|
||||
*destination = value;
|
||||
return SYSTEM_SERVICE_OK;
|
||||
}
|
||||
|
||||
int ListRunningBigApp(const std::string& caller, std::int32_t* appIds, std::uint32_t capacity, std::uint32_t* count) {
|
||||
if (appIds == nullptr || count == nullptr) NotImplemented_nid_no_patch((caller + ": null list or count").c_str());
|
||||
if (capacity == 0) NotImplemented_nid_no_patch((caller + ": a list with no room for the running title").c_str());
|
||||
appIds[0] = SYSTEM_SERVICE_RUNNING_APP_ID;
|
||||
*count = 1;
|
||||
return SYSTEM_SERVICE_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
@@ -455,13 +477,7 @@ int APS5_VABI sceSystemServiceGetAppIdOfRunningBigApp(void) {
|
||||
}
|
||||
|
||||
int APS5_VABI sceSystemServiceGetAppId(const char* titleId) {
|
||||
if (titleId == nullptr) {
|
||||
NotImplemented_nid_no_patch("sceSystemServiceGetAppId: null title ID");
|
||||
}
|
||||
if (RunningTitleId() != titleId) {
|
||||
NotImplemented_nid_no_patch("sceSystemServiceGetAppId: title other than the running title");
|
||||
}
|
||||
return SYSTEM_SERVICE_RUNNING_APP_ID;
|
||||
return RunningAppId("sceSystemServiceGetAppId", titleId);
|
||||
}
|
||||
|
||||
int APS5_VABI sceSystemServiceGetAppTitleId(int appId, char* titleId) {
|
||||
@@ -474,6 +490,26 @@ int APS5_VABI sceLncUtilGetAppTitleId(std::int32_t appId, char* titleId) {
|
||||
return SYSTEM_SERVICE_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI sceLncUtilGetAppId(const char* titleId) {
|
||||
return RunningAppId("sceLncUtilGetAppId", titleId);
|
||||
}
|
||||
|
||||
int APS5_VABI sceLncUtilIsAppLaunched(const char* titleId, bool* launched) {
|
||||
return AnswerForRunningApp("sceLncUtilIsAppLaunched", RunningAppId("sceLncUtilIsAppLaunched", titleId), launched, true);
|
||||
}
|
||||
|
||||
int APS5_VABI sceLncUtilGetAppIdOfRunningBigApp() {
|
||||
return sceSystemServiceGetAppIdOfRunningBigApp();
|
||||
}
|
||||
|
||||
int APS5_VABI sceLncUtilGetAppIdListOfBigApp(std::int32_t* appIds, std::uint32_t capacity, std::uint32_t* count) {
|
||||
return ListRunningBigApp("sceLncUtilGetAppIdListOfBigApp", appIds, capacity, count);
|
||||
}
|
||||
|
||||
int APS5_VABI sceSystemServiceGetAppIdListOfBigApp(std::int32_t* appIds, std::uint32_t capacity, std::uint32_t* count) {
|
||||
return ListRunningBigApp("sceSystemServiceGetAppIdListOfBigApp", appIds, capacity, count);
|
||||
}
|
||||
|
||||
int APS5_VABI sceSystemServiceKillApp(int appId, int how, int reason, int coreDump) {
|
||||
if (appId != SYSTEM_SERVICE_RUNNING_APP_ID) {
|
||||
NotImplemented_nid_no_patch("sceSystemServiceKillApp: application other than the running title");
|
||||
|
||||
@@ -234,21 +234,6 @@ int APS5_VABI sceLncUtilGetAppFocusedAppStatus(LncAppStatus* status) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceLncUtilGetAppId(const char* titleId) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceLncUtilGetAppIdListOfBigApp(std::int32_t* appIds, std::uint32_t capacity, std::uint32_t* count) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceLncUtilGetAppIdOfRunningBigApp() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceLncUtilGetAppLaunchedUser(std::int32_t appId, std::int32_t* userId) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
@@ -344,11 +329,6 @@ int APS5_VABI sceLncUtilIsActiveCdlg(bool* active) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceLncUtilIsAppLaunched(const char* titleId, bool* launched) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceLncUtilIsAppSuspended(std::int32_t appId, bool* suspended) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
@@ -1835,11 +1815,6 @@ int APS5_VABI sceSystemServiceGetAppFocusedAppStatus(SystemServiceAppStatus* sta
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceSystemServiceGetAppIdListOfBigApp(std::int32_t* appIds, std::uint32_t capacity, std::uint32_t* count) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceSystemServiceGetAppLaunchedUser(std::int32_t appId, std::int32_t* userId) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "SceTypes.hpp"
|
||||
#include "prx/libSceSystemService/SystemService.hpp"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
@@ -37,6 +38,31 @@ bool LaunchAppThrows(const char* titleId, const char* const* arguments, const vo
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename TList>
|
||||
void TestBigAppList(TList list) {
|
||||
const int runningAppId = sceSystemServiceGetAppIdOfRunningBigApp();
|
||||
constexpr std::int32_t Sentinel = 0x5a5a5a5a;
|
||||
for (const std::uint32_t capacity : {1u, 4u}) {
|
||||
std::int32_t appIds[4] = {Sentinel, Sentinel, Sentinel, Sentinel};
|
||||
std::uint32_t count = 0xdeadbeefu;
|
||||
Require(list(appIds, capacity, &count) == SYSTEM_SERVICE_OK);
|
||||
Require(count == 1 && appIds[0] == runningAppId);
|
||||
for (std::size_t index = 1; index < 4; ++index) Require(appIds[index] == Sentinel);
|
||||
}
|
||||
std::int32_t appIds[2] = {Sentinel, Sentinel};
|
||||
std::uint32_t count = 0xdeadbeefu;
|
||||
Require(Throws([&] { return list(appIds, 0, &count); }));
|
||||
Require(Throws([&] { return list(nullptr, 2, &count); }));
|
||||
Require(Throws([&] { return list(appIds, 2, nullptr); }));
|
||||
Require(appIds[0] == Sentinel && appIds[1] == Sentinel && count == 0xdeadbeefu);
|
||||
}
|
||||
|
||||
void TestRunningBigApp() {
|
||||
Require(sceLncUtilGetAppIdOfRunningBigApp() == sceSystemServiceGetAppIdOfRunningBigApp());
|
||||
TestBigAppList(sceLncUtilGetAppIdListOfBigApp);
|
||||
TestBigAppList(sceSystemServiceGetAppIdListOfBigApp);
|
||||
}
|
||||
|
||||
void TestPlayerDialogParam() {
|
||||
alignas(8) unsigned char buffer[0x100];
|
||||
std::memset(buffer, 0xab, sizeof(buffer));
|
||||
@@ -150,5 +176,6 @@ int main() {
|
||||
SystemServiceEvent event;
|
||||
event.event_type = 7;
|
||||
Require(sceSystemServiceReceiveEvent(&event) == SYSTEM_SERVICE_ERROR_NO_EVENT);
|
||||
TestRunningBigApp();
|
||||
TestPlayerDialogParam();
|
||||
}
|
||||
@@ -42,7 +42,19 @@ bool Throws(TCall call) {
|
||||
}
|
||||
|
||||
bool GetAppIdThrows(const char* titleId) {
|
||||
return Throws([&] { static_cast<void>(sceSystemServiceGetAppId(titleId)); });
|
||||
return Throws([&] { static_cast<void>(sceSystemServiceGetAppId(titleId)); }) && Throws([&] { static_cast<void>(sceLncUtilGetAppId(titleId)); });
|
||||
}
|
||||
|
||||
bool IsAppLaunchedThrows(const char* titleId) {
|
||||
bool launched = false;
|
||||
return Throws([&] { static_cast<void>(sceLncUtilIsAppLaunched(titleId, &launched)); }) && !launched;
|
||||
}
|
||||
|
||||
void CheckRunningTitleLookups(const char* titleId, int runningAppId) {
|
||||
Require(sceLncUtilGetAppId(titleId) == runningAppId);
|
||||
bool launched = false;
|
||||
Require(sceLncUtilIsAppLaunched(titleId, &launched) == 0 && launched);
|
||||
Require(Throws([&] { static_cast<void>(sceLncUtilIsAppLaunched(titleId, nullptr)); }));
|
||||
}
|
||||
|
||||
bool GetAppTitleIdThrows(int appId, GuardedBuffer& buffer) {
|
||||
@@ -70,6 +82,7 @@ void CheckNullBuffers(int runningAppId) {
|
||||
Require(Throws([&] { static_cast<void>(sceLncUtilGetAppTitleId(runningAppId, nullptr)); }));
|
||||
Require(Throws([&] { static_cast<void>(sceSystemServiceGetAppTitleId(runningAppId + 1, nullptr)); }));
|
||||
Require(GetAppIdThrows(nullptr));
|
||||
Require(IsAppLaunchedThrows(nullptr));
|
||||
}
|
||||
|
||||
void CheckKnownTitle(int runningAppId) {
|
||||
@@ -80,13 +93,16 @@ void CheckKnownTitle(int runningAppId) {
|
||||
const char* const otherTitles[] = {"PPSA00001", "PPSA00010", "ppsa00000", "PPSA0000", "PPSA000000", "PPSA00000 ", " PPSA00000", "CUSA00000", ""};
|
||||
for (const char* other : otherTitles) {
|
||||
Require(GetAppIdThrows(other));
|
||||
Require(IsAppLaunchedThrows(other));
|
||||
}
|
||||
CheckRunningTitleLookups("PPSA00000", runningAppId);
|
||||
|
||||
GuardedBuffer buffer;
|
||||
Require(sceSystemServiceGetAppTitleId(runningAppId, buffer.bytes) == 0);
|
||||
Require(std::memcmp(buffer.bytes, "PPSA00000", titleId.size() + 1) == 0);
|
||||
Require(buffer.GuardIntact());
|
||||
Require(sceSystemServiceGetAppId(buffer.bytes) == runningAppId);
|
||||
Require(sceLncUtilGetAppId(buffer.bytes) == runningAppId);
|
||||
|
||||
GuardedBuffer lncBuffer;
|
||||
Require(sceLncUtilGetAppTitleId(runningAppId, lncBuffer.bytes) == 0);
|
||||
@@ -104,8 +120,10 @@ void CheckKnownTitle(int runningAppId) {
|
||||
|
||||
void CheckLongTitle(int runningAppId) {
|
||||
Require(sceSystemServiceGetAppId("PPSA000000") == runningAppId);
|
||||
CheckRunningTitleLookups("PPSA000000", runningAppId);
|
||||
Require(GetAppIdThrows("PPSA00000"));
|
||||
Require(GetAppIdThrows("PPSA0000000"));
|
||||
Require(IsAppLaunchedThrows("PPSA00000"));
|
||||
GuardedBuffer buffer;
|
||||
Require(GetAppTitleIdThrows(runningAppId, buffer));
|
||||
Require(LncGetAppTitleIdThrows(static_cast<std::uint32_t>(runningAppId), buffer));
|
||||
@@ -114,6 +132,7 @@ void CheckLongTitle(int runningAppId) {
|
||||
void CheckMissingMetadata(int runningAppId) {
|
||||
Require(GetAppIdThrows("PPSA00000"));
|
||||
Require(GetAppIdThrows(nullptr));
|
||||
Require(IsAppLaunchedThrows("PPSA00000"));
|
||||
GuardedBuffer buffer;
|
||||
Require(GetAppTitleIdThrows(runningAppId, buffer));
|
||||
Require(LncGetAppTitleIdThrows(static_cast<std::uint32_t>(runningAppId), buffer));
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
- [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.
|
||||
- [sceSystemServiceGetAppId, sceSystemServiceGetAppTitleId, sceLncUtilGetAppTitleId](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - the console's results for a title ID or app ID other than the running title are unknown, and so are its errors for null pointers, so those calls throw. `sceSystemServiceGetAppId` compares the title ID exactly with the one in `param.json` or `param.sfo`. The title ID buffer is 10 bytes, so a running title ID of 10 or more characters throws too. The signatures follow [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/SystemService/SystemService.cs#L236-L260), except that `sceLncUtilGetAppTitleId` returns an `int`, as declared in the pending exports, and 0 on success like `sceSystemServiceGetAppTitleId`; SharpProspero names `ErrorNoAppInfo` (0x80A10009) only for `sceSystemServiceGetAppFocusedAppStatus`.
|
||||
- [sceLncUtilGetAppId, sceLncUtilIsAppLaunched, sceLncUtilGetAppIdListOfBigApp, sceSystemServiceGetAppIdListOfBigApp](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - only the running title answers. `sceLncUtilGetAppId` returns its app ID as `sceSystemServiceGetAppId` does, `sceLncUtilIsAppLaunched` reports it launched, and both big-app lists write its app ID as their only entry with a count of 1, because AnyPS5 runs one title and cannot start another. Another title ID, a null pointer and a list capacity of 0 throw: whether the console reports another installed title as not launched, and its errors for these arguments, are unknown. The signatures are the ones the pending exports recovered
|
||||
- [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): the native export takes one URI argument. Null input, the 6015-byte length limit and supported scheme checks are recovered. The host still returns kernel `EOPNOTSUPP` for valid input; a missing browser service's native error is unresolved.
|
||||
- [sceSystemServiceParamGetString](../../../core/libs/prx/libSceSystemService/Export.cpp) (libSceSystemService) - the system name (parameter 6) is the fixed `PS5`, not the console's name. As in a payload process on a PS5 (firmware 13.60), the name is written NUL-padded to the whole buffer, and a buffer under 65 bytes, a null buffer or any other parameter returns `SYSTEM_SERVICE_ERROR_PARAMETER` without writing. Parameters 0 to 40, 100 to 110, 1000 to 1010, -1 and `INT_MAX` were tried there; the others are assumed to fail the same way. PPSA26344 at `0xA87935` passes parameter 6 with a 65-byte buffer
|
||||
|
||||
Reference in new issue
Block a user