Files
AnyPS5/docs/dev/debt/libSceNpManager.md
Dean 74bdc3a3a7 Merge pull request #8110 from savvaniss/feat/np-account-signed-out
feat(libSceNpManager): answer the PS4 account and presence queries for a signed-out user
2026-10-22 01:54:31 +13:00

11 KiB

libSceNpManager technical debt

Silent stubs

  • sceNpUnregisterPlusEventCallback (libSceNpManager) - returns 0 whether or not a callback was registered, as sceNpUnregisterPremiumEventCallback does: sceNpRegisterPlusEventCallback keeps no callback, and a signed-out user gets no plus events

Unknown function info

  • libSceNpManager pending exports - 150 named callable exports are present in the local libSceNpManager.sprx export table and the public PS5 3.20 symbol list. Their signatures and behavior are unverified; each declaration uses the no-parameter unknown-signature convention and throws through NotImplemented_nid_no_patch.

  • sceNpGetSandboxInfo (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.

  • sceNpUnknown_8weiQyIdI3A (libSceNpManager, NID 8weiQyIdI3A) - the name is not in aerolib. EA SPORTS FC 27 (PPSA34015) fails to load libSceNpManager.prx without it (unresolved ELF import / GetLastError: 127). Its only call is mov edi, r14d (a user id) and lea rsi, [rbp-0x40] after a 17-byte copy into that buffer (mov edx, 0x11); test eax, eax follows. The C name, the type of the 17-byte object and the console return are unknown, so every call throws without reading or writing caller memory.

  • sceNpUnknown_WxLcN76q19o (libSceNpManager, NID WxLcN76q19o) - the name is not in aerolib. PPSA34015 imports it from libSceNpManager.prx as a strong JUMP_SLOT with no call found in the eboot; the loader still requires the export. Arguments, result and console errors are unknown, so every call throws.

  • sceNpSetTimeout (libSceNpManager) - the signature follows orbital, shadPS4 and SharpProspero; the rejected values (all five 0, negative retries, a resolve timeout under 1 s or another timeout under 10 s, 0 meaning the default) are shadPS4's, not checked on a console. An id that was never created or was deleted returns REQUEST_NOT_FOUND, as in shadPS4; there is no network, so the timeouts are not stored

  • sceNpGetUserIdByAccountId - the (account id, user id output) signature and its errors follow shadPS4: account id 0 or a null output returns SCE_NP_ERROR_INVALID_ARGUMENT, and a signed-out NP returns SCE_NP_ERROR_SIGNED_OUT without writing the output. NP is always signed out here, so no account id resolves to a user

  • sceNpNotifyPlusFeature (libSceNpManager) - PS4 titles import it; its parameter block and what the console does with it for a signed-out user are unknown (shadPS4 returns 0 without reading it), so every call throws.

Functional

  • sceNpGetAccountCountry, sceNpGetAccountDateOfBirth, sceNpGetAccountLanguage, sceNpGetParentalControlInfo (libSceNpManager) - PS4 forms taking an online id, not measured on a console. Signatures and checks follow shadPS4: a null pointer is INVALID_ARGUMENT; no user is signed in, so no online id matches one and the rest return USER_NOT_FOUND without writing, like sceNpCheckNpAvailability. Request ids are not checked

  • sceNpGetUserIdByOnlineId (libSceNpManager) - the (online id, user id output) signature follows shadPS4: a null online id or output returns SCE_NP_ERROR_INVALID_ARGUMENT, and a signed-out NP returns SCE_NP_ERROR_SIGNED_OUT without writing the output, as sceNpGetUserIdByAccountId does

  • sceNpCheckPlus (libSceNpManager) - the (request id, parameter, result) signature follows shadPS4: request id 0 or a null parameter or result returns SCE_NP_ERROR_INVALID_ARGUMENT, and every other call returns SCE_NP_ERROR_SIGNED_OUT without writing the result, as sceNpCheckPremium does. The parameter's size and feature fields, which shadPS4 checks, are not read: the errors the console returns for them are not known

  • sceNpGetAccountId, sceNpSetGamePresenceOnline (libSceNpManager) - PS4 forms; the (online id, account id output) and (request id, online id, presence) signatures follow shadPS4. A null online id or output, or request id 0 for sceNpSetGamePresenceOnline, returns SCE_NP_ERROR_INVALID_ARGUMENT. sceNpSetGamePresenceOnline then returns SCE_NP_ERROR_REQUEST_NOT_FOUND for a request that was never created or was deleted, as shadPS4 does. Otherwise both return SCE_NP_ERROR_SIGNED_OUT without writing, as sceNpGetAccountIdA does. The console's result for a signed-out user is not measured

  • NP reachability callbacks retain one callback and its user data; duplicate registration and unregistering an absent callback return the errors used by shadPS4. No callback is delivered because the existing NP model remains signed out with reachability unavailable.

  • sceNpCheckNpAvailability (libSceNpManager) - the (req_id, online_id) signature and the errors follow shadPS4 with no user signed in to PSN: a null online id is SCE_NP_ERROR_INVALID_ARGUMENT, and any other online id matches no user, SCE_NP_ERROR_USER_NOT_FOUND; the request id is not checked, as in the other NpManager requests

  • NP state callbacks (libSceNpManager) - the registration rules are shadPS4's: sceNpRegisterStateCallbackA keeps up to 8 callbacks and returns the slot plus 1, a null callback returns INVALID_ARGUMENT, a callback already registered CALLBACK_ALREADY_REGISTERED and a ninth one CALLBACK_MAX (0x8055001D, np_error.h); sceNpUnregisterStateCallbackA returns INVALID_ARGUMENT for an id outside 1..8 and CALLBACK_NOT_REGISTERED for an empty slot; the legacy sceNpRegisterStateCallback keeps one callback with the same errors. Each registration gets SIGNED_OUT for the initial user (0x10000000) once, from the next sceNpCheckCallback on the calling thread. For the A form this follows KytyPS5, whose sceNpRegisterStateCallbackA marks the registration pending. KytyPS5 never calls the legacy callback (sceNpRegisterStateCallback stores nothing); it is called as (user, SIGNED_OUT, nullptr, userdata), as in shadPS4, which passes an NpId only for SIGNED_IN (L823, L938-L940). shadPS4 instead queues SIGNED_OUT from the user service login event and delivers it from sceNpCheckCallback (DispatchPendingNpStateCallbacks); the reachability callback is not given an initial UNAVAILABLE, unlike that function (L922-L961). A callback being delivered when another thread unregisters it is still called once. When and how often the console calls the state callbacks, and the errors, are not measured

  • sceNpRegisterGamePresenceCallback (libSceNpManager) - accepts any callback, null included, and returns nothing; no game presence event is delivered because the NP model remains signed out. Kyty ignores the callback the same way, and shadPS4 keeps the last one without calling it. Not measured on a PS5

  • The following pending declarations have unverified signatures and behavior; they are parameterless import-resolution declarations and throw through NotImplemented_nid_no_patch: sceNpCheckCallbackForLib.