Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions core/libs/prx/libSceNpAuth/Export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ int APS5_VABI sceNpAuthDeleteRequest(int req_id) {
return 0;
}

int APS5_VABI sceNpAuthGetAuthorizedAppCode() {
NotImplemented_nid_no_patch(__func__);
return 0;
}

int APS5_VABI sceNpAuthGetAuthorizationCodeV3(int req_id, const void* param, void* auth_code, int* issuer_id) {
(void)req_id;
(void)issuer_id;
Expand Down
14 changes: 14 additions & 0 deletions core/libs/prx/libSceNpAuthAuthorizedAppDialog/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
add_library(libSceNpAuthAuthorizedAppDialog SHARED EXCLUDE_FROM_ALL Export.cpp)
target_include_directories(libSceNpAuthAuthorizedAppDialog PRIVATE ${LIBS_INCLUDE_DIR})
configure_windows_unwind(libSceNpAuthAuthorizedAppDialog)

if(BUILD_TESTING)
add_test_executable(guest_np_auth_authorized_app_dialog_tests ${LIBS_INCLUDE_DIR}/tests/GuestNpAuthAuthorizedAppDialog.cpp)
target_include_directories(guest_np_auth_authorized_app_dialog_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_np_auth_authorized_app_dialog_tests PRIVATE libSceNpAuthAuthorizedAppDialog)
add_test(NAME guest_np_auth_authorized_app_dialog COMMAND guest_np_auth_authorized_app_dialog_tests)
if(WIN32)
set_tests_properties(guest_np_auth_authorized_app_dialog PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNpAuthAuthorizedAppDialog>")
endif()
endif()
70 changes: 70 additions & 0 deletions core/libs/prx/libSceNpAuthAuthorizedAppDialog/Export.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include <atomic>
#include <cstdint>
#include <cstddef>
#include <cstring>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"

namespace {

constexpr int COMMON_DIALOG_STATUS_NONE = 0;
constexpr int COMMON_DIALOG_STATUS_INITIALIZED = 1;
constexpr int COMMON_DIALOG_STATUS_RUNNING = 2;
constexpr int COMMON_DIALOG_STATUS_FINISHED = 3;
constexpr int COMMON_DIALOG_ERROR_NOT_INITIALIZED = static_cast<int>(0x80B80003u);
constexpr int COMMON_DIALOG_ERROR_ALREADY_INITIALIZED = static_cast<int>(0x80B80004u);
constexpr int COMMON_DIALOG_ERROR_NOT_FINISHED = static_cast<int>(0x80B80005u);
constexpr int COMMON_DIALOG_ERROR_BUSY = static_cast<int>(0x80B80007u);
constexpr int COMMON_DIALOG_ERROR_ARG_NULL = static_cast<int>(0x80B8000Du);
constexpr int COMMON_DIALOG_RESULT_USER_CANCELED = 1;

std::atomic<int> g_status{COMMON_DIALOG_STATUS_NONE};

}

extern "C" {

int APS5_VABI sceNpAuthAuthorizedAppDialogInitialize(void) {
int expected = COMMON_DIALOG_STATUS_NONE;
if (!g_status.compare_exchange_strong(expected, COMMON_DIALOG_STATUS_INITIALIZED)) return COMMON_DIALOG_ERROR_ALREADY_INITIALIZED;
return 0;
}

int APS5_VABI sceNpAuthAuthorizedAppDialogOpen(const void* param) {
const int status = g_status.load();
if (status == COMMON_DIALOG_STATUS_NONE) return COMMON_DIALOG_ERROR_NOT_INITIALIZED;
if (status == COMMON_DIALOG_STATUS_RUNNING) return COMMON_DIALOG_ERROR_BUSY;
if (param == nullptr) return COMMON_DIALOG_ERROR_ARG_NULL;
g_status = COMMON_DIALOG_STATUS_FINISHED;
return 0;
}

int APS5_VABI sceNpAuthAuthorizedAppDialogUpdateStatus(void) {
return g_status.load();
}

int APS5_VABI sceNpAuthAuthorizedAppDialogGetStatus(void) {
return g_status.load();
}

int APS5_VABI sceNpAuthAuthorizedAppDialogGetResult(void* result) {
const int status = g_status.load();
if (status == COMMON_DIALOG_STATUS_NONE) return COMMON_DIALOG_ERROR_NOT_INITIALIZED;
if (result == nullptr) return COMMON_DIALOG_ERROR_ARG_NULL;
if (status != COMMON_DIALOG_STATUS_FINISHED) return COMMON_DIALOG_ERROR_NOT_FINISHED;
const std::int32_t canceled = COMMON_DIALOG_RESULT_USER_CANCELED;
std::memcpy(result, &canceled, sizeof(canceled));
return 0;
}

int APS5_VABI sceNpAuthAuthorizedAppDialogClose(void) {
if (g_status.load() == COMMON_DIALOG_STATUS_NONE) return COMMON_DIALOG_ERROR_NOT_INITIALIZED;
return 0;
}

int APS5_VABI sceNpAuthAuthorizedAppDialogTerminate(void) {
if (g_status.exchange(COMMON_DIALOG_STATUS_NONE) == COMMON_DIALOG_STATUS_NONE) return COMMON_DIALOG_ERROR_NOT_INITIALIZED;
return 0;
}

}
7 changes: 7 additions & 0 deletions core/libs/prx/libSceSaveData.native/Export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -808,4 +808,11 @@ int APS5_VABI sceSaveDataDirNameSearch2() {
NotImplemented_nid_no_patch(__func__);
return 0;
}

APS5_EXPORT("RvID8BVeg+g", sceSaveDataUnknown_RvID8BVeg);
int APS5_VABI sceSaveDataUnknown_RvID8BVeg() {
NotImplemented_nid_no_patch("RvID8BVeg+g");
return 0;
}

}
62 changes: 62 additions & 0 deletions core/libs/tests/GuestNpAuthAuthorizedAppDialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "prx/libc/include/general/VabiMacros.hpp"
#include <cstdint>
#include <cstdlib>

extern "C" {
int APS5_VABI sceNpAuthAuthorizedAppDialogInitialize(void);
int APS5_VABI sceNpAuthAuthorizedAppDialogOpen(const void* param);
int APS5_VABI sceNpAuthAuthorizedAppDialogUpdateStatus(void);
int APS5_VABI sceNpAuthAuthorizedAppDialogGetStatus(void);
int APS5_VABI sceNpAuthAuthorizedAppDialogGetResult(void* result);
int APS5_VABI sceNpAuthAuthorizedAppDialogClose(void);
int APS5_VABI sceNpAuthAuthorizedAppDialogTerminate(void);
}

namespace {

void Require(bool value) { if (!value) std::abort(); }

constexpr int kStatusNone = 0;
constexpr int kStatusInitialized = 1;
constexpr int kStatusFinished = 3;
constexpr int kErrNotInitialized = static_cast<int>(0x80B80003);
constexpr int kErrAlreadyInitialized = static_cast<int>(0x80B80004);
constexpr int kErrNotFinished = static_cast<int>(0x80B80005);
constexpr int kErrArgNull = static_cast<int>(0x80B8000D);
constexpr int kResultUserCanceled = 1;

}

int main() {
std::int64_t param = 0;
std::int32_t result[2] = {-1, -1};

Require(sceNpAuthAuthorizedAppDialogGetStatus() == kStatusNone);
Require(sceNpAuthAuthorizedAppDialogTerminate() == kErrNotInitialized);
Require(sceNpAuthAuthorizedAppDialogClose() == kErrNotInitialized);
Require(sceNpAuthAuthorizedAppDialogOpen(&param) == kErrNotInitialized);
Require(sceNpAuthAuthorizedAppDialogGetResult(result) == kErrNotInitialized);

Require(sceNpAuthAuthorizedAppDialogInitialize() == 0);
Require(sceNpAuthAuthorizedAppDialogInitialize() == kErrAlreadyInitialized);
Require(sceNpAuthAuthorizedAppDialogGetStatus() == kStatusInitialized);
Require(sceNpAuthAuthorizedAppDialogUpdateStatus() == kStatusInitialized);

Require(sceNpAuthAuthorizedAppDialogOpen(nullptr) == kErrArgNull);
Require(sceNpAuthAuthorizedAppDialogGetResult(result) == kErrNotFinished);

Require(sceNpAuthAuthorizedAppDialogOpen(&param) == 0);
Require(sceNpAuthAuthorizedAppDialogUpdateStatus() == kStatusFinished);
Require(sceNpAuthAuthorizedAppDialogGetStatus() == kStatusFinished);

Require(sceNpAuthAuthorizedAppDialogGetResult(nullptr) == kErrArgNull);
Require(sceNpAuthAuthorizedAppDialogGetResult(result) == 0);
Require(result[0] == kResultUserCanceled);
Require(result[1] == -1);

Require(sceNpAuthAuthorizedAppDialogClose() == 0);
Require(sceNpAuthAuthorizedAppDialogTerminate() == 0);
Require(sceNpAuthAuthorizedAppDialogTerminate() == kErrNotInitialized);
Require(sceNpAuthAuthorizedAppDialogGetStatus() == kStatusNone);
return 0;
}
3 changes: 3 additions & 0 deletions docs/dev/TechnicalDebt.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Throughout the project, every function at every stage either **does exactly what
- [libSceErrorDialog](../../core/libs/prx/libSceErrorDialog/Export.cpp) - the error dialog runs the state machine but shows nothing; the error code passed to `sceErrorDialogOpen` is only logged
- [libSceLoginDialog](../../core/libs/prx/libSceLoginDialog/Export.cpp) - the login dialog runs the common-dialog state machine but shows nothing and reports the user as having cancelled
- [libSceCdlgG2P](../../core/libs/prx/libSceCdlgG2P/Export.cpp) - the G2P dialog runs the common-dialog state machine but shows nothing and reports the user as having cancelled. The signatures (`Open` and `GetResult` take a pointer, the others none) and the leading `int32` result are assumed from the other common dialogs, not verified for G2P; PPSA01289 imports it
- [libSceNpAuthAuthorizedAppDialog](../../core/libs/prx/libSceNpAuthAuthorizedAppDialog/Export.cpp) - the authorized-app dialog runs the common-dialog state machine but shows nothing and reports the user as having cancelled, as there is no PSN sign-in to authorize an app against. The signatures follow the other common dialogs (`Open` takes a parameter block, `GetResult` writes a 32-bit result); Minecraft (PPSA17221) imports the seven functions and fails to load without them.
- [libSceVrSetupDialog](../../core/libs/prx/libSceVrSetupDialog/Export.cpp) - the VR setup dialog runs the common-dialog state machine but shows nothing and reports the user as having cancelled, as no headset is supported (see libSceHmd2). The signatures are assumed from the other common dialogs; PPSA12544 imports it
- [scePthreadMutexattrSetprotocol](../../core/libs/prx/libkernel/Pthread/src/Mutex.cpp) (libkernel) - accepts 0 to 2 as a PS5 (firmware 13.60) does and returns `EINVAL` otherwise, but the protocol is not stored or applied: priority inheritance and protection are not modelled. On the console a null or uninitialized mutex attribute returns `EINVAL` from the SCE attribute calls, `scePthreadMutexInit` takes an uninitialized attribute as the default one, and a destroyed mutex returns `EINVAL` from `scePthreadMutexDestroy`; a null mutex pointer crashed the payload and still throws
- [libSceHmd](../../core/libs/prx/libSceHmd/Export.cpp) implements only the disconnected-headset path: initialization succeeds, device queries report `NotDetected`, and opening a device returns `DeviceDisconnected`. Headset support, tracking, rendering and additional HMD exports are not implemented; SDK-level ABI compatibility and in-game behaviour remain unverified.
Expand Down Expand Up @@ -59,6 +60,8 @@ Throughout the project, every function at every stage either **does exactly what
- [nearbyintf](../../core/libs/prx/libc/src/Math.cpp) (libc, NID `c+4r-T-tEIc`) uses the host rounding mode, not the console's; console rounding mode state remains unverified.
- [_Thrd_sleep](../../core/libs/prx/libc/src/Threads.cpp) (libc, NID `jfRI3snge3o`) follows the Dinkumware threads library shipped with [Visual C++ 2013](https://github.com/adityaramesh/concurrency_runtime/tree/master/VS2013_SP2/crt/src/thr) (`xtime.c`) and C11 Annex K, without console verification. It reads a 16-byte xtime (64-bit seconds and nanoseconds) on the guest `CLOCK_REALTIME`, normalizes the nanoseconds and sleeps through `nanosleep`, retrying on `EINTR`, so it is a cancellation point; a null xtime or one whose normalization overflows throws. The console's `_Thrd_sleep` (disassembled from a title's `libc.prx`) also takes an optional `xtime*` of remaining time and returns `int`; here the sleep is never cut short, so it returns 0 and leaves the remaining time untouched.
- [sceCoredumpGetThreadContextInfo](../../core/libs/prx/libkernel/System/src/Coredump.cpp) (libkernel, NID `ShChva57wIM`) - declared as a throwing stub. The pointer and size arguments and integer return type follow [SharpProspero's PS5 bindings](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/Kernel/KernelSystem.cs). The context structure and console behavior are unverified; the stub does not read or write caller memory. PPSA01736 imports it
- [sceNpAuthGetAuthorizedAppCode](../../core/libs/prx/libSceNpAuth/Export.cpp) (libSceNpAuth) - declared without parameters as a throwing stub; Minecraft (PPSA17221) imports it and fails to load without it. The request parameter and code output are not known, and there is no PSN sign-in for it to succeed against.
- [sceSaveDataUnknown_RvID8BVeg](../../core/libs/prx/libSceSaveData.native/Export.cpp) (libSceSaveData.native, NID `RvID8BVeg+g`) - declared without parameters as a throwing stub; Minecraft (PPSA17221) imports it beside `sceSaveDataTransferringMountPs4` and `sceSaveDataDirNameSearchPs4` and fails to load without it. No name in aerolib or among the PS4-migration variants tried with `tools/nid_names.py` hashes to it.
- [sceNpWebApi2PushEventAbortHandle](../../core/libs/prx/libSceNpWebApi2/Export.cpp) (libSceNpWebApi2, NID `1OLgvahaSco`) is a throwing stub. The two signed 32-bit handle arguments and return type follow [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/443f022450f6857256e780daa3d5a14029a748f7/src/core/libraries/np/np_web_api2/np_web_api2.cpp) (PS4); the PS5 signature and abort behavior are unverified. PPSA01736 imports it.
- [sceNpGetSandboxInfo](../../core/libs/prx/libSceNpManager/Export.cpp) (libSceNpManager, NID `ZVZ++68nNI8`) - the name hashes to the imported NID (found with nidhunt, confirmed with `tools/nid_names.py`). STAR WARS: Galactic Racer (PPSA28416) imports it; its OnlineSubsystemPS5 calls it with one pointer to a 0x50-byte stack buffer and reads the buffer as a string (discussions/3086). The returned string, the exact parameter struct and console errors are unknown, so every call throws without reading or writing caller memory. A working implementation belongs with that title's bring-up.
- [sceKernelGetSystemSwVersion](../../core/libs/prx/libkernel/System/src/SystemConfiguration.cpp) (libkernel) reports baseline system software version `0x01000000` ("01.000.000") for ProsperoStore (PPSA99000). The 0x28-byte layout (`uint64_t size` at 0, `versionString` at 8 and `version` at 0x24) matches [ProsperoStore's caller](https://github.com/blackbearreloaded/ProsperoStore/blob/20584011/src/diag/trace.cpp#L20-L26), [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/811bfcd7d1/src/core/libraries/kernel/kernel.h#L45-L49), [fpPS4](https://github.com/red-prig/fpPS4/blob/04cefd43e6/kernel/ps4_libkernel.pas#L502-L506) and [OpenOrbis](https://github.com/OpenOrbis/OpenOrbis-PS4-Toolchain/blob/0a1aaf9dd4/include/orbis/_types/kernel.h#L256-L260). These sources support the structure layout, but not the reported version value: the console firmware version remains unverified. The checks are unverified too: a null pointer returns `SCE_KERNEL_ERROR_EFAULT` and a `size` other than 0x28 returns `SCE_KERNEL_ERROR_EINVAL`, while shadPS4 returns success for null and never reads `size`.
Expand Down
Loading