From a0e7f7fb65bc02a93738381eebe788161bda9fab Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Sun, 5 Oct 2025 19:25:46 -0500 Subject: [PATCH] NpManager: Implement more request-related behavior (#3703) * Implement sceNpCheckPlus * Rework request storage We'll need to store more data to "fake" async requests. * sceNpAbortRequest Pretty simple to add, so might as well. * Formatting changes * Async request logic There's probably some things I'm getting wrong for cases where PSN is connected, but for reasons that should be pretty obvious, learning how that all works is a little more involved than the PSN disconnected results. * Add missing error check * Update np_manager.cpp * Add a mutex to prevent concurrent reads/writes to g_requests I imagine multi-threading is a lot more commonly used with the async functions, though I haven't tested enough to know. * Update np_manager.h * Move request creation to separate internal function * Oops Not sure how that got missed, but good thing I spotted it * Oops --- src/core/libraries/np/np_error.h | 5 +- src/core/libraries/np/np_manager.cpp | 354 ++++++++++++++++++++++++--- src/core/libraries/np/np_manager.h | 26 +- 3 files changed, 342 insertions(+), 43 deletions(-) diff --git a/src/core/libraries/np/np_error.h b/src/core/libraries/np/np_error.h index 83140f702..0a3db903b 100644 --- a/src/core/libraries/np/np_error.h +++ b/src/core/libraries/np/np_error.h @@ -8,5 +8,8 @@ // For error codes shared between multiple Np libraries. constexpr int ORBIS_NP_ERROR_INVALID_ARGUMENT = 0x80550003; constexpr int ORBIS_NP_ERROR_SIGNED_OUT = 0x80550006; +constexpr int ORBIS_NP_ERROR_INVALID_SIZE = 0x80550011; +constexpr int ORBIS_NP_ERROR_ABORTED = 0x80550012; constexpr int ORBIS_NP_ERROR_REQUEST_MAX = 0x80550013; -constexpr int ORBIS_NP_ERROR_REQUEST_NOT_FOUND = 0x80550014; \ No newline at end of file +constexpr int ORBIS_NP_ERROR_REQUEST_NOT_FOUND = 0x80550014; +constexpr int ORBIS_NP_ERROR_INVALID_ID = 0x80550015; \ No newline at end of file diff --git a/src/core/libraries/np/np_manager.cpp b/src/core/libraries/np/np_manager.cpp index a210c9a40..ebc940bf3 100644 --- a/src/core/libraries/np/np_manager.cpp +++ b/src/core/libraries/np/np_manager.cpp @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include + #include "common/config.h" #include "common/logging/log.h" #include "core/libraries/error_codes.h" @@ -13,20 +15,38 @@ namespace Libraries::Np::NpManager { static bool g_signed_in = false; static s32 g_active_requests = 0; -static std::vector g_requests; +static std::mutex g_request_mutex; -s32 PS4_SYSV_ABI sceNpCreateRequest() { - LOG_DEBUG(Lib_NpManager, "called"); +// Internal types for storing request-related information +enum class NpRequestState { + None = 0, + Ready = 1, + Aborted = 2, + Complete = 3, +}; + +struct NpRequest { + NpRequestState state; + bool async; + s32 result; +}; + +static std::vector g_requests; + +s32 CreateNpRequest(bool async) { if (g_active_requests == ORBIS_NP_MANAGER_REQUEST_LIMIT) { return ORBIS_NP_ERROR_REQUEST_MAX; } + std::scoped_lock lk{g_request_mutex}; + s32 req_index = 0; while (req_index < g_requests.size()) { // Find first nonexistant request - if (g_requests[req_index] == OrbisNpRequestState::None) { + if (g_requests[req_index].state == NpRequestState::None) { // There is no request at this index, set the index to ready then break. - g_requests[req_index] = OrbisNpRequestState::Ready; + g_requests[req_index].state = NpRequestState::Ready; + g_requests[req_index].async = async; break; } req_index++; @@ -34,7 +54,8 @@ s32 PS4_SYSV_ABI sceNpCreateRequest() { if (req_index == g_requests.size()) { // There are no requests to replace. - g_requests.emplace_back(OrbisNpRequestState::Ready); + NpRequest new_request{NpRequestState::Ready, async, 0}; + g_requests.emplace_back(new_request); } // Offset by one, first returned ID is 0x20000001 @@ -42,69 +63,187 @@ s32 PS4_SYSV_ABI sceNpCreateRequest() { return req_index + ORBIS_NP_MANAGER_REQUEST_ID_OFFSET + 1; } +s32 PS4_SYSV_ABI sceNpCreateRequest() { + LOG_DEBUG(Lib_NpManager, "called"); + return CreateNpRequest(false); +} + +s32 PS4_SYSV_ABI sceNpCreateAsyncRequest(const OrbisNpCreateAsyncRequestParameter* param) { + LOG_DEBUG(Lib_NpManager, "called"); + if (param == nullptr) { + return ORBIS_NP_ERROR_INVALID_ARGUMENT; + } + + if (param->size != sizeof(OrbisNpCreateAsyncRequestParameter)) { + return ORBIS_NP_ERROR_INVALID_SIZE; + } + + return CreateNpRequest(true); +} + s32 PS4_SYSV_ABI sceNpCheckNpAvailability(s32 req_id, OrbisNpOnlineId* online_id) { if (online_id == nullptr) { return ORBIS_NP_ERROR_INVALID_ARGUMENT; } + std::scoped_lock lk{g_request_mutex}; + s32 req_index = req_id - ORBIS_NP_MANAGER_REQUEST_ID_OFFSET - 1; if (g_active_requests == 0 || g_requests.size() <= req_index || - g_requests[req_index] == OrbisNpRequestState::None) { + g_requests[req_index].state == NpRequestState::None) { return ORBIS_NP_ERROR_REQUEST_NOT_FOUND; } - if (g_requests[req_index] == OrbisNpRequestState::Complete) { + auto& request = g_requests[req_index]; + if (request.state == NpRequestState::Complete) { + request.result = ORBIS_NP_ERROR_INVALID_ARGUMENT; return ORBIS_NP_ERROR_INVALID_ARGUMENT; + } else if (request.state == NpRequestState::Aborted) { + request.result = ORBIS_NP_ERROR_ABORTED; + return ORBIS_NP_ERROR_ABORTED; } - g_requests[req_index] = OrbisNpRequestState::Complete; + request.state = NpRequestState::Complete; if (!g_signed_in) { + request.result = ORBIS_NP_ERROR_SIGNED_OUT; + // If the request is processed in some form, and it's an async request, then it returns OK. + if (request.async) { + return ORBIS_OK; + } return ORBIS_NP_ERROR_SIGNED_OUT; } - LOG_ERROR(Lib_NpManager, "(STUBBED) called, req_id = {:#x}", req_id); + LOG_ERROR(Lib_NpManager, "(STUBBED) called, req_id = {:#x}, is_async = {}", req_id, + request.async); + + request.result = ORBIS_OK; return ORBIS_OK; } s32 PS4_SYSV_ABI sceNpCheckNpAvailabilityA(s32 req_id, Libraries::UserService::OrbisUserServiceUserId user_id) { + std::scoped_lock lk{g_request_mutex}; + s32 req_index = req_id - ORBIS_NP_MANAGER_REQUEST_ID_OFFSET - 1; if (g_active_requests == 0 || g_requests.size() <= req_index || - g_requests[req_index] == OrbisNpRequestState::None) { + g_requests[req_index].state == NpRequestState::None) { return ORBIS_NP_ERROR_REQUEST_NOT_FOUND; } - if (g_requests[req_index] == OrbisNpRequestState::Complete) { + auto& request = g_requests[req_index]; + if (request.state == NpRequestState::Complete) { + request.result = ORBIS_NP_ERROR_INVALID_ARGUMENT; return ORBIS_NP_ERROR_INVALID_ARGUMENT; + } else if (request.state == NpRequestState::Aborted) { + request.result = ORBIS_NP_ERROR_ABORTED; + return ORBIS_NP_ERROR_ABORTED; } - g_requests[req_index] = OrbisNpRequestState::Complete; + request.state = NpRequestState::Complete; if (!g_signed_in) { + request.result = ORBIS_NP_ERROR_SIGNED_OUT; + // If the request is processed in some form, and it's an async request, then it returns OK. + if (request.async) { + return ORBIS_OK; + } return ORBIS_NP_ERROR_SIGNED_OUT; } - LOG_ERROR(Lib_NpManager, "(STUBBED) called, req_id = {:#x}", req_id); + LOG_ERROR(Lib_NpManager, "(STUBBED) called, req_id = {:#x}, is_async = {}", req_id, + request.async); + + request.result = ORBIS_OK; return ORBIS_OK; } s32 PS4_SYSV_ABI sceNpCheckNpReachability(s32 req_id, Libraries::UserService::OrbisUserServiceUserId user_id) { + std::scoped_lock lk{g_request_mutex}; + s32 req_index = req_id - ORBIS_NP_MANAGER_REQUEST_ID_OFFSET - 1; if (g_active_requests == 0 || g_requests.size() <= req_index || - g_requests[req_index] == OrbisNpRequestState::None) { + g_requests[req_index].state == NpRequestState::None) { return ORBIS_NP_ERROR_REQUEST_NOT_FOUND; } - if (g_requests[req_index] == OrbisNpRequestState::Complete) { + auto& request = g_requests[req_index]; + if (request.state == NpRequestState::Complete) { + request.result = ORBIS_NP_ERROR_INVALID_ARGUMENT; return ORBIS_NP_ERROR_INVALID_ARGUMENT; + } else if (request.state == NpRequestState::Aborted) { + request.result = ORBIS_NP_ERROR_ABORTED; + return ORBIS_NP_ERROR_ABORTED; } - g_requests[req_index] = OrbisNpRequestState::Complete; + request.state = NpRequestState::Complete; if (!g_signed_in) { + request.result = ORBIS_NP_ERROR_SIGNED_OUT; + // If the request is processed in some form, and it's an async request, then it returns OK. + if (request.async) { + return ORBIS_OK; + } return ORBIS_NP_ERROR_SIGNED_OUT; } - LOG_ERROR(Lib_NpManager, "(STUBBED) called, req_id = {:#x}", req_id); + LOG_ERROR(Lib_NpManager, "(STUBBED) called, req_id = {:#x}, is_async = {}", req_id, + request.async); + + request.result = ORBIS_OK; + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpCheckPlus(s32 req_id, const OrbisNpCheckPlusParameter* param, + OrbisNpCheckPlusResult* result) { + + if (req_id == 0 || param == nullptr || result == nullptr) { + return ORBIS_NP_ERROR_INVALID_ARGUMENT; + } + + if (param->size != sizeof(OrbisNpCheckPlusParameter)) { + return ORBIS_NP_ERROR_INVALID_SIZE; + } + + if (param->features < 1 || param->features > 3) { + // TODO: If compiled SDK version is greater or equal to fw 3.50, + // error if param->features != 1 instead. + return ORBIS_NP_ERROR_INVALID_ARGUMENT; + } + + std::scoped_lock lk{g_request_mutex}; + + s32 req_index = req_id - ORBIS_NP_MANAGER_REQUEST_ID_OFFSET - 1; + if (g_active_requests == 0 || g_requests.size() <= req_index || + g_requests[req_index].state == NpRequestState::None) { + return ORBIS_NP_ERROR_REQUEST_NOT_FOUND; + } + + auto& request = g_requests[req_index]; + if (request.state == NpRequestState::Complete) { + request.result = ORBIS_NP_ERROR_INVALID_ARGUMENT; + return ORBIS_NP_ERROR_INVALID_ARGUMENT; + } else if (request.state == NpRequestState::Aborted) { + request.result = ORBIS_NP_ERROR_ABORTED; + return ORBIS_NP_ERROR_ABORTED; + } + + request.state = NpRequestState::Complete; + if (!g_signed_in) { + request.result = ORBIS_NP_ERROR_SIGNED_OUT; + // If the request is processed in some form, and it's an async request, then it returns OK. + if (request.async) { + return ORBIS_OK; + } + return ORBIS_NP_ERROR_SIGNED_OUT; + } + + LOG_ERROR(Lib_NpManager, + "(STUBBED) called, req_id = {:#x}, is_async = {}, param.features = {:#x}", req_id, + request.async, param->features); + + // For now, set authorized to true to signal PS+ access. + result->authorized = true; + + request.result = ORBIS_OK; return ORBIS_OK; } @@ -114,23 +253,39 @@ s32 PS4_SYSV_ABI sceNpGetAccountLanguage(s32 req_id, OrbisNpOnlineId* online_id, return ORBIS_NP_ERROR_INVALID_ARGUMENT; } + std::scoped_lock lk{g_request_mutex}; + s32 req_index = req_id - ORBIS_NP_MANAGER_REQUEST_ID_OFFSET - 1; if (g_active_requests == 0 || g_requests.size() <= req_index || - g_requests[req_index] == OrbisNpRequestState::None) { + g_requests[req_index].state == NpRequestState::None) { return ORBIS_NP_ERROR_REQUEST_NOT_FOUND; } - if (g_requests[req_index] == OrbisNpRequestState::Complete) { + auto& request = g_requests[req_index]; + if (request.state == NpRequestState::Complete) { + request.result = ORBIS_NP_ERROR_INVALID_ARGUMENT; return ORBIS_NP_ERROR_INVALID_ARGUMENT; + } else if (request.state == NpRequestState::Aborted) { + request.result = ORBIS_NP_ERROR_ABORTED; + return ORBIS_NP_ERROR_ABORTED; } - g_requests[req_index] = OrbisNpRequestState::Complete; + request.state = NpRequestState::Complete; if (!g_signed_in) { + request.result = ORBIS_NP_ERROR_SIGNED_OUT; + // If the request is processed in some form, and it's an async request, then it returns OK. + if (request.async) { + return ORBIS_OK; + } return ORBIS_NP_ERROR_SIGNED_OUT; } + LOG_ERROR(Lib_NpManager, "(STUBBED) called, req_id = {:#x}, is_async = {}", req_id, + request.async); + std::memset(language, 0, sizeof(OrbisNpLanguageCode)); - LOG_ERROR(Lib_NpManager, "(STUBBED) called"); + + request.result = ORBIS_OK; return ORBIS_OK; } @@ -141,23 +296,39 @@ s32 PS4_SYSV_ABI sceNpGetAccountLanguageA(s32 req_id, return ORBIS_NP_ERROR_INVALID_ARGUMENT; } + std::scoped_lock lk{g_request_mutex}; + s32 req_index = req_id - ORBIS_NP_MANAGER_REQUEST_ID_OFFSET - 1; if (g_active_requests == 0 || g_requests.size() <= req_index || - g_requests[req_index] == OrbisNpRequestState::None) { + g_requests[req_index].state == NpRequestState::None) { return ORBIS_NP_ERROR_REQUEST_NOT_FOUND; } - if (g_requests[req_index] == OrbisNpRequestState::Complete) { + auto& request = g_requests[req_index]; + if (request.state == NpRequestState::Complete) { + request.result = ORBIS_NP_ERROR_INVALID_ARGUMENT; return ORBIS_NP_ERROR_INVALID_ARGUMENT; + } else if (request.state == NpRequestState::Aborted) { + request.result = ORBIS_NP_ERROR_ABORTED; + return ORBIS_NP_ERROR_ABORTED; } - g_requests[req_index] = OrbisNpRequestState::Complete; + request.state = NpRequestState::Complete; if (!g_signed_in) { + request.result = ORBIS_NP_ERROR_SIGNED_OUT; + // If the request is processed in some form, and it's an async request, then it returns OK. + if (request.async) { + return ORBIS_OK; + } return ORBIS_NP_ERROR_SIGNED_OUT; } + LOG_ERROR(Lib_NpManager, "(STUBBED) called, req_id = {:#x}, user_id = {}, is_async = {}", + req_id, user_id, request.async); + std::memset(language, 0, sizeof(OrbisNpLanguageCode)); - LOG_ERROR(Lib_NpManager, "(STUBBED) called, user_id = {}", user_id); + + request.result = ORBIS_OK; return ORBIS_OK; } @@ -167,25 +338,41 @@ s32 PS4_SYSV_ABI sceNpGetParentalControlInfo(s32 req_id, OrbisNpOnlineId* online return ORBIS_NP_ERROR_INVALID_ARGUMENT; } + std::scoped_lock lk{g_request_mutex}; + s32 req_index = req_id - ORBIS_NP_MANAGER_REQUEST_ID_OFFSET - 1; if (g_active_requests == 0 || g_requests.size() <= req_index || - g_requests[req_index] == OrbisNpRequestState::None) { + g_requests[req_index].state == NpRequestState::None) { return ORBIS_NP_ERROR_REQUEST_NOT_FOUND; } - if (g_requests[req_index] == OrbisNpRequestState::Complete) { + auto& request = g_requests[req_index]; + if (request.state == NpRequestState::Complete) { + request.result = ORBIS_NP_ERROR_INVALID_ARGUMENT; return ORBIS_NP_ERROR_INVALID_ARGUMENT; + } else if (request.state == NpRequestState::Aborted) { + request.result = ORBIS_NP_ERROR_ABORTED; + return ORBIS_NP_ERROR_ABORTED; } - g_requests[req_index] = OrbisNpRequestState::Complete; + request.state = NpRequestState::Complete; if (!g_signed_in) { + request.result = ORBIS_NP_ERROR_SIGNED_OUT; + // If the request is processed in some form, and it's an async request, then it returns OK. + if (request.async) { + return ORBIS_OK; + } return ORBIS_NP_ERROR_SIGNED_OUT; } + LOG_ERROR(Lib_NpManager, "(STUBBED) called, req_id = {:#x}, is_async = {}", req_id, + request.async); + // TODO: Add to config? *age = 13; std::memset(info, 0, sizeof(OrbisNpParentalControlInfo)); - LOG_ERROR(Lib_NpManager, "(STUBBED) called"); + + request.result = ORBIS_OK; return ORBIS_OK; } @@ -196,38 +383,127 @@ sceNpGetParentalControlInfoA(s32 req_id, Libraries::UserService::OrbisUserServic return ORBIS_NP_ERROR_INVALID_ARGUMENT; } + std::scoped_lock lk{g_request_mutex}; + s32 req_index = req_id - ORBIS_NP_MANAGER_REQUEST_ID_OFFSET - 1; if (g_active_requests == 0 || g_requests.size() <= req_index || - g_requests[req_index] == OrbisNpRequestState::None) { + g_requests[req_index].state == NpRequestState::None) { return ORBIS_NP_ERROR_REQUEST_NOT_FOUND; } - if (g_requests[req_index] == OrbisNpRequestState::Complete) { + auto& request = g_requests[req_index]; + if (request.state == NpRequestState::Complete) { + request.result = ORBIS_NP_ERROR_INVALID_ARGUMENT; return ORBIS_NP_ERROR_INVALID_ARGUMENT; + } else if (request.state == NpRequestState::Aborted) { + request.result = ORBIS_NP_ERROR_ABORTED; + return ORBIS_NP_ERROR_ABORTED; } - g_requests[req_index] = OrbisNpRequestState::Complete; + request.state = NpRequestState::Complete; if (!g_signed_in) { + request.result = ORBIS_NP_ERROR_SIGNED_OUT; + // If the request is processed in some form, and it's an async request, then it returns OK. + if (request.async) { + return ORBIS_OK; + } return ORBIS_NP_ERROR_SIGNED_OUT; } + LOG_ERROR(Lib_NpManager, "(STUBBED) called, req_id = {:#x}, user_id = {}, is_async = {}", + req_id, user_id, request.async); + // TODO: Add to config? *age = 13; std::memset(info, 0, sizeof(OrbisNpParentalControlInfo)); - LOG_ERROR(Lib_NpManager, "(STUBBED) called, user_id = {}", user_id); + + request.result = ORBIS_OK; + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpAbortRequest(s32 req_id) { + LOG_DEBUG(Lib_NpManager, "called req_id = {:#x}", req_id); + + std::scoped_lock lk{g_request_mutex}; + + s32 req_index = req_id - ORBIS_NP_MANAGER_REQUEST_ID_OFFSET - 1; + if (g_active_requests == 0 || g_requests.size() <= req_index || + g_requests[req_index].state == NpRequestState::None) { + return ORBIS_NP_ERROR_REQUEST_NOT_FOUND; + } + + if (g_requests[req_index].state == NpRequestState::Complete) { + // If the request is already complete, abort is ignored. + return ORBIS_OK; + } + + g_requests[req_index].state = NpRequestState::Aborted; + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpWaitAsync(s32 req_id, s32* result) { + if (result == nullptr) { + return ORBIS_NP_ERROR_INVALID_ARGUMENT; + } + + std::scoped_lock lk{g_request_mutex}; + + s32 req_index = req_id - ORBIS_NP_MANAGER_REQUEST_ID_OFFSET - 1; + if (g_active_requests == 0 || g_requests.size() <= req_index || + g_requests[req_index].state == NpRequestState::None) { + return ORBIS_NP_ERROR_REQUEST_NOT_FOUND; + } + + if (!g_requests[req_index].async || g_requests[req_index].state == NpRequestState::Ready) { + return ORBIS_NP_ERROR_INVALID_ID; + } + + // Since we're not actually performing any sort of network request here, + // we can just set result based on the request and return. + *result = g_requests[req_index].result; + LOG_WARNING(Lib_NpManager, "called req_id = {:#x}, returning result = {:#x}", req_id, + static_cast(*result)); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpPollAsync(s32 req_id, s32* result) { + if (result == nullptr) { + return ORBIS_NP_ERROR_INVALID_ARGUMENT; + } + + std::scoped_lock lk{g_request_mutex}; + + s32 req_index = req_id - ORBIS_NP_MANAGER_REQUEST_ID_OFFSET - 1; + if (g_active_requests == 0 || g_requests.size() <= req_index || + g_requests[req_index].state == NpRequestState::None) { + return ORBIS_NP_ERROR_REQUEST_NOT_FOUND; + } + + if (!g_requests[req_index].async || g_requests[req_index].state == NpRequestState::Ready) { + return ORBIS_NP_ERROR_INVALID_ID; + } + + // Since we're not actually performing any sort of network request here, + // we can just set result based on the request and return. + *result = g_requests[req_index].result; + LOG_WARNING(Lib_NpManager, "called req_id = {:#x}, returning result = {:#x}", req_id, + static_cast(*result)); return ORBIS_OK; } s32 PS4_SYSV_ABI sceNpDeleteRequest(s32 req_id) { LOG_DEBUG(Lib_NpManager, "called req_id = {:#x}", req_id); + + std::scoped_lock lk{g_request_mutex}; + s32 req_index = req_id - ORBIS_NP_MANAGER_REQUEST_ID_OFFSET - 1; if (g_active_requests == 0 || g_requests.size() <= req_index || - g_requests[req_index] == OrbisNpRequestState::None) { + g_requests[req_index].state == NpRequestState::None) { return ORBIS_NP_ERROR_REQUEST_NOT_FOUND; } g_active_requests--; - g_requests[req_index] = OrbisNpRequestState::None; + g_requests[req_index].state = NpRequestState::None; return ORBIS_OK; } @@ -429,16 +705,22 @@ void RegisterLib(Core::Loader::SymbolsResolver* sym) { g_signed_in = Config::getPSNSignedIn(); LIB_FUNCTION("GpLQDNKICac", "libSceNpManager", 1, "libSceNpManager", sceNpCreateRequest); + LIB_FUNCTION("eiqMCt9UshI", "libSceNpManager", 1, "libSceNpManager", sceNpCreateAsyncRequest); LIB_FUNCTION("2rsFmlGWleQ", "libSceNpManager", 1, "libSceNpManager", sceNpCheckNpAvailability); LIB_FUNCTION("8Z2Jc5GvGDI", "libSceNpManager", 1, "libSceNpManager", sceNpCheckNpAvailabilityA); LIB_FUNCTION("KfGZg2y73oM", "libSceNpManager", 1, "libSceNpManager", sceNpCheckNpReachability); + LIB_FUNCTION("r6MyYJkryz8", "libSceNpManager", 1, "libSceNpManager", sceNpCheckPlus); LIB_FUNCTION("KZ1Mj9yEGYc", "libSceNpManager", 1, "libSceNpManager", sceNpGetAccountLanguage); LIB_FUNCTION("TPMbgIxvog0", "libSceNpManager", 1, "libSceNpManager", sceNpGetAccountLanguageA); LIB_FUNCTION("ilwLM4zOmu4", "libSceNpManager", 1, "libSceNpManager", sceNpGetParentalControlInfo); LIB_FUNCTION("m9L3O6yst-U", "libSceNpManager", 1, "libSceNpManager", sceNpGetParentalControlInfoA); + LIB_FUNCTION("OzKvTvg3ZYU", "libSceNpManager", 1, "libSceNpManager", sceNpAbortRequest); + LIB_FUNCTION("jyi5p9XWUSs", "libSceNpManager", 1, "libSceNpManager", sceNpWaitAsync); + LIB_FUNCTION("uqcPJLWL08M", "libSceNpManager", 1, "libSceNpManager", sceNpPollAsync); LIB_FUNCTION("S7QTn72PrDw", "libSceNpManager", 1, "libSceNpManager", sceNpDeleteRequest); + LIB_FUNCTION("Ghz9iWDUtC4", "libSceNpManager", 1, "libSceNpManager", sceNpGetAccountCountry); LIB_FUNCTION("JT+t00a3TxA", "libSceNpManager", 1, "libSceNpManager", sceNpGetAccountCountryA); LIB_FUNCTION("8VBTeRf1ZwI", "libSceNpManager", 1, "libSceNpManager", diff --git a/src/core/libraries/np/np_manager.h b/src/core/libraries/np/np_manager.h index f5ae92efc..61a283ba7 100644 --- a/src/core/libraries/np/np_manager.h +++ b/src/core/libraries/np/np_manager.h @@ -26,12 +26,6 @@ enum class OrbisNpState : u32 { using OrbisNpStateCallbackForNpToolkit = PS4_SYSV_ABI void (*)(s32 userId, OrbisNpState state, void* userdata); -enum class OrbisNpRequestState { - None = 0, - Ready = 1, - Complete = 2, -}; - enum class OrbisNpGamePresenseStatus { Offline = 0, Online = 1, @@ -66,5 +60,25 @@ struct OrbisNpParentalControlInfo { bool user_generated_content_restriction; }; +struct OrbisNpCheckPlusParameter { + u64 size; + Libraries::UserService::OrbisUserServiceUserId user_id; + u8 padding[4]; + u64 features; + u8 reserved[32]; +}; + +struct OrbisNpCheckPlusResult { + bool authorized; + u8 reserved[32]; +}; + +struct OrbisNpCreateAsyncRequestParameter { + u64 size; + u64 cpu_affinity_mask; + s32 thread_priority; + u8 padding[4]; +}; + void RegisterLib(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::Np::NpManager