Skip to content

feat(libSceNpAuth): implement offline auth requests - #3604

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
itsbo5:feat/libSceNpAuth-complete
Oct 12, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
itsbo5:feat/libSceNpAuth-complete

Conversation

@itsbo5

@itsbo5 itsbo5 commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

What

Implement sceNpAuthCreateRequest, sceNpAuthGetIdTokenV3, and sceNpAuthWaitAsync offline stubs in libSceNpAuth. Add guest test covering sequential request ID generation, parameter validation, and offline signed-out returns. Document unverified request tracking behavior in TechnicalDebt.md.

Tested

Verified guest tests in core/libs/tests/GuestNpAuth.cpp.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • AI-assisted: yes

@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Progress report (27873b0 → 62d1275)

📈 System libraries: 87.15% (+0.08%, +3 implemented functions)

✅ 3 implemented
Library Name
libSceNpAuth sceNpAuthCreateRequest
libSceNpAuth sceNpAuthGetIdTokenV3
libSceNpAuth sceNpAuthWaitAsync

@adriadam10 adriadam10 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. The offline behaviour (incrementing request ids, SCE_NP_ERROR_SIGNED_OUT for tokens) matches shadPS4/KytyPS5. A few things before it can merge:

  • The PR template is empty (What, Tested, Checklist), which is why conventions fails. Please fill it in, including what you ran.
  • No test. Please add a guest test registered in ctest covering CreateRequest (distinct ids), GetIdTokenV3 (null param/id_token → INVALID_ARGUMENT, otherwise SIGNED_OUT) and WaitAsync.
  • core/libs/prx/libSceNpAuth/Export.cpp:25-57: the diff re-indents untouched functions (DeleteRequest, GetAuthorizationCodeV3, PollAsync) and the file now mixes 1- and 4-space indentation. Please match the file's style and keep only the changed lines.
  • Export.cpp:54: WaitAsync accepts any req_id and a null result. shadPS4 returns INVALID_ARGUMENT for a null result and REQUEST_NOT_FOUND for an unknown id. Either do the same or add a line in docs/dev/TechnicalDebt.md ("Unknown function info") saying ids are not tracked and req_id is not validated (same for Poll/Delete).

@itsbo5

itsbo5 commented Oct 11, 2026

Copy link
Copy Markdown
Contributor Author

updated

@blawesom

Copy link
Copy Markdown
Contributor

Independent pre-review on Linux (full CI runs only happen on manual trigger, so recording one): CachyOS, kernel 7.2.9, GCC 16.2.1, Ninja, Release, BUILD_TESTING=ON.

  • Builds; tools/check_conventions.py --base origin/main passes.
  • Full suite: 833/833 passed (all tests including the Vulkan suites on AMD RX 9070 XT / RADV).

@xXPBSXx

xXPBSXx commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Tested together with the Ces branch for Teardown (PPSA15246): with this PR the title no longer throws at sceNpAuthGetIdTokenV3 and goes on to the graphics start-up (details in #3701).

One point to check against the reference: shadPS4's GetIdToken (np_auth.cpp) distinguishes the request kind when signed out. For an async request (created with sceNpAuthCreateAsyncRequest) the call returns ORBIS_OK and stores the signed-out error in the request result, which sceNpAuthPollAsync/sceNpAuthWaitAsync return later; only for a synchronous request does the call itself return SCE_NP_ERROR_SIGNED_OUT. This PR returns signed-out from sceNpAuthGetIdTokenV3 for every request id and does not record the kind of the request. Teardown did not trip over it in a 60 s run, and I have not checked which request kind it uses, so this is a note on fidelity, not a failure.

AI-assisted (Claude Code).

@itsbo5

itsbo5 commented Oct 11, 2026

Copy link
Copy Markdown
Contributor Author

Tested together with the Ces branch for Teardown (PPSA15246): with this PR the title no longer throws at sceNpAuthGetIdTokenV3 and goes on to the graphics start-up (details in #3701).

One point to check against the reference: shadPS4's GetIdToken (np_auth.cpp) distinguishes the request kind when signed out. For an async request (created with sceNpAuthCreateAsyncRequest) the call returns ORBIS_OK and stores the signed-out error in the request result, which sceNpAuthPollAsync/sceNpAuthWaitAsync return later; only for a synchronous request does the call itself return SCE_NP_ERROR_SIGNED_OUT. This PR returns signed-out from sceNpAuthGetIdTokenV3 for every request id and does not record the kind of the request. Teardown did not trip over it in a 60 s run, and I have not checked which request kind it uses, so this is a note on fidelity, not a failure.

AI-assisted (Claude Code).

Thanks for testing with Teardown and verifying the graphics startup progress!

Regarding the request kinds: the Technical Debt entry currently documents that request IDs are atomic counters and are not tracked offline. As titles exercise more of the asynchronous auth flow, we can follow up with full request state tracking (distinguishing sync vs async) in a dedicated PR.

@adriadam10 adriadam10 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, the offline path is a good start and the new guest_np_auth test fails without the change. One thing before it can merge:

  • core/libs/prx/libSceNpAuth/Export.cpp:43-44 (sceNpAuthGetIdTokenV3) returns SCE_NP_ERROR_SIGNED_OUT for every request id. As @xXPBSXx pointed out, shadPS4 (np_auth.cpp, GetIdToken with CreateNpAuthRequest(async)) treats the two request kinds differently: for a request from sceNpAuthCreateAsyncRequest the call returns OK and the signed-out error is stored in the request, then returned by sceNpAuthPollAsync/sceNpAuthWaitAsync; only a request from sceNpAuthCreateRequest gets the error from the call itself. Right now main throws here, so returning a plausible result that differs for async requests is the case we avoid (exact or throw).
    What would fix it: keep a small mutex-protected table req_id -> {async, result} filled by the two Create* functions; GetIdTokenV3/GetAuthorizationCodeV3 return OK and store SCE_NP_ERROR_SIGNED_OUT for async requests, Poll/Wait return the stored result, and add test rows for both kinds. Unknown ids need either a reference or a line under "Unknown function info" (shadPS4 returns REQUEST_NOT_FOUND, but it is PS4).
  • Then update the docs/dev/TechnicalDebt.md:70 entry, which currently says requests are not tracked.

Checked: build and ctest of the PR merged onto main, and the negative run of the test. Note that shadPS4 is a PS4 reference; if you have anything from PS5, cite it.

@itsbo5
itsbo5 force-pushed the feat/libSceNpAuth-complete branch from 935e5c1 to 954b793 Compare October 11, 2026 17:06
@itsbo5

itsbo5 commented Oct 11, 2026

Copy link
Copy Markdown
Contributor Author

Thanks, the offline path is a good start and the new guest_np_auth test fails without the change. One thing before it can merge:

  • core/libs/prx/libSceNpAuth/Export.cpp:43-44 (sceNpAuthGetIdTokenV3) returns SCE_NP_ERROR_SIGNED_OUT for every request id. As @xXPBSXx pointed out, shadPS4 (np_auth.cpp, GetIdToken with CreateNpAuthRequest(async)) treats the two request kinds differently: for a request from sceNpAuthCreateAsyncRequest the call returns OK and the signed-out error is stored in the request, then returned by sceNpAuthPollAsync/sceNpAuthWaitAsync; only a request from sceNpAuthCreateRequest gets the error from the call itself. Right now main throws here, so returning a plausible result that differs for async requests is the case we avoid (exact or throw).
    What would fix it: keep a small mutex-protected table req_id -> {async, result} filled by the two Create* functions; GetIdTokenV3/GetAuthorizationCodeV3 return OK and store SCE_NP_ERROR_SIGNED_OUT for async requests, Poll/Wait return the stored result, and add test rows for both kinds. Unknown ids need either a reference or a line under "Unknown function info" (shadPS4 returns REQUEST_NOT_FOUND, but it is PS4).
  • Then update the docs/dev/TechnicalDebt.md:70 entry, which currently says requests are not tracked.

Checked: build and ctest of the PR merged onto main, and the negative run of the test. Note that shadPS4 is a PS4 reference; if you have anything from PS5, cite it.

Updated to track requests following shadPS4 (np_auth.cpp):

  • Added a mutex-protected table tracking request kinds (async vs sync) and results.
  • sceNpAuthGetIdTokenV3 and sceNpAuthGetAuthorizationCodeV3 now return 0 for async requests while deferring SCE_NP_ERROR_SIGNED_OUT to PollAsync/WaitAsync, and return SCE_NP_ERROR_SIGNED_OUT directly for synchronous requests.
  • Unknown or deleted request IDs return SCE_NP_ERROR_REQUEST_NOT_FOUND (0x80550014), documented under Unknown function info in docs/dev/TechnicalDebt.md.
  • Expanded GuestNpAuth with test rows for both request kinds, unknown IDs, and deleted IDs.

@adriadam10 adriadam10 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update; the sync/async table is what was needed. Checked: build and ctest of the PR merged onto main (guest_np_auth passes). Remaining points, all against the same shadPS4 np_auth.cpp the TechnicalDebt line cites:

  • core/libs/prx/libSceNpAuth/Export.cpp:11: 0x80550014 is the generic ORBIS_NP_ERROR_REQUEST_NOT_FOUND. shadPS4's auth functions return ORBIS_NP_AUTH_ERROR_REQUEST_NOT_FOUND = 0x80550306 (np_error.h). Please use that in the code, the test (GuestNpAuth.cpp:26) and docs/dev/TechnicalDebt.md:70, whose "follow shadPS4" is otherwise not true.
  • Export.cpp:90-95 and :82-86 (WaitAsync/PollAsync): shadPS4 returns ORBIS_NP_AUTH_ERROR_INVALID_ID (0x80550307) when the request is not async, or when it is async but GetIdToken/GetAuthorizationCode has not been called on it yet (state Ready). Here a sync request (and an unprocessed async one) returns OK with the stored result. Please track that state (e.g. a processed flag set by the Get* calls) and update the test rows (GuestNpAuth.cpp:72-76 currently pin the sync case as OK).
  • Once GetIdTokenV3/GetAuthorizationCodeV3 ran on a request, shadPS4 returns INVALID_ARGUMENT on a second call (state Complete). If you don't model that, list it under the TechnicalDebt entry.

@itsbo5
itsbo5 force-pushed the feat/libSceNpAuth-complete branch from 954b793 to 28738c7 Compare October 11, 2026 17:54
@itsbo5

itsbo5 commented Oct 11, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the update; the sync/async table is what was needed. Checked: build and ctest of the PR merged onto main (guest_np_auth passes). Remaining points, all against the same shadPS4 np_auth.cpp the TechnicalDebt line cites:

  • core/libs/prx/libSceNpAuth/Export.cpp:11: 0x80550014 is the generic ORBIS_NP_ERROR_REQUEST_NOT_FOUND. shadPS4's auth functions return ORBIS_NP_AUTH_ERROR_REQUEST_NOT_FOUND = 0x80550306 (np_error.h). Please use that in the code, the test (GuestNpAuth.cpp:26) and docs/dev/TechnicalDebt.md:70, whose "follow shadPS4" is otherwise not true.
  • Export.cpp:90-95 and :82-86 (WaitAsync/PollAsync): shadPS4 returns ORBIS_NP_AUTH_ERROR_INVALID_ID (0x80550307) when the request is not async, or when it is async but GetIdToken/GetAuthorizationCode has not been called on it yet (state Ready). Here a sync request (and an unprocessed async one) returns OK with the stored result. Please track that state (e.g. a processed flag set by the Get* calls) and update the test rows (GuestNpAuth.cpp:72-76 currently pin the sync case as OK).
  • Once GetIdTokenV3/GetAuthorizationCodeV3 ran on a request, shadPS4 returns INVALID_ARGUMENT on a second call (state Complete). If you don't model that, list it under the TechnicalDebt entry.

updated

@xXPBSXx

xXPBSXx commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Rebase needed: merged into current main (bb48d60fc), this PR conflicts in core/libs/CMakeLists.txt (its guest_np_auth_tests block sits next to a block added on main; TechnicalDebt.md conflicts too).

Test from Teardown (PPSA15246), Windows, 60 s runs: with this PR the title passes sceNpAuthGetIdTokenV3 and goes on to savedata and graphics start-up (details in #3701); without it the call throws.

AI-assisted (Claude Code).

@xXPBSXx

xXPBSXx commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

Review notes, comparing the code with the shadPS4 source this PR's TechnicalDebt entry cites (np_auth.cpp and np_error.h, read at current main). I did not run these; they are differences between this diff and that reference, not console measurements.

  1. Error code for invalid arguments. The entry says SCE_NP_ERROR_INVALID_ARGUMENT on repeated calls "follows shadPS4". In shadPS4 GetIdToken/GetAuthorizationCode return ORBIS_NP_AUTH_ERROR_INVALID_ARGUMENT (0x80550301) for a null param or output pointer, for a request that is already Complete, and sceNpAuthWaitAsync does so for a null result. This diff returns SCE_NP_ERROR_INVALID_ARGUMENT (0x80550003) in all of those places (sceNpAuthGetIdTokenV3, sceNpAuthGetAuthorizationCodeV3, sceNpAuthWaitAsync), and core/libs/tests/GuestNpAuth.cpp pins invalidArgument = 0x80550003. Either use 0x80550301 or say in the entry that it deliberately differs.
  2. No parameter size check. shadPS4 returns ORBIS_NP_AUTH_ERROR_INVALID_SIZE (0x80550302) when param->size is not the structure size, before the request lookup. This diff reads neither param field, so a wrong size is accepted. The structure layouts are not in this PR, so adding it needs them; if that is the reason, the entry should list it as not checked.
  3. sceNpAuthAbortRequest is unchanged and ignores state. In shadPS4 it returns ORBIS_NP_AUTH_ERROR_REQUEST_NOT_FOUND for an unknown id and marks a not-yet-processed request aborted, so the next Get* returns ORBIS_NP_AUTH_ERROR_ABORTED (0x80550304). Here it still returns 0 for any id, and the test calls sceNpAuthAbortRequest(asyncReq) on a request that has completed. Not required for PPSA15246, but the entry describes request tracking as following shadPS4.
  4. Unbounded table. g_requests only shrinks in sceNpAuthDeleteRequest; a title that creates requests without deleting them grows it without limit (shadPS4 has ORBIS_NP_AUTH_ERROR_REQUEST_MAX, 0x80550305). Minor.

Also: the branch conflicts with main (docs/dev/TechnicalDebt.md and core/libs/CMakeLists.txt are the likely places) and needs a rebase.

For context, PPSA15246 stops at sceNpAuthGetIdTokenV3 not implemented on main, so the PR is what that title needs; the points above are about matching the cited reference.

AI-assisted (Claude Code).

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Conflicts with main in core/libs/CMakeLists.txt and docs/dev/TechnicalDebt.md; please rebase. One more from the same shadPS4 source: its auth functions return ORBIS_NP_AUTH_ERROR_INVALID_ARGUMENT (0x80550301) for null pointers and for a second Get* call, not 0x80550003 (Export.cpp:9, GuestNpAuth.cpp:24). The three points from the last review are done.

Mouad-Scriptz-0 pushed a commit to Mouad-Scriptz-0/AnyPS5 that referenced this pull request Oct 12, 2026
…orizedAppCode

There is no PSN sign-in, so the code getter answers SCE_NP_ERROR_SIGNED_OUT
instead of throwing; its parameters are unknown and not read. Minecraft
(PPSA17221) calls it after its sign-in dialog and treats the result as
offline play. The request, token and wait calls are left to boykopovar#3604.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Mouad-Scriptz-0

Mouad-Scriptz-0 commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

#4218 overlapped this PR with a simpler signed-out model for sceNpAuthCreateRequest, sceNpAuthGetIdTokenV3 and sceNpAuthWaitAsync; it is now cut down to sceNpAuthGetAuthorizedAppCode only (a stub from #4118 that Minecraft PPSA17221 calls after its sign-in dialog), so the request model stays here. Minecraft reaches its menu with the signed-out answers to the same three calls, in case that helps as a second title for this PR.

Mouad-Scriptz-0 pushed a commit to Mouad-Scriptz-0/AnyPS5 that referenced this pull request Oct 12, 2026
…orizedAppCode

There is no PSN sign-in, so the code getter answers SCE_NP_ERROR_SIGNED_OUT
instead of throwing; its parameters are unknown and not read. Minecraft
(PPSA17221) calls it after its sign-in dialog and treats the result as
offline play. The request, token and wait calls are left to boykopovar#3604.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Pacuka

Pacuka commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

Data point from Minecraft (PPSA17221), Linux / RX 6650 XT (RADV), on main d592d54e1 + #4215 #4218 #454 #3633: opening Settings from the main menu aborts with sceNpAuthCreateRequest not implemented (called from the game, through libSceNpAuth.prx). With this PR applied, Settings opens and the game continues. The merge into current main conflicted only in docs/dev/TechnicalDebt.md and in the test registration in core/libs/CMakeLists.txt; Export.cpp merged cleanly next to #4218.

@adriadam10
adriadam10 force-pushed the feat/libSceNpAuth-complete branch from 28738c7 to 62d1275 Compare October 12, 2026 20:37

@adriadam10 adriadam10 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, and thanks @xXPBSXx, @oneandonlydean and @Pacuka for the review and the Teardown/Minecraft runs. Checked: build and ctest of the rebased branch (87/87 in core/libs), and guest_np_auth fails without the change. I rebased onto main (the debt entries now live in docs/dev/debt/) and added these on top, so merging:

  • Export.cpp: invalid-argument errors now use ORBIS_NP_AUTH_ERROR_INVALID_ARGUMENT (0x80550301), as in shadPS4 np_error.h, in the code, the test and the debt entry.
  • sceNpAuthAbortRequest follows shadPS4: unknown id returns REQUEST_NOT_FOUND, an abort before processing makes the next Get* return ORBIS_NP_AUTH_ERROR_ABORTED (0x80550304), an abort after completion is ignored. Test rows added.
  • docs/dev/debt/libSceNpAuth.md: entry moved there and extended with what is not modelled (INVALID_SIZE checks, REQUEST_MAX).

@adriadam10
adriadam10 merged commit fa0cc75 into boykopovar:main Oct 12, 2026
8 checks passed
adriadam10 pushed a commit to Mouad-Scriptz-0/AnyPS5 that referenced this pull request Oct 12, 2026
…orizedAppCode

There is no PSN sign-in, so the code getter answers SCE_NP_ERROR_SIGNED_OUT
instead of throwing; its parameters are unknown and not read. Minecraft
(PPSA17221) calls it after its sign-in dialog and treats the result as
offline play. The request, token and wait calls are left to boykopovar#3604.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
RINNECODER added a commit to RINNECODER/AnyPS5 that referenced this pull request Oct 13, 2026
* feat(libSceTextToSpeech2): return EOPNOTSUPP from remaining speech exports

Titles that call Open/Speak after a failed initialize should get the same unavailable-engine error instead of a throw.

Co-authored-by: Cursor <cursoragent@cursor.com>
(cherry picked from commit ae425ed)

* fix(net): preserve truncated UDP receives on Windows

(cherry picked from commit 859736a)

* feat(libs): declare the PS VR2 exports PPSA15878 imports

Propagation: Paradise Hotel (PPSA15878) does not load on main: its
executable imports 15 PS VR2 functions that no library exports, the
first reported being sceVrTracker2GetPlayAreaOrientedBoundingBox
(snYs7Nf-RKk). Declare the nine libSceHmd2 reprojection and gaze
exports, three libSceVrTracker2 exports and three scePadVrController
trigger effect exports, without parameters, as throwing stubs. Names
come from the aerolib NID list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit bdf67fc)

* feat(libSceRazorCpu): add sceRazorCpuPushMarker

PPSA04540 (Rise of the Ronin) imports it. Like sceRazorCpuPushMarkerStatic
it does nothing without a capture and returns 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 9f3cc31)

* feat(libSceNgs2): export sceNgs2ReportRegisterHandler and sceNgs2ReportUnregisterHandler

PPSA04540 (Rise of the Ronin) imports both and now loads past them;
calling either throws until NGS2 produces reports.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 295e48f)

* feat(libSceJson2): add sce::Json::Parser::parse with a read callback

PPSA04540 (Rise of the Ronin) imports it. The characters the callback
returns are parsed as by the (text, size) overload.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 95a92f3)

* fix(libSceNpTrophy2): accept a null details or data in GetTrophyInfo and GetGroupInfo

sceNpTrophy2GetTrophyInfo and sceNpTrophy2GetGroupInfo rejected a call
unless both outputs were given, although both already fill each output
only when it is not null. PPSA18391 (Clickteam Fusion) queries trophies
with a null details. Only a call with neither output is rejected now, as
in sceNpTrophy2GetGameInfo.

(cherry picked from commit 69e3c1d)

* refactor(audioin): name X+4jdIS75P0 sceAudioInIsPadEmbeddedMic

(cherry picked from commit 93f5220)

* feat(libc): implement guest fstatvfs volume statistics

(cherry picked from commit 1ead4a1)

* feat(libSceCesCs): add sceCesRefersUcsProfileCp1251 and sceCesMbcsUcsContextInit

PPSA15246 (Teardown) imports both from the module-named libSceCesCs-module and
stops at the loader without them. Cp1251 joins Cp1252 in sceCesSbcToUtf8 and
sceCesUtf8ToSbc; the context initializer succeeds without storing anything
because its layout is unknown (listed in TechnicalDebt.md).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
(cherry picked from commit 6616544)

* build(libc): register filesystem statistics source separately

(cherry picked from commit 5bd43e3)

* feat(libSceAudioIn): implement sceAudioInHqOpen and sceAudioInAsyncOpen

Both open the same SDL capture port as sceAudioInOpen, so Input,
GetSilentState and Close work on their handles. HqOpen accepts only a
128-sample grain at 48 kHz (SharpProspero, KytyPS5); AsyncOpen returns
INVALID_SIZE above 384 samples (SharpProspero). Values the sources
disagree on throw. Format 0x10 still throws: only KytyPS5 accepts it.

Imported by FMOD-based titles, The Smurfs Dreams (PPSA21607) and Astro
Bot (PPSA21564); Ghost of Yotei (PPSA26344) calls sceAudioInOpen.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 16bfdf9)
(cherry picked from commit 9ac583b)

* fix(libkernel): reserve the AMM ranges below host regions at the top of the guest arena

The AMM ranges were reserved at the last 64 GiB of the guest arena and
the reservation threw when that window was not free. On Windows the
stacks of the threads that exist before the arena is reserved (the main
thread and the loader's workers) are placed at random addresses and are
left in the arena as host regions; when one fell in the last 64 GiB, the
first AMM use threw "fixed guest mapping ... overlaps a host region in
the guest arena". Reserve the highest free 64 GiB window instead: the
last 64 GiB when it is free, and the window just below an occupied part
of it otherwise.

(cherry picked from commit 3c6c5d5)

* feat(libSceSigninDialog): complete offline sign-in dialog lifecycle

(cherry picked from commit 4b91755)

* fix(libSceFont): return the letter step of sceFontWritingRefersRenderStepCharacter through a pointer

The second argument is an out pointer to the writing's letter step, as
KytyPS5 and the SharpProspero bindings declare it. It was filled as a
letter step struct, which wrote 64 bytes over the caller's 8-byte
pointer. The letter step now lives in the writing and the call stores
its address, or null when there is no current step.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
(cherry picked from commit b576273)

* feat(libSceNpEntitlementAccess): implement offline entitlement info requests

(cherry picked from commit e6dcb46)

* feat(libSceFont): implement sceFontCharacterGetSyllableStringState

The call was an unimplemented stub. It now writes syllable state 0 and
returns OK for every character outside the Thai block, where a PS4
firmware 11.00 libSceFont measures 1, 3 or 4; Thai characters throw as
not implemented. A null character or result returns
SCE_FONT_ERROR_INVALID_PARAMETER, and a null character writes 0 to a
non-null result, as measured. The signature follows SharpProspero.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
(cherry picked from commit e127a52)

* feat(libSceNet): export sce_net_in6addr_linklocal_allnodes

Co-authored-by: eliasbruno124-dev <230422461+eliasbruno124-dev@users.noreply.github.com>
(cherry picked from commit 4891d62)

* feat(libSceUlt): add underscore mutex and queue create exports

(cherry picked from commit 54b9b93)

* feat(libSceFiber): add the underscore thread frame pointer export

(cherry picked from commit 5f123fd)

* fix(exports): export the calls PPSA07411 imports

PPSA07411 (Resident Evil 4) fails to load without these imports that no library exports. Their signatures are unknown, so they are declared without parameters and throw until they are implemented. Adds one test and a TechnicalDebt entry.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
(cherry picked from commit a03afed)

* feat(libSceAudioOut): implement sceAudioOutSysGetHdmiMonitorInfo

Surround Sound Studio (PPSA99051), catalog build on main a11c8f7 with
the flat-interpolation fix, stops 16 s in, before its first frame
(orishamir, boykopovar#3581 comment 6109839314):

    sceAudioOutSysGetHdmiMonitorInfo not implemented

The call takes (type, out, size); out must be non-null, size exactly
0x180 and type 1 (HDMI) or 0x10 (sainsaji/PS5-Audio-Passthrough-Research
c3be9c2a, docs/FINDINGS.md section 3 and AGENTS.md:25, firmware 12.70).
Titles read the monitor name at +0x0B, the descriptor count at +0x94 and
8-byte descriptors from +0x98 (same, FINDINGS.md hardware log item 1 and
sample-app/src/platform/ps5/bitstream_out.cpp:92-128).

Audio reaches the host through SDL as PCM and there is no EDID, so type 1
with a 0x180-byte buffer reports a sink without a name or descriptors:
the buffer is zeroed and 0 is returned. Surround Sound Studio's
Passthrough page then lists no formats; EVO Player's code treats an empty
list like a negative return. A null buffer returns 0x80260004, as the
other AudioOut calls do. Type 0x10, other types and other sizes throw:
their results and error codes are not known.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit f511809)

* feat(libSceVideoOut): export sceVideoOutAddBufferAttributeOption

Elden Ring Nightreign (PPSA25380) imports the function, which no library
exported, so the title failed to load. The option is ORed into the buffer
attribute and a null attribute throws. Options other than 0 and 8 still
throw when the buffers are registered.

(cherry picked from commit d40189d)

* fix(pad): report special ports as not connected in scePadOpen

scePadOpen returned the standard pad's handle for a special port
(type 2) as well, and scePadGetHandle found it there. Both ports then
read the one input queue, so a press queued between two frames could be
drained by the special port's read and never reach the standard port.
PPSA16827 (Harmony's Odyssey) opens both ports for the initial user and
reads both every frame, also polling controller information and device
class data for the special one.

Special ports now return DEVICE_NOT_CONNECTED (0x80920007) from
scePadOpen, as scePadOpenExt already does because the host has no
special controller, and scePadGetHandle has no handle for them.
TechnicalDebt's scePadOpenExt entry now covers both calls.

guest_pad opens a special port before and after the standard one and
expects DEVICE_NOT_CONNECTED, and DEVICE_NO_HANDLE from scePadGetHandle
for the special port while the standard handle stays valid. It fails on
main.

PPSA16827 over 130 s of its title screen: 6812 scePadRead, 3408
scePadGetControllerInformation and 3406 scePadDeviceClassParseData calls
before, two reads of the same queue per frame; 2702 reads, one
information call and no parse calls after.

(cherry picked from commit 73866db)

* test(libSceLibcInternal): run guest_force_tls_destructor on Windows

sceKernelGetModuleInfoFromAddr has a Windows path since 77ef75c, so
_sceLibcInternalForceTlsDestructor finds each dso's module there too.
The test takes the other module's address with GetProcAddress where
Linux uses dlsym(RTLD_NEXT), and the TechnicalDebt entry no longer says
the call throws on Windows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit c27e67c)

* fix(rtc): recognize additional measured named time zones

Add thirteen offsets measured repeatedly on PS5 firmware 13.42, keeping DST names ahead of their shorter prefixes. Cover case folding, prefix matching and a second valid date.

Written with AI assistance; validated against real hardware and the guest RTC tests.

(cherry picked from commit 4d15f9e)

* fix(libSceUserService): report an unrestricted age level

sceUserServiceGetAgeLevel reported 0. On a PS5 (firmware 13.60) the
value is the age of the user's parental restriction (0, 7, 12 and 15
measured) and 0xFFFFFFFF without one, so 0 is a user restricted to age
0. A user who is not logged in returns 0x80960009 (not logged in) with or
without an output, before the null output check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit d5f11b1)

* fix(libSceNet): accept guest socket addresses whatever their sa_len

(cherry picked from commit 2d3dd33)

* feat(libSceSysmodule): register libSceAudioPropagation module ID (0x120)

(cherry picked from commit 5d298b6)

* feat(input): configure stick deadzones and mouse sensitivity

anyps5-input.ini accepts LeftStickDeadzone and RightStickDeadzone (whole
percent, 0 to 90), a radial deadzone on the controller sticks whose
remaining travel is rescaled to the full range, and MouseSensitivity
(above 0, at most 10), which replaces the fixed factor of 1 for mouse
look. The defaults keep the current mapping exactly.

(cherry picked from commit 3c58161)

* fix(exports): export the PS VR2 calls PPSA07411 imports that no library has

PPSA07411 (Resident Evil 4) fails to load without these imports. Their signatures are unknown, so they are declared without parameters and throw until they are implemented. Adds a TechnicalDebt entry.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
(cherry picked from commit 1b7e842)

* feat(libSceContentExport): implement the export session calls

sceContentExportStart hands out positive session ids, at most 10 live
(SharpProspero MaxExecution), and sceContentExportFinish closes them.
sceContentExportGetProgress, sceContentExportCancel and
sceContentExportFromDataWithThumbnail take their Orbital signatures and
check the session. The host has no media library to export into, so
FromDataWithThumbnail throws before it calls either data callback, and
GetProgress and Cancel throw for a live session since no export ever
runs and their result for an idle session is unknown. An eleventh Start
and Term with live sessions throw.

Titles: Cult of the Lamb PPSA06465 imports GetProgress, Cancel and
FromDataWithThumbnail (boykopovar#2686); PPSA21564 (#271) and Cyberpunk 2077
PPSA04029 (#266) import Start.

Sources: Orbital tools/ida/db_types.json (cc408367) for the signatures,
SharpProspero Interop/Content/ContentExport.cs (5dfdb4b0) for the
session model and MaxExecution, shadPS4 content_export.h (443f0224) for
the parameter and callback layouts.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 473d6dd)
(cherry picked from commit 6ce1240)

* test(libSceSysmodule): verify handle and symbol resolution for libSceAudioPropagation

(cherry picked from commit 7cf2ee8)

* fix(libSceVideoOut): return INVALID_HANDLE for events on ports that are not open

Registering a flip or vblank event on a handle that sceVideoOutOpen never
created, or that was closed, threw, which ended titles that register
their flip event before they open the port and ignore the result. The
documented error SCE_VIDEO_OUT_ERROR_INVALID_HANDLE is returned instead,
the same check sceVideoOutSetFlipRate and the other output calls use.

The flip test program gains an "unopened" mode.

(cherry picked from commit 43573fd)

* fix(libSceNgs2): report EMPTY for a streaming sampler that played its queue

A playing sampler voice whose waveform still accepts blocks (CONTINUE)
reported only INUSE|PLAYING after it had played every queued block, so
a title that waits for EMPTY before it reuses the voice never did.
PPSA18391 (engine: Clickteam Fusion) reads state_flags & 0x22 != 2 from
sceNgs2VoiceGetState as the end of a sound; each of its sound effects
played once and never again.

The voice now also reports EMPTY (0x20) in that state and keeps
playing, so blocks added later still play. A waveform that was closed
without CONTINUE does not report it.

(cherry picked from commit 2335904)

* fix(exports): also export sceHmd2GetFieldOfView

main has sceHmd2GetFieldOfViewWithoutHandle only; PPSA07411 imports sceHmd2GetFieldOfView.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
(cherry picked from commit 859d0b1)

* feat(libSceSysmodule): register libSceVoiceChat module ID (0x114)

(cherry picked from commit 567898c)

* fix(libSceNet): report EAGAIN when a datagram receive times out on Windows

With SO_RCVTIMEO set, Winsock fails a receive that waits that long with
WSAETIMEDOUT, which native_error turned into ETIMEDOUT (60). sceNetRecv,
sceNetRecvfrom and sceNetRecvmsg on a datagram socket therefore failed
with 0x8041013C on Windows, where FreeBSD's sbwait returns EWOULDBLOCK
(35) to soreceive, Linux returns EAGAIN, and POSIX (XSH 2.10.16)
requires EAGAIN or EWOULDBLOCK when no data was received.

A datagram socket has no connection that can time out, so WSAETIMEDOUT
there only means that the receive timeout the guest set has expired:
report EAGAIN. Stream sockets keep ETIMEDOUT, since Winsock leaves a
connection in an indeterminate state after a timeout; TechnicalDebt
records that gap and the one for SO_SNDTIMEO.

(cherry picked from commit f7a8549)

* fix(libSceUserService): answer sceUserServiceGetUserName as the console does

On a PS5 (firmware 13.60) a null name returns INVALID_ARGUMENT first,
then a user id the console does not know returns 0x80960105 whatever
the buffer, and a buffer shorter than 17 bytes is zeroed before
BUFFER_TOO_SHORT is returned. Here an unknown user returned
INVALID_ARGUMENT and a short buffer was left untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 802ec55)

* fix(libSceNet): sceNetEpollControl takes 2 as MOD and 3 as DEL

sceNetEpollControl used Linux's EPOLL_CTL numbering (1 ADD, 2 DEL, 3 MOD).
The SCE values are 1 ADD, 2 MOD, 3 DEL (shadPS4 net_types.h,
ORBIS_NET_EPOLL_CTL_*). A title removing a socket with op 3 and a null
event got EINVAL, and op 2 deleted the registration it meant to modify.
PPSA01289 (Sackboy: A Big Adventure) removes its UDP socket from its epoll
this way before closing it, every time its network session is torn down.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 22827bf)

* fix(libSceNet): failures also set libkernel's errno

libSceNet stored its errno only in its own slot (sceNetErrnoLoc). Titles
that use the BSD socket model read errno after a libSceNet call, as the
console's libSceNet calls are kernel calls that set it; shadPS4 mirrors its
net errno into the kernel errno the same way (SetKernelErrnoHook).

PPSA01289 (Sackboy: A Big Adventure) reads errno through Unreal's
GetLastErrorCode after sceNetRecvfrom. It never saw EWOULDBLOCK, so
UIpNetDriver::TickDispatch kept receiving and the game thread never left
its first networked frame.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 5d14cd0)

* feat(libSceNpWebApi2): export sceNpWebApi2AddWebTraceTag

PPSA33016 imports sceNpWebApi2AddWebTraceTag (NID MgsTa76wlEk), and no
library exported it, so the loader stopped before the title started.
The title does not call it at start-up or in play, so the export throws
like the other unimplemented functions.

(cherry picked from commit 2fd05f4)

* fix(libSceUserService): report the console's default accessibility settings

On a PS5 (firmware 13.60) a user with every accessibility setting at
its default reads chat transcription 0, press-and-hold delay 0, trigger
effect 1, vibration 1, zoom 0 and zoom follow focus 1; all six read 0
here. A user who is not logged in returns 0x80960009 with or without an
output, as sceUserServiceGetAgeLevel does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 78abb2b)

* fix(libSceSystemService): answer parameter 400 with the console language

(cherry picked from commit b843b16)

* fix(libScePosixForWebKit): use FreeBSD's gai_strerror message texts

gai_strerror returned its own wording for most codes, so a resolver
failure was described with text FreeBSD's libc does not use: EAI_NONAME
(8) gave "Name or service not known" instead of "hostname nor servname
provided, or not known", EAI_BADFLAGS (3) "Invalid flags" instead of
"Invalid value for ai_flags", and an unknown code "Unknown address
resolution error" instead of "Unknown error". Twelve of the fifteen
texts differed.

FreeBSD 11.4, lib/libc/net/gai_strerror.c:

	static const char *ai_errlist[] = {
		"Success",					/* 0 */
		"Address family for hostname not supported",	/* 1 */
		"Temporary failure in name resolution",		/* EAI_AGAIN */
		"Invalid value for ai_flags",			/* EAI_BADFLAGS */
		"Non-recoverable failure in name resolution",	/* EAI_FAIL */
		"ai_family not supported",			/* EAI_FAMILY */
		"Memory allocation failure", 			/* EAI_MEMORY */
		"No address associated with hostname",		/* 7 */
		"hostname nor servname provided, or not known",	/* EAI_NONAME */
		"servname not supported for ai_socktype",	/* EAI_SERVICE */
		"ai_socktype not supported", 			/* EAI_SOCKTYPE */
		"System error returned in errno", 		/* EAI_SYSTEM */
		"Invalid value for hints",			/* EAI_BADHINTS */
		"Resolved protocol is unknown",			/* EAI_PROTOCOL */
		"Argument buffer overflow"			/* EAI_OVERFLOW */
	};
	...
	if (ecode >= 0 && ecode < EAI_MAX)
		return ai_errlist[ecode];
	return "Unknown error";

The table and the unknown-code text now match, as 5830d8e did for
strerror.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 30d1e85)

* test(avplayer): link guest_avplayer with the shared runtime libraries

guest_avplayer_tests imports __cxa_throw from libc.prx, which is loaded
before libstdc++, but -static-libgcc gave it a private copy of
_Unwind_Resume. A failed Check threw through libc.prx's unwinder and the
landing pad of the test function resumed with the private one, so on
Linux every failure aborted in _Unwind_RaiseException_Phase2 instead of
printing its message from main. This is the unexplained Linux abort in
the intermittent guest_avplayer failures.

The test is now linked without the static runtime flags, as the AgcDriver,
Agc and VideoOut tests already are, so the unwinder comes from the same
library as __cxa_throw. A forced Check failure in TestPlayback aborted
before and now prints its message and exits with 1.

(cherry picked from commit fa5199c)
(cherry picked from commit 5959506)

* fix(libSceAmpr): export sceAmprAmmSetPageTablePoolOccupancyNotificationThreshold

Resolves NID touqMEt6qXQ, the last import Trails in the Sky 2nd Chapter
(PPSA35169) is left missing on libSceAmpr.prx once the libkernel pair in boykopovar#4214
is recorded. No reference describes the function's contract, so it throws via
the project's NotImplemented_nid_no_patch pattern rather than guessing a result
that a caller would act on.

sceAmprAmmGetUsageStatsData (KqiWXLgCVe0) is deliberately not included: boykopovar#3814
exports it and boykopovar#4207 answers it from a cited layout.

See issue boykopovar#4214.

(cherry picked from commit ef3b121)

* feat(libSceVoiceQoS): export sceVoiceQoSSetConnectionAttribute

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit bad49ba)

* fix(videodec2): answer picture info from the decoder that last wrote the buffer

sceVideodec2GetPictureInfo searched the live decoders in handle order and
returned the first one that had ever written the queried frame buffer. When
two decoders wrote the same address, the lower handle answered with stale
timestamps, a stale AVC decoder answered for an HEVC or VP9 picture, a stale
HEVC or VP9 decoder made an AVC query throw, and resetting or deleting the
decoder that wrote the buffer last exposed the older decoder's picture again.

Record the decoder that last published a picture into each frame buffer and
answer from that decoder only. Reset and Delete drop only the decoder's own
records, so another decoder's picture is never removed or brought back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 48919d0)

* feat(libSceHttp2): implement sceHttp2DeleteCookieBox

PPSA35943 (Graveyard Keeper 2) imports sceHttp2DeleteCookieBox, which no
library exported. On current main the loader stops the title there:

  ./eboot.elf: symbol lookup error: ./eboot.elf: undefined symbol:
  O9ync3F-JVI

sceHttp2DeleteCookieBox(cookieBoxId) erases the box from the handle
registry sceHttp2CreateCookieBox adds it to and returns 0, or the
library's invalid-id error (0x817B1100) for an id that is not a live
cookie box. The signature follows SharpProspero and the behaviour
prosper's sceHttp2DeleteCookieBox; the error code is listed in
TechnicalDebt as not measured on a console.

guest_http2 deletes a box twice, a context id, a box whose context was
terminated, and the two boxes it uses before sceHttp2Term.

With this change the title loads and runs into its asset loading.

(cherry picked from commit ce0915e)

* feat(libSceNgs2): implement the Geom reset functions

Implement sceNgs2GeomResetListenerParam and sceNgs2GeomResetSourceParam,
taken from boykopovar#1021 and limited to the two reset functions. The Geom
structures get their real layouts. sceNgs2GeomCalcListener and
sceNgs2GeomApply stay unimplemented.

Co-Authored-By: Dextroid17 <217507631+Dextroid17@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit cac398c)

* feat(libSceSysmodule): register libSceAcm (0x10B) and libScePsml (0x137) module IDs

(cherry picked from commit 94f06ce)

* fix(libSceWebBrowserDialog): permit termination from finished state in sceWebBrowserDialogTerminate

(cherry picked from commit 98e0fb0)

* feat(libc): query filesystem statistics by guest path

(cherry picked from commit c052b7c)

* feat(libSceNetCtlApDialog): run the offline access-point dialog lifecycle

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit dbecde0)

* fix(exports): export the calls PPSA02530 imports

PPSA02530 (PRAGMATA) fails to load without these imports that no library exports. Their signatures are unknown, so they are declared without parameters and throw until they are implemented. Adds a TechnicalDebt entry.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
(cherry picked from commit 147c0db)

* feat(libSceVoiceQoS): implement sceVoiceQoSEnd

End clears the init flag set by sceVoiceQoSInit and returns 0, so the
library can be initialized again. Before an initialization it returns
0x804E0901 (LIBVOICEQOS_NOT_INIT), as measured on a PS5 (firmware 13.60)
in boykopovar#1407.

LEGO Horizon Adventures (PPSA14632) calls it at shutdown and Ghost of
Yotei (PPSA26344) calls it on its sceVoiceQoSInit failure branch.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 25fbc94)
(cherry picked from commit 5164f78)

* fix(savedata): fill the search infos of sceSaveDataDirNameSearch

SaveDataDirNameSearchResult.infos points at an array the title reads one
entry per returned directory name, but the search never wrote it, and
SaveDataSearchInfo was declared as 128 opaque bytes. A title that asks for
the infos read whatever its buffer held.

SaveDataSearchInfo is now the 48-byte record shadPS4 declares as
OrbisSaveDataSearchInfo (blocks, free blocks, 32 reserved bytes), and the
search fills one per returned name. Every native save reports
SAVE_DATA_BLOCKS_MAX blocks, as sceSaveDataGetMountInfo and the block sort
keys already assume, so both counts are SAVE_DATA_BLOCKS_MAX and the
reserved bytes are zero.

guest_savedata_search_tests checks the two records, their zero reserved
bytes and that the search writes nothing past them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VFVE5WbaUJ2vyj8NAW44CS
(cherry picked from commit 4b125c0)

* fix(savedata): let a trailing % in a directory name pattern match nothing

sceSaveDataDirNameSearch reads % in the directory name pattern as any
run of characters and _ as one character. The matcher stopped when the
name ran out and then required the pattern to have ended too, so a
trailing % with nothing left to match failed: SAVEDATA% did not find a
save named SAVEDATA, and TRAI_% did not find TRAIL. A % now matches no
characters at the end of a name as it already did in the middle.

(cherry picked from commit 12ef40e)

* fix(ampr): reject command buffer offsets beyond bound memory

(cherry picked from commit b92287d)
(cherry picked from commit c20583b)

* feat(libSceLibcInternal): implement getopt and getopt_long

Export getopt (VUtibKJCt1o) and getopt_long (8VVXJxB5nlk) from
libSceLibcInternal together with the guest variables optind
(zCnSJWp-Qj8), optarg (zG0BNJOZdm4), opterr (yaFXXViLWPw), optopt
(FwzVaZ8Vnus) and optreset (CZNm+oNmB-I). The NIDs were computed with
tools/nid_names.py and all seven are in aerolib; the PS5 payload SDK
f5d40f02 lists the functions and the five objects in
sce_stubs/libSceLibcInternal.c.

Titles (predicted stops from registry order, not observed runs):
- XPSemu PPSA97358, after execv/execve, the signal waits, the
  credential setters, mlockall and tcsendbreak:
  "FAIL: unresolved ELF import VUtibKJCt1o from libSceLibcInternal.prx"
  (getopt idx 204, 10 call sites from 0xF6C23D), then optind (207),
  optreset (208), optarg (209).
- RetroArch PPSA99169: getopt_long (idx 554, call sites 0xD2FC0C,
  0xD3002A), optind (553), optarg (555).

Behaviour follows FreeBSD release/11.4.0 8c639945: getopt is
lib/libc/stdlib/getopt.c (no permutation, GNU "::" optional argument,
lone "-" as an option when listed), getopt_long is getopt_internal
from lib/libc/stdlib/getopt_long.c with GNU_COMPATIBLE (permutation,
POSIXLY_CORRECT read through the guest getenv on the first call and on
optreset, "+" and "-" prefixes, "W;", optind 0 as a reset, abbreviation
and ambiguity rules and the GNU warning texts). Warnings are written to
the guest stderr stream as "<__progname>: <message>", as warnx does.
The struct option layout and argument kinds are include/getopt.h.
The code lives in libSceLibcInternal because __progname is a libkernel
export that libc cannot link.

A null getopt option string, a null argument vector or argument, a
negative optind and an optind moved inside a pending permutation throw
where FreeBSD faults. getopt_long_only is not exported.

guest_getopt runs the FreeBSD getopt_test cases (contrib/netbsd-tests
t_getopt.sh with the h_getopt and h_getopt_long result format) plus
grouped and optional arguments, "--", permutation order, "+" and "-"
prefixes, optreset and optind 0 restarts, POSIXLY_CORRECT, all three
long argument kinds, abbreviations, ambiguity, flag pointers, "W;",
optopt with opterr 0 and the exact stderr text.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit a274016)
(cherry picked from commit 1d67426)

* feat(libSceNpPartner001): implement sceNpEAAccessInitialize and sceNpEAAccessTerminate

UFC 6 (PPSA23566) imports both. Initialization marks the library
initialized and termination clears it, as in shadPS4. Termination
without initialization and a second initialization throw, since no
PS5 source settles their results.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit d2866a8)
(cherry picked from commit e2954aa)

* feat(libSceShare): implement sceShareCaptureVideoClipExtended

Imported by the Share plugin of Hollow Knight: Silksong (PPSA12544).
Takes the extended parameter and request id like
sceShareCaptureScreenshotExtended, as KytyPS5 does: nothing is
captured, so it stores the invalid request id -1 when the pointer is
not null and returns NOT_SUPPORTED.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 2450909)
(cherry picked from commit f3a6edf)

* feat(libSceContentSearch): implement the search calls over an empty library

Cult of the Lamb (PPSA06465) imports libSceContentSearch, including
sceContentSearchGetContentLastUpdateId, OpenMetadataByContentId,
GetTotalContentSize and GetNumOfContent (import audit in boykopovar#2686), which
were declared without parameters and threw.

Give the nine pending calls the signatures of AlexAltea/orbital
db_types.json (cc408367, lines 555-569) and SharpProspero
Interop/Content/ContentSearch.cs (5dfdb4b0), and implement the content
library the host has, which is empty:

- GetNumOfContent, GetTotalContentSize and SearchContent report 0 rows
  and 0 bytes, GetContentLastUpdateId and the search calls report update
  id 0. A search limit above 92 returns 0x809D100A and every call before
  Init returns 0x809D1001, both from SharpProspero.
- Filters and sort conditions use SharpProspero's layouts (added to
  SceTypes.hpp with size checks) and are checked against its enums;
  unknown values, null outputs and null arrays with a length throw.
- OpenMetadata and OpenMetadataByContentId throw, as no source gives the
  error for content that is not in the library, so no metadata id is
  handed out and CloseMetadata, GetMetadataFieldInfo and
  GetMetadataValue throw too.

The update id value, the argument errors and the check order are
recorded in TechnicalDebt. The four ContentSearch calls leave the
unimplemented-imports test, and guest_content_search covers the library.

(cherry picked from commit 1c7a830)

* fix(exports): export the calls PPSA29866 imports

PPSA29866 (Tomba! 2) fails to load without these imports that no library exports. Their signatures are unknown, so they are declared without parameters and throw until they are implemented. Adds a TechnicalDebt entry.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
(cherry picked from commit 0485570)

* feat(libSceNpEntitlementAccess): implement sceNpEntitlementAccessGetGameTrialsFlag

PRAGMATA (PPSA02530) calls it after sceRazorCpuSync and stops on main
with "sceNpEntitlementAccessGetGameTrialsFlag not implemented". From
called once; I logged four register values but cannot tell which are
arguments. Answering 0 without writing anything carried on." Killing
Floor 3 (PPSA08427) and RE4 also import it.

The title is reported as a full game, not a game trial: 0 is written to
the uint32_t output and 0 returned; a null pointer returns 0x817D0002.
Signature, value, one-word write and error follow sharpemu
src/SharpEmu.Libs/Np/NpEntitlementAccessExports.cs:98-116 and its test
NpEntitlementAccessExportsTests.cs:16-36 (a2983692930564815a77f81e74c151268f5b935f),
used as a source of facts; 0x817D0002 is also the parameter error of
KytyPS5, prosper and sceNpEntitlementAccessGetEntitlementKey here. The
library has no initialization state, so none is checked. The NID
y7JD1gfwyfA hashes from the name and is in aerolib. Unverified points
are in TechnicalDebt.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 5690b84)

* feat(libSceUlt): accept option parameters in sceUltQueueCreate and sceUltQueueDataResourcePoolCreate

(cherry picked from commit 0634b44)

* feat(libSceNpSessionSignaling): answer connection status queries offline

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 3fa1fe3)

* feat(libSceNgs2): calculate the listener coordinate transform

(cherry picked from commit 4168cf3)

* fix(libSceNgs2): reject unverified listener transforms

(cherry picked from commit dadc23a)

* feat(libSceAmpr): implement _Cnd_signal and _Cnd_init_with_name

Deathloop (PPSA01670), Minecraft Legends (PPSA05510) and GTA III
Definitive Edition import both from libSceAmpr. They take a pointer to
the handle slot and act on the conditions created by the libc _Cnd_init:
_Cnd_signal wakes one waiter through a libc helper, _Cnd_init_with_name
is _Cnd_init with the name ignored. _Thrd_id still throws.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit dce1747)

* feat(libSceAmpr): implement std::_Throw_Cpp_error

Throw a guest std::system_error for the Dinkumware _Cpp_error codes,
as in VC12 and microsoft/STL thread0.cpp: the error_code holds the
FreeBSD errno and a guest generic error category modelled in libc, and
what() is the table message followed by the category message. Codes
outside the table throw std::out_of_range. The system_error copy
constructor and assignment now copy the error_code too.

Imported by Deathloop (PPSA01670) and Minecraft Legends (PPSA05510).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit bed1dea)
(cherry picked from commit 2dc4d9d)

* feat(libSceAcm): implement sceAcm_FFT and sceAcm_Panner

(cherry picked from commit 86bd3b6)

* fix(exports): export the calls PPSA30601 imports

PPSA30601 (Resonance: A Plague Tale Legacy) fails to load without these imports that no library exports. Their signatures are unknown, so they are declared without parameters and throw until they are implemented. Adds a TechnicalDebt entry.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
(cherry picked from commit d7bf16a)

* fix(libkernel): close() closes libSceNet sockets

A libSceNet socket is a kernel descriptor on the console, so titles close it
with close(). libSceNet keeps its sockets in its own table, and libkernel's
close passed their numbers to the CRT, which reported an invalid parameter
and left the socket open. libSceNet now registers a closer with libkernel,
as it registers its poller for select. PPSA01289 (Sackboy: A Big Adventure)
closes its P2P socket this way each time it tears its network session down,
leaking one open socket per attempt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 12b18af)

* fix(libkernel): setsockopt sets options of libSceNet sockets

A title creating a socket with sceNetSocket sets its options with the BSD
setsockopt, which looked the descriptor up only among libkernel's own
sockets and returned EBADF. libSceNet now registers an option setter with
libkernel, as it does for close and select, and accepts SO_REUSEADDR,
SO_BROADCAST, SO_SNDBUF and SO_RCVBUF like libkernel's own sockets.

PPSA01289 (Sackboy: A Big Adventure) sets SO_BROADCAST on its UDP P2P
socket this way in UIpNetDriver::InitBase. The failure made every listen
fail, and the engine travelled back to its default map with ?closed,
reloading it about every two seconds behind the loading screen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit d5805fb)

* fix(libs): take guest entropy from the host OS instead of std::random_device

std::random_device in libstdc++ reads RDSEED on x86 Linux. On an AMD
EPYC 9V45 (Zen 5) CI runner its 32-bit results repeat about 130 times
in 65536 draws, so guest_posix_random fails. libc now exports
HostEntropy_nid_no_patch, which uses getentropy (rand_s on Windows) and
throws when the OS cannot provide entropy. arc4random, arc4random_buf,
sceRandomGetRandomNumber, /dev/random and /dev/urandom reads,
std::_Random_device and sceKernelUuidCreate use it, and the arc4random
and random device TechnicalDebt entries say so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 8f9efc2)

* feat(pad): hold the sticks from the controller command file

(cherry picked from commit e0eef6c)

* fix(libSceNet): preserve successful stream recvfrom results

(cherry picked from commit 74defef)

* fix(libSceNet): read setsockopt timeouts as struct timeval

libkernel's setsockopt() hands options for a libSceNet socket to
sceNetSetsockopt(), whose SO_RCVTIMEO and SO_SNDTIMEO take an int of
microseconds. The POSIX call takes a struct timeval, so main read the
low half of tv_sec as microseconds: {1, 250000} set a 1 microsecond
receive timeout, {0, 500000} set 0, which disables the timeout, and an
out-of-range tv_usec was accepted.

FreeBSD reads a struct timeval, sys/kern/uipc_socket.c, sosetopt():

	case SO_SNDTIMEO:
	case SO_RCVTIMEO:
	...
		error = sooptcopyin(sopt, &tv, sizeof tv,
		    sizeof tv);
	if (error)
		goto bad;
	if (tv.tv_sec < 0 || tv.tv_usec < 0 ||
	    tv.tv_usec >= 1000000) {
		error = EDOM;
		goto bad;
	}

and sooptcopyin() fails a shorter value with EINVAL:

	if ((valsize = sopt->sopt_valsize) < minlen)
		return EINVAL;

setsockopt() on a libSceNet socket now converts the timeval for these
two options, with EINVAL for a short value and EDOM for a negative or
out-of-range one. sceNetSetsockopt() keeps taking microseconds; both
paths share the code that sets the host timeout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit e9c5ae2)

* feat(libSceNpAuthAuthorizedAppDialog): add the dialog, with NpAuth and SaveData imports of Minecraft

Minecraft (PPSA17221) fails to load on nine absent imports. The authorized-app
dialog runs the common-dialog state machine without UI and reports the user
as having cancelled, like the login and VR setup dialogs. The other two,
sceNpAuthGetAuthorizedAppCode and the unnamed libSceSaveData.native NID
RvID8BVeg+g, are declared as throwing stubs with unknown signatures.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 295e6b5)

* feat(libSceAmpr): answer sceAmprAmmGetUsageStatsData

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
(cherry picked from commit 4b6f463)

* feat(libSceRazorCpu): implement sceRazorCpuSync

PRAGMATA (PPSA02530) imports sceRazorCpuSync (NID Ax7NjOzctIM), which no
library exports on main, so the load fails on the unresolved import. The
title calls it after sceConvertKeycodeGetCharacter. From boykopovar#3043 (comment
6106731532): "`sceRazorCpuSync`: answering 0 and doing nothing was
enough to carry on (the other `sceRazorCpu*` calls in `main` are no-ops
without a capture)."

SharpProspero src/SharpProspero/Interop/Debug/RazorCpu.cs:119-122
(5dfdb4b0b166e83dc9ae275001afb695f12c7174, GPL-3.0, used as a source of
facts) gives int sceRazorCpuSync(void), an unnamed frame-boundary event.
Without a capture there is no event to record, so it returns 0 and does
nothing, like the other sceRazorCpu markers here and the shadPS4 stub
(razor_cpu.cpp:143, 3a9f57265d28975658f1ca941daa5c879c7a74bd). The NID
hashes from the name and is in aerolib. Unverified points are in
TechnicalDebt.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 4ab6a04)

* feat(libSceSharePlay): implement sceSharePlayProhibitController

PRAGMATA (PPSA02530) imports sceSharePlayProhibitController (NID
FzQS6DREDfk), which no library exports on main, so the load fails on the
unresolved import. It is one of the "six declared-only imports" of
xXPBSXx's branch in boykopovar#3043 (comment 6107100345): "These only stop the
load failure; as described above, the title calls some of them later and
needs their real behavior."

sharpemu src/SharpEmu.Libs/Share/SharePlayExports.cs:9-31
(a2983692930564815a77f81e74c151268f5b935f, used as a source of facts)
takes one value, accepts 0 and 1 and returns 0. Nothing here would read
the setting, as no Share Play session or visitor controller exists, so
it is not stored. sharpemu rejects other values with its synthetic
0x80020003, not a Share Play code, so they throw, as
sceSharePlayInitialize does for its unknown error. Like the other exports
of the library it does not check initialization. The NID hashes from the
name and is in aerolib. Unverified points are in TechnicalDebt.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 9698804)

* feat(libSceNet): implement sceNetResolverAbort and sceNetResolverStartNtoaMultipleRecords

UFC 6 (PPSA23566) imports sceNetResolverAbort (boykopovar#992, boykopovar#1502); Palworld
(PPSA23126) and LEGO Horizon Adventures (PPSA14632) import
sceNetResolverStartNtoaMultipleRecords.

Signatures and behaviour follow shadPS4 811bfcd7d17e
(src/core/libraries/net/net.cpp, net_resolver.cpp); the abort signature
also matches SharpProspero Interop/Net/Socket.cs.

sceNetResolverStartNtoaMultipleRecords shares the lookup of the Ex form
and, like it, throws for any flag. sceNetResolverAbort returns EBADF for
an unknown resolver and throws for flag bits other than NTOA (1) and
ATON (2) preservation. Host lookups cannot be interrupted, so an abort
during a running lookup makes it fail with EINTR when the host call
returns, without writing its output; with nothing running, the
preservation flags make the next lookup of that kind fail with EINTR.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit bcc8be8)
(cherry picked from commit 3d64981)

* feat(libSceNpAuth): complete offline request lifecycle following shadPS4

(cherry picked from commit 62d1275)

* feat(libSceNpAuth): return the signed-out error from sceNpAuthGetAuthorizedAppCode

There is no PSN sign-in, so the code getter answers SCE_NP_ERROR_SIGNED_OUT
instead of throwing; its parameters are unknown and not read. Minecraft
(PPSA17221) calls it after its sign-in dialog and treats the result as
offline play. The request, token and wait calls are left to boykopovar#3604.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 09c9854)

* feat(libSceSaveData): answer sceSaveDataDirNameSearch2

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
(cherry picked from commit 989504e)

* fix(libs): build the statvfs path statistics on macOS without O_PATH

macOS has no O_PATH; fall back to a plain read-only open and treat sockets as
unsupported in fstatfs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Drop functions duplicated by the main merge (RazorCpu, Acm)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: notaxeltv <notaxeltv@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: ArjenS-LA <arjensingh@outlook.com>
Co-authored-by: hugodearaujo <hugoaraujocamara@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: EdouardSence <103503538+EdouardSence@users.noreply.github.com>
Co-authored-by: Simon <340958984+ee6aba54@users.noreply.github.com>
Co-authored-by: Josip Parlov <josipparlov@protonmail.com>
Co-authored-by: lorkydey <57268822+Lorkydey@users.noreply.github.com>
Co-authored-by: xXPBSXx <20614131+xXPBSXx@users.noreply.github.com>
Co-authored-by: David <david@example.com>
Co-authored-by: Zurisen <carlosmarctor@gmail.com>
Co-authored-by: virp-mta <vaqrux1@gmail.com>
Co-authored-by: JAB-dev <68183649+JAB-dev@users.noreply.github.com>
Co-authored-by: overlordxrz-source <overlordxrz-source@users.noreply.github.com>
Co-authored-by: eliasbruno124-dev <230422461+eliasbruno124-dev@users.noreply.github.com>
Co-authored-by: Semir Kabir <66262518+semirkabir@users.noreply.github.com>
Co-authored-by: screamm <davidrydgren@gmail.com>
Co-authored-by: omurc4 <omurc4@gmail.com>
Co-authored-by: gookie <36005381+gookie-dev@users.noreply.github.com>
Co-authored-by: LeandroLP23 <leandroplacidi@gmail.com>
Co-authored-by: Zayd Zaari <110066668+zaydzaari@users.noreply.github.com>
Co-authored-by: Jordan Hans <jordan.hans@ymail.com>
Co-authored-by: Kikoarl <7354010+Kikoarl@users.noreply.github.com>
Co-authored-by: dantdmdarealguy <vaibhav.vaidish.898@gmail.com>
Co-authored-by: Yunus Shaikh <75296019+yunusshaikh7@users.noreply.github.com>
Co-authored-by: jdmagic <jdsiegle14@gmail.com>
Co-authored-by: fma-rc <188743521+fma-rc@users.noreply.github.com>
Co-authored-by: milescoviello <kitslayer29@gmail.com>
Co-authored-by: Yassine <yassinkokabi4@gmail.com>
Co-authored-by: Dextroid17 <217507631+Dextroid17@users.noreply.github.com>
Co-authored-by: Tyler Westerberg <tylerwesterberg05@gmail.com>
Co-authored-by: muhzain05 <muhammadzainasad6@gmail.com>
Co-authored-by: Del'aRun <zadli@evileat.org>
Co-authored-by: Nithishvelan M <mnithishvelan@gmail.com>
Co-authored-by: p3nicillin <lcmcclellan12@gmail.com>
Co-authored-by: pallp <pallhansen01@gmail.com>
Co-authored-by: Blazing Cook <>
Co-authored-by: lorkydey <lorky.contact@gmail.com>
Co-authored-by: jagrat Singh <jagratsingh9899@gmail.com>
Co-authored-by: winstrex <79346005+winstrex@users.noreply.github.com>
Co-authored-by: Aarav <211792885+AaravMehta-07@users.noreply.github.com>
Co-authored-by: Mouad-Scriptz-0 <mouadscriptz@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build docs needs rebase Conflicts with main, rebase needed prx

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants