357 KiB
Project technical debt
Build
- Building on Windows requires a specific version of mingw - MinGW-w64 GCC 15.2.0 (
winlibs-gcc15,x86_64-ucrt-posix-seh) - Even compiled prx libraries on Windows require nearby (static linking of these dependencies causes conflicts):
- libgcc_s_seh-1.dll
- libstdc++-6.dll
- libwinpthread-1.dll
- winpthreads initializes a statically initialized rwlock on its first lock and fails a concurrent first lock with
EINVAL, whichstd::shared_mutexandstd::shared_timed_mutexignore, so that lock does not exclude. Guest rwlocks (Pthread.hpp) are locked once when created. The hoststd::shared_mutexobjects in Recompiler.cpp and GuestWriteWatch.cpp are not, and can still race on their first contended use.
Silent stubs
Throughout the project, every function at every stage either does exactly what it's supposed to or throws an exception. Everywhere... except:
- libSceSaveDataDialog.native shows no UI and ignores progress values. Progress-bar mode (5) stays running until the caller closes it, matching Skyrim PPSA03747's save sequence; other modes still finish immediately and return button 1 and the first nonempty directory name. Console dialog timing and selection behavior remain unverified.
- libSceMsgDialog.native - dialogs finish at
sceMsgDialogOpenwithout UI and answer with button 1, sosceMsgDialogClosereturnsNOT_RUNNING; its result beforesceMsgDialogInitializefollows libSceMsgDialog - libSceCommonDialog
- libSceErrorDialog - the error dialog runs the state machine but shows nothing; the error code passed to
sceErrorDialogOpenis only logged - libSceLoginDialog - the login dialog runs the common-dialog state machine but shows nothing and reports the user as having cancelled
- libSceCdlgG2P - the G2P dialog runs the common-dialog state machine but shows nothing and reports the user as having cancelled. The signatures (
OpenandGetResulttake a pointer, the others none) and the leadingint32result are assumed from the other common dialogs, not verified for G2P; PPSA01289 imports it - libSceVrSetupDialog - the VR setup dialog runs the common-dialog state machine but shows nothing and reports the user as having cancelled, as no headset is supported (see libSceHmd2). The signatures are assumed from the other common dialogs; PPSA12544 imports it
- libSceHmd implements only the disconnected-headset path: initialization succeeds, device queries report
NotDetected, and opening a device returnsDeviceDisconnected. Headset support, tracking, rendering and additional HMD exports are not implemented; SDK-level ABI compatibility and in-game behaviour remain unverified. - pthread_mutexattr_setprotocol, pthread_mutexattr_setprioceiling, pthread_mutexattr_getprioceiling (libkernel) - the protocol and the priority ceiling are stored and reported as in FreeBSD's libthr (the ceiling is set or read only under
PTHREAD_PRIO_PROTECT, and setting a protocol resets it to the highestSCHED_RRpriority), but mutexes do not apply them: a priority-inherit or priority-protect mutex locks like a normal one and does not change its owner's priority - libSceHmd2 has no PS VR2 runtime:
sceHmd2Initializefails, and every other export it has (and every libSceVrTracker2 export) throws. PPSA01317 skips its whole VR set-up when initialization fails - libSceMbus implements only the no-device path: initialization and termination succeed, no device events are reported and device queries return no entries
- libSceAudioPropagation implements only the no-acoustic-propagation path: the system keeps a 16-byte header in the title's CPU memory (no GPU memory), rooms, portals, sources and materials are tracked handles, attributes are validated and have no effect, no rays are requested and sources report no audio paths. Ray results, path calculation and audio paths are accepted only when empty and throw otherwise;
sceAudioPropagationSourceRenderwrites silence (zeroes) to each source's output buffer for the given size, without a dry signal. Objects still alive when their system is destroyed become unusable, and their later destroy or unregister is a no-op: PPSA21567 releases its reference-counted room, portal and source owners just beforesceAudioPropagationSystemDestroy, so the order for every object is not proven. Occlusion, reflections and reverb from level geometry are absent; in-game behaviour remains unverified. - libSceAcm batches execute as silent no-ops, so
sceAcm_ConvReverb_SharedInput,sceAcm_FFTandsceAcm_Pannerreturn success without encoding audio commands. - libSceNpCommerce - the PS Store icon show/hide calls and
sceNpCommerceSetPsStoreIconLayoutdo nothing - libSceUsbd implements only the no-device path:
sceUsbdInitandsceUsbdExitsucceed without a host USB context, the device list is always empty and event handling waits for its timeout; calls that need a device throw. Transfers follow thelibusb_transferlayout from libusb.h, which shadPS4 passes to titles asSceUsbdTransfer:sceUsbdAllocTransferzero-allocates one with its iso packet count (a negative count returns null),sceUsbdFillInterruptTransferfills the fieldslibusb_fill_interrupt_transfersets, andsceUsbdCancelTransferreportsLIBUSB_ERROR_NOT_FOUNDmapped to0x80240005by shadPS4's0x80240000 - errorrule, since no transfer can be submitted.sceUsbdEventHandlingOkreturns 1 because no other thread handles events, andsceUsbdFreeConfigDescriptoraccepts only null because no descriptor is ever returned. The device and handle calls take the argument lists of FreeBSD 11.4 libusb (libusb.h) and return0x80240002for the null arguments it rejects withLIBUSB_ERROR_INVALID_PARAM(libusb10.c, libusb10_desc.c, libusb10_io.c); a null device or handle in the calls it treats as null-safe returns 0, null or nothing, as there.sceUsbdOpenandsceUsbdGetActiveConfigDescriptorthrow on a null device, which libusb dereferences. Any other device or handle was never returned by this library, so those calls throw. The layout, the argument lists and the error codes are unverified on PS5 - libSceSystemService -
sceSystemServicePowerTick,sceSystemServiceReportAbnormalTermination,sceSystemServiceDisableMusicPlayer,sceSystemServiceReenableMusicPlayer,sceSystemServiceDisableMediaPlayandsceSystemServiceReenableMediaPlayreturn success and do nothing: the host has no auto power-off timer to reset, no system crash reporter to notify, no system music player to pause or resume and no system media playback to disable. PPSA01521 callssceSystemServiceDisableMediaPlayduring start-up, and its wrappers for both pass no arguments - sceSystemServiceLaunchWebBrowser (libSceSystemService) - AnyPS5 launches no web browser, so the call fails and nothing is shown. RommPS PPSA76677 then tells the player to scan its QR code instead
- libSceBluetoothHid implements only the no-device path: initialization and callback and device registration succeed, the callback is never called because no device connects, and calls that need a connected device throw
- System gesture recognizers (libSceSystemGesture) -
sceSystemGestureGetPrimitiveTouchEvents,GetPrimitiveTouchEventsCount,GetTouchEvents,GetPrimitiveTouchEventByIndexand the recognizer append, remove, reset and update calls report that no touch input exists and keep no recognizer state, so a title never receives a gesture event. Handle and pointer arguments are still checked. Error codes follow the 0x80D1 values main already uses in this file; KytyPS5 uses 0x8089 (INVALID_ARGUMENT 0x80890001, INVALID_HANDLE 0x80890006), and which one the console returns is not verified - sceVideoOutOpen validates the priority and CPU affinity that the open param requests for the VideoOut service thread but does not apply them: the port's present and vblank threads are host threads, and guest priorities and affinities do not reach host scheduling
- sceVideoOutAddVrrStatusFlagsPrivilege returns 0 and does nothing: the host output has no VRR state to report. The name comes from an assert message in a title that requires
SCE_VIDEO_OUT_OK; the NID hashes to it, the arguments are unknown (it is called without any) - sceVideoOutVrrPegToFixedRate, sceVideoOutVrrUnpegFromFixedRate (libSceVideoOut) - PPSA05684 passes the handle to both, two further zero arguments to
sceVideoOutVrrPegToFixedRate, and ignores the results. The meaning of those two arguments is unknown, so only zeros are accepted. VRR is not modelled and the output always runs at a fixed rate, so both calls only validate the handle and return 0 - libSceAudio3d - the port produces no sound: objects can be reserved and
sceAudio3dObjectSetAttributesaccepts their attributes, but the library has no bed exports or mixing to give them audio, the attributes have no effect andsceAudio3dPortPushonly paces the queue atgranularitysamples per frame at 48 kHz.sceAudio3dPortSetAttributeaccepts the late reverb level and the downmix spread attributes and ignores them.sceAudio3dObjectSetAttributesvalidates the port, the reserved object and the attribute array (an object id that was never reserved returns the invalid-object error, while shadPS4 returns success for it and the error only for a released object; neither is measured on a console), treating the reset-state attribute as valid with a null value and requiring a value for the others; the attribute identifiers and the value of each are not interpreted.sceAudio3dPortFlushdrops the frames queued bysceAudio3dPortAdvanceinstead of mixing and submitting them to an output, as there is no output - libSceTextToSpeech2 has no speech engine:
sceTextToSpeech2Initializeand the other exports returnEOPNOTSUPP. PPSA01317 skips its narration set-up when initialization fails - libSceAvPlayer:
sceAvPlayerSetLogCallbackaccepts a callback that is never called, as the player produces no log messages, andsceAvPlayerSetAvailableBandwidthhas no effect, as it governs HLS sources, whichsceAvPlayerAddSourcedoes not implement. - libSceHttp2 - no request reaches the network, so
sceHttp2SetMinSslVersionhas no TLS connection to restrict and its value is ignored, as forsceHttp2SslEnableOptionandsceHttp2SslDisableOption. The three setters validateidagainst the live handle registry and returnSCE_HTTP2_ERROR_INVALID_ID(0x817B1100) for a handle that was never allocated, was deleted, or belonged to a terminated context, following prosper. Whether the console restricts the object kind these setters accept, and what it does with an id from a previous init/term cycle, is unverified, so any live handle kind is accepted and ids are never reused.sceHttp2Term,sceHttp2DeleteTemplate,sceHttp2DeleteRequest,sceHttp2CreateTemplate,sceHttp2CreateRequestWithURL,sceHttp2CreateCookieBoxandsceHttp2SendRequestAsyncalso return the invalid-id error for a handle of the wrong kind or no longer live, following prosper (not measured on a console) - libSceNpTrophy2:
sceNpTrophy2RegisterUnlockCallbackaccepts a callback that is never called, as no trophy is ever unlocked,sceNpTrophy2UnregisterUnlockCallbackonly returns success, andsceNpTrophy2ShowTrophyListreturns success without showing a list (there is no system trophy UI; seen on PPSA15552). - sceAvPlayerSetTrickSpeed (libSceAvPlayer) with a negative speed runs the clock backwards but delivers no frames; when a forward speed is set again, playback resumes from the rewound time.
- sceRudpProcessEvents and sceRudpNetFlush (libSceRudp) - there is no reliable-UDP stack on the host, and every
sceRudpWrite,sceRudpReadandsceRudpGetStatuscall here reports a reset or idle context without queueing data, so no context ever holds pending data to process or send; both calls return success aftersceRudpInitandRUDP_ERROR_NOT_INITIALIZEDbefore it, as shadPS4 returns OK from its stubs. PPSA03490 callssceRudpProcessEvents(0)followed bysceRudpNetFlush()from its P2P service thread and ignores the first result; whether the real calls take parameters is unknown - sceRudpActivate (libSceRudp) - there is no reliable-UDP stack on the host to activate, so it returns success without doing anything, as shadPS4 does for its own
sceRudpActivate. PPSA01325 calls it with no arguments during start-up; what the console activates, and whether it reports an error beforesceRudpInit, is unverified - ulobjmgr registers no object:
_sceUlobjmgrRegisterObjectalways hands out id 0 and_sceUlobjmgrUnregisterObjectreleases nothing, as shadPS4 does - libSceHttp - no request reaches the network, so
sceHttpSetResponseHeaderMaxSizehas no response header to limit,sceHttpSetRecvBlockSize((int id, u32 blockSize)as in shadPS4) no response body to read in blocks andsceHttpRedirectCacheFlushno redirect to forget;sceHttpsUnloadCertreturns success likesceHttpsLoadCert, which keeps no certificate;sceHttpSetRedirectCallbackandsceHttpSetCookieRecvCallbackaccept callbacks that are never called,sceHttpsSetSslVersionhas no TLS connection to configure andsceHttpsGetSslErrorreports error 0 with detail 0;sceHttpSetAuthInfoCallbackaccepts a callback that is never called, as no server asks for authentication;sceHttpsGetCaListandsceHttpsFreeCaListreport an empty CA list (certsnull,certsNum0) and return 0, as no CA store is kept, and a null list returnsERROR_INVALID_VALUE; unlike shadPS4 they do not check thathttp_ctx_idis a live context nor that the library is initialised, andsceHttpsFreeCaListalso nullscerts, which shadPS4 leaves untouched. The signatures and the{ void* certs; int certsNum; }layout follow shadPS4 (PS4), not confirmed on a PS5 title - sceFontGlyphDefineAttribute (libSceFont) checks the glyph and ignores the attribute and its value, whose meaning is unknown. PPSA01325 sets attribute 0x11 to 0 on a glyph from
sceFontGenerateCharGlyphthat it deletes unused, and draws the character withsceFontRenderCharGlyphImageHorizontal - sceAudioInInit (libSceAudioIn) - returns 0 without library-wide setup, as
sceAudioOutInitdoes; eachsceAudioInOpenopens its own SDL capture device - sceRazorCpuPushMarker (libSceRazorCpu) - signature (label, color, flags) from SharpProspero, the same as sceRazorCpuPushMarkerStatic's except that the label is copied; it does nothing without a capture and returns 0
Unknown function info
-
sceHttpUriBuild (libSceHttp) retains
//for a non-opaque URI independently of the selected fields, following shadPS4. Black Myth: Wukong builds itsSchemeheader with option 1 and expectshttp://orhttps://. Other partial field combinations follow the PS4 reference and remain unverified on PS5 hardware. -
sceCoredumpGetThreadContextInfo (libkernel, NID
ShChva57wIM) - declared as a throwing stub. The pointer and size arguments and integer return type follow SharpProspero's PS5 bindings. The context structure and console behavior are unverified; the stub does not read or write caller memory. PPSA01736 imports it -
sceNpWebApi2PushEventAbortHandle (libSceNpWebApi2, NID
1OLgvahaSco) is a throwing stub. The two signed 32-bit handle arguments and return type follow shadPS4 (PS4); the PS5 signature and abort behavior are unverified. PPSA01736 imports it. -
sceNpGetSandboxInfo (libSceNpManager, NID
ZVZ++68nNI8) - the name hashes to the imported NID (found with nidhunt, confirmed withtools/nid_names.py). STAR WARS: Galactic Racer (PPSA28416) imports it; its OnlineSubsystemPS5 calls it with one pointer to a 0x50-byte stack buffer and reads the buffer as a string (discussions/3086). The returned string, the exact parameter struct and console errors are unknown, so every call throws without reading or writing caller memory. A working implementation belongs with that title's bring-up. -
sceKernelGetSystemSwVersion (libkernel) reports baseline system software version
0x01000000("01.000.000") for ProsperoStore (PPSA99000). The 0x28-byte layout (uint64_t sizeat 0,versionStringat 8 andversionat 0x24) matches ProsperoStore's caller, shadPS4, fpPS4 and OpenOrbis. These sources support the structure layout, but not the reported version value: the console firmware version remains unverified. The checks are unverified too: a null pointer returnsSCE_KERNEL_ERROR_EFAULTand asizeother than 0x28 returnsSCE_KERNEL_ERROR_EINVAL, while shadPS4 returns success for null and never readssize. -
kern.rng_pseudo (libkernel) -
sysctlbynamefills the whole output buffer with bytes from the host'sstd::random_deviceand leaves the length unchanged; a write returns -1 withEPERMand a call without an output buffer throws. The only caller seen is mbedTLS'smbedtls_hardware_pollin the catalog's ProsperoLight boilerplate, which asks for 64-byte blocks and fails if fewer come back. The console's generator, its per-call maximum and its answer to a size query are unknown -
kern.sdk_version (libkernel) -
sysctlbynamereports the system software version as the 4-byte value0x01000000(1.00), the valuesceKernelGetSystemSwVersionreports; a write returns -1 withEPERM. The major version is byte 3 and the minor version byte 2, in hex digits that read as decimal (13.60 is0x1360xxxx), as Capy Mobile (PPSA92280), remote_lua_loader and the lapse payload read it. Capy Mobile only displays it. The console's firmware version is not modeled and the low two bytes are unknown -
PPSA01530, PPSA23827 and PPSA13356 imports declared without parameters, signatures unknown, added without an implementation because the titles fail to load without them: sceNetShowIfconfig (libSceNet), sce::Json::Value::setNullAccessCallBack (libSceJson2), kqueue and kevent (libkernel), and scePadUnknown_n3kSX62fgNo (libScePad), whose real name is unknown. _sceUltWaitingQueueResourcePoolCreate, _sceUltSemaphoreCreate, _sceUltMutexOptParamInitialize, _sceUltMutexCreate, _sceUltQueueDataResourcePoolCreate and _sceUltQueueCreate (libSceUlt) forward to the exports without the underscore; that their argument lists match is inferred from the other underscore Ult exports, not measured.
-
sceVideoOutGetOutputStatusWithVrr (libSceVideoOut, NID
gWT7X8H0bYs) - the name hashes to the imported NID. PPSA26344 version 02.002.000 passes a VideoOut handle and an output pointer at three call sites. It compares a 32-bit value at byte 4 with 2, tests bit 0x10 at byte 16, and, when set, compares low 16-bit values at bytes 48, 50 and 52 with 48, 60 and 120. The full output layout, size, field meanings and console errors are unknown. Every call throws without reading or writing caller memory. -
sceHttp2WebSocketSetPingInterval (libSceHttp2, NID
YfaXPnc8PJE) - imported bylibdiscord_partner_sdk.prxof PPSA23126 (issue 2648). The parameters, the unit of the interval and the console errors are unknown. Every call throws. -
sceKernelGetProsperoSystemSwVersion (libkernel) reports system software version
0x01000000("01.000.000"); the console's firmware version is not modeled. The 0x28-byte block (a 64-bit size at 0, the version string at 8 and the packed version at 0x24) follows SharpProspero, which Prospero Multi Tools (PPSA99110) and Prospero Explorer (PPSA99109) are built with and which sets the size to 40, and the same fields in etaHEN and shsrv. A size other than 0x28 returnsSCE_KERNEL_ERROR_EINVALwithout writing; whether the console checks the size is unverified, since etaHEN and shsrv declare a 0x30-byte block and do not set it -
sceKernelGetAllowedSdkVersionOnSystem (libkernel) reports the system software version with the 12 patch bits set,
0x01000fff, as shadPS4 does on the PS4 and as SharpProspero describes it, which Prospero Explorer (PPSA99109) reads it through; a null pointer returnsSCE_KERNEL_ERROR_EINVAL. The console's value and its errors are unverified -
sceSystemServiceLaunchApp (libSceSystemService) - AnyPS5 runs one title and cannot start another, so every call throws without reading its arguments. The (title ID, null-terminated argv, launch parameters) signature follows SharpProspero, whose
AppLauncherProspero Explorer (PPSA99109) and Prospero Multi Tools (PPSA99110) import it through and which passes a 0x20-byte launch context or null; the console's argument checks and errors are unknown -
getuid, geteuid, getgid, getegid and issetugid (libkernel) report the root identity (0) and a process that never changed credentials (
issetugid0), as a jailbroken process has; the host user and group are not exposed to the guest. The values a title sees on a console are unverified -
sceKernelGetAppInfo (libkernel) - only
app_idand the title ID (offset 0x10, up to 9 characters plus a terminator) are written; callers declare the structure with different sizes, so the rest is left alone.app_idis 1, the running title's id in libSceSystemService, which is a guess, not something measured. The error codes follow shadPS4:EPERMfor another process, and 0 without writing anything for a null pointer. -
libScePlayGo - the chunk set comes from
playgo-chunkdefs.xml(every listed chunk plus chunks 0 through the default chunk), otherwise fromsce_sys/playgo-chunk.dat, whoseplgxheader is read as holding the chunk count as a 16-bit value at offset 0x0A and ids 0 to count - 1 are taken as valid. The field was identified on four dumps, where exactly that many 0x20-byte entries follow from offset 0x100 (RIDE 4 PPSA01599: 35, Persona 5 Royal PPSA05110: 25, LEGO Horizon Adventures PPSA14632 and Kena PPSA01802: 1); the rest of the format is not decoded and ids are assumed to be contiguous. Every listed chunk is reported as installed (LOCAL_FAST). Without either file every chunk id is accepted whilescePlayGoGetChunkIdlists only chunk 0; the console's answer for an id outside the package's chunk table is not checked. -
sceFontSetScriptLanguage, sceFontGetScriptLanguage, sceFontSetTypographicDesign, sceFontGetTypographicDesign (libSceFont) - signatures follow SharpProspero, not confirmed for the PS5. The handle keeps the language set for each script and the feature set for each typographic design and returns them, with 0 for one never set; the console default and its valid ranges are unknown, so any value is accepted. Neither setting changes shaping or rendering yet
-
Packed pixel ancillary word (shader recompiler) - the sample index at bits 8-11 and the render target index at bits 16-28 follow #295, and their equality with the SampleId and Layer builtins is inferred, not measured. A value passed through a select, move or phi is rebuilt from those two fields with bits 0-7, 12-15 and 29-31 zero. That is exact only because every read of the word must be an extract inside one modelled field; any other read throws. The other bits are unmodelled and their RDNA 2 layout is unknown: the RDNA 3.5 ISA is reported to give prim type at bits 0-1, VRS rates at bits 2-5 and eye id at bit 7, which was not checked against RDNA 2
-
sceAudioPropagationSourceSetAudioPath (libSceAudioPropagation, NID
tKSmk2JsMAA) -(uint64_t path, const void* data, float gain)follows SharpProspero and SAROS's call, which passes a handle fromsceAudioPropagationSourceGetAudioPath, path data and gain 1.0. Path updates are unsupported and every call throws without reading or writing caller memory. The no-propagation model yields no path handles; path allocation, ownership, rendering and console error codes remain unknown. -
Color comparison descriptor forms: emulated color comparison supports UNORM, SNORM and float formats for 2D, 2D-array and cube views. 8-bit sRGB (
Format8Srgb,Format8_8Srgb,Format8_8_8_8Srgb) returns 0 for every compare function, measured withimage_sample_c_lzon gfx1035 over references -0.5..1.5 and texel codes 0..255. Anisotropic filters are refused. Bilinear cube comparisons of float, unorm and snorm formats withoutDISABLE_CUBE_WRAPare refused; on that hardware a 4x4 R32 float cube blends across faces (46 of 90 edge rows differ from a per-face clamp; face 0, ref 0.1, u=3.9 v=2.5 is 0.6016 and u=1.5 v=0.1 is 0.3984), and withDISABLE_CUBE_WRAPthe per-face clamp matches. An 8-bit sRGB bilinear cube without that bit returns 0, since every texel comparison is already 0 for every compare function and the selected face cannot change the result. Cube-edge sampling behavior and console coverage on PS5's gfx1013 remain unverified. -
sceNpEntitlementAccessGetEntitlementKey - the three-argument signature, 16-byte key and errors
0x817D0002/0x817D0007follow KytyPS5; PPSA01521 passes a service label, entitlement label and output pointer. Only the no-key path is implemented: local entitlement labels carry no keys, and the output is untouched on failure. Console error precedence and key provisioning are unverified -
sceNpEntitlementAccess{Request,Poll}{Unified,Service}EntitlementInfo{,List} - signatures unknown; no reference implements them, so they are declared without parameters. The single-item variants copy the behaviour of the list ones, with no source of their own. Like the consume requests in the same library, they report the signed-out NP state with
SCE_NP_ERROR_SIGNED_OUT(0x80550006) and write nothing. PPSA15657 calls the unified request during start-up and continues past the error. Whether the console fails at the request or at the poll when signed out is unverified -
sceRudpGetStatus - PPSA01521 passes an output pointer and byte count
0xF8. Measured on a PS5 (firmware 13.60): the status is 0xF8 bytes; beforesceRudpInitevery call returnsRUDP_ERROR_NOT_INITIALIZED, and after it a null pointer or a byte count of 0 or above 0xF8 returnsRUDP_ERROR_INVALID_ARGUMENT. The layout matchesSceRudpStatusin Vita3K withcurrentContextsat 0x64 andallocs,frees,memCurrentandmemPeakat 0xC8 to 0xD4. OnlycurrentContextsis reported: the traffic counters stay 0 because nothing is sent, and the allocator counters stay 0 because the library does not allocate from the title's pool (the console reports 6 allocations and 0x1260 bytes right aftersceRudpInit, and 4 more allocations and 0x3F0 bytes per context). The console also writescurrentContextsand the allocator counters when the byte count is smaller than their offset; only the requested bytes are written here. -
sceHttpSetCookieEnabled - the two-argument signature and 0/1 enable values follow VitaSDK and shadPS4; PPSA01521 passes 0 to disable cookies. Disabling succeeds because the offline HTTP backend has no cookie engine; enabling throws. Invalid enable values use the same error as
sceHttpSetInflateGZIPEnabled. Like the existing offline HTTP setters, the handle is not validated; requests still fail with the network error. Console behavior is unverified -
sceHmd2Initialize (libSceHmd2) - the error the console returns when the PS VR2 runtime is unavailable is unknown; it returns libSceHmd's
UNSUPPORTED_FEATURE(0x81110016). PPSA01317 passes a pointer to 16 zeroed bytes and only tests the result for non-zero -
PPSA01317 imports declared without parameters, signatures unknown: the remaining libSceHmd2 and libSceVrTracker2 exports. Names from the aerolib NID list
-
PPSA15878 imports declared without parameters, signatures unknown: the libSceHmd2 reprojection and gaze exports,
sceVrTracker2Finalize,sceVrTracker2GetPlayAreaOrientedBoundingBoxandsceVrTracker2LocateCoordinateSystemin libSceVrTracker2, and thescePadVrControllertrigger effect exports in libScePad. Names from the aerolib NID list -
libSceMbus (
libSceDeviceService) - signatures taken from PPSA01317, which callssceDeviceServiceInitialize(3, 0), pollssceDeviceServiceGetEventState(1)and queries again when bit 0 or 1 is set, and callssceDeviceServiceQueryDeviceInfo_(0x7001, 0, 0, infos, 1, &count, &unknown, 0x70), treating a negative result as an error andcountas the number of entries. The host has no devices: the event state is 0 and a query returns 0 withcount0 -
NGS2 ATRAC9 waveform loops accepts one integer forward
smplloop. Inclusive RIFF endpoints and encoder-delay adjustment follow vgmstream riff.c. PPSA03747 supplies a 60-byte sampler chunk with one loop,samplerData24, start 256, inclusive end 299224 and delay 256 for 298969 audible samples. The chunk size and loop count bound the records;samplerDatais not interpreted. Output positions are assumed to use audible samples and an exclusive end. Blocks split into an optional intro, a repeated range and an optional tail; zero play count means infinite repeats, positive play count includes the first pass. ATRAC9 ranges include a preceding codec frame for decoder history. The output block layout, repeat-count mapping and error codes are unverified on hardware. Multiple, reverse, alternating and fractional loops throw. -
NGS2 submixer UserFx (control
0x20000004) invokes the title's callback after input mixing on every playing grain, including silence. The 40-byte control and 48-byte process context follow shadPS4. PPSA03747 installs a peak-meter callback; its code confirms the channel pointers, user data 0, channel count, grain size and sample-rate offsets and returns 0. Other user data words are preserved. Flags are assumed to be 1 after registration/restart and 0 thereafter, following UserFx2's first-process convention; this callback does not inspect them. Null handlers disable the effect, setup clears it, and nonzero callback results throw. These lifecycle and error semantics are unverified on console hardware. -
NGS2 ATRAC9 streaming keeps waveform duration and skip counts across compressed input blocks. The shared
APPENDflag (2), calledONLY_DATAin the compressed-data reference, ignores an ATRAC9 continuation block's sample, skip and repeat counts, following KytyPS5; PPSA03747 confirms a 262044-byte initial buffer declaring 11310532 samples, followed by 16384-byte buffers with flags 3. Incomplete superframes are retained until more input arrives. Input-block completion callbacks allow refills; the final callback of a logical waveform waits for its buffered PCM to drain, preserving the existing complete-block repeat behaviour. This buffering, callback timing, decoded-byte accounting and starvation silence are unverified on hardware. A closed ATRAC9 stream ending before its declared samples throws; fragmented ATRAC9 waveforms with repeats are unsupported. PCM streaming retains its existing append validation and early-close behaviour. -
PPSA01341 imports declared without parameters, signatures unknown: sceAgcSetSemaphoreMemory. Name from the shadPS4 aerolib NID list
-
sceAppContentDownloadDataGetAvailableSpaceKb (libSceAppContent) - a title whose
param.jsondeclaresdownloadDataSize0 gets 0 KB and OK; the console's behaviour for a title without a download data area is unverified (it may return an error instead). KytyPS5 does not special-case it, and shadPS4 stubs 1048576 KB -
sceNpEAAccessInitialize, sceNpEAAccessTerminate (libSceNpPartner001) - names and the no-argument signatures follow shadPS4; imported by PPSA23566, not confirmed on a PS5 title
-
sceSigninDialogClose, sceSigninDialogGetResult (libSceSigninDialog) - SceSigninDialogResult layout (int32 result and 3 reserved int32 words, zeroed) follows KytyPS5 and SharpProspero; error codes follow libSceLoginDialog's 0x80B8xxxx common-dialog codes rather than KytyPS5's 0x8135xxxx, and offline calls finish as user cancelled without opening a dialog. Neither choice is verified on hardware
-
libSceBluetoothHid (libSceBluetoothHid) - signatures taken from PPSA01317:
sceBluetoothHidInit()andsceBluetoothHidUnregisterCallback()without arguments,sceBluetoothHidRegisterCallback(callback, 0, param)with a 16-byte param, andsceBluetoothHidRegisterDevice/sceBluetoothHidUnregisterDevice(vendorId, productId); the report and device name exports are declared without parameters -
sceAgcWaitRegMemPatchMask (libSceAgc) - follows
sceAgcWaitRegMemPatchReference: the mask is taken as a 32-bit value and written to the low mask word of a 32- or 64-bit wait, as OpenAGC does; sharpemu writes both words of a 64-bit wait's mask. A mask above 32 bits throws -
scePsmlMfsr2CreateContext, scePsmlMfsr2CreateSharedResources, scePsmlMfsr2GetContextInitRequirement, scePsmlMfsr2GetDispatchPackets, scePsmlMfsr2GetDispatchPacketsSizeInDwords, scePsmlMfsr2GetSharedResourcesInitRequirement, scePsmlMfsr2Init, scePsmlMfsr2ReleaseContext, scePsmlMfsr2ReleaseSharedResources (libScePsml_mfsr2) - unknown signatures, imported by PPSA23566; declared without parameters
-
sceAgcDcbSetCfRegisterDirect, sceAgcDcbSetCfRegisterRangeDirect (libSceAgc) - signatures follow OpenAGC and SharpProspero, which agree; the SET_CONFIG_REG (0x68) packet is OpenAGC's. The driver does not execute SET_CONFIG_REG, so a submitted packet throws
-
scePadOpen and scePadOpenExt (libScePad) - special ports (type 2) return
DEVICE_NOT_CONNECTED(0x80920007) because the host has no special controller, andscePadGetHandlehas no handle for them; whether the console opens a handle and reports the device as disconnected later is unknown. scePadOpenExt handles only special ports. PPSA01317 passes a 16-byte param that names the device by vendor and product id (b7 0e 04 0e ...for 0x0eb7:0x0e04) and skips the user on any negative result. Other port types throw -
scePadVrControllerReadState (libScePad, NID
iA-DdobUen8) - the name hashes to the imported NID; the(int handle, void* state)signature follows PS5VR (PPSA99177), which passes a PS VR2 Sense controller handle fromscePadOpentype 3 or 4 and a 0x68-byte state it reads as buttons at 0, stick bytes at 4 and a connected byte at 0x40. The title calls it only aftersceHmd2Initializesucceeds, which it does not here, so every call throws; the state layout is otherwise unknown -
scePadSetVibrationMode (libScePad) - modes 0 to 3 are accepted and stored; the meaning of mode 3 is unknown (PPSA21480 calls it with 3 right after
scePadOpenand aborts on failure; SharpProspero names only 1 and 2). The stored mode has no other effect -
PPSA23566 imports declared without parameters, signatures unknown: sceAudioOut2UserGetSupportedAttributes, sceConvertKeycodeGetCharacterFromKeyboardData, sce::Json::MemAllocator::notifyError, sceNetResolverAbort, sceNpCommerceDialogOpen2, sceNpEntitlementAccessGetPftFlag, sceProprietaryVoiceChatHelper{Initialize,Terminate,SetVoiceChatState,GetVoiceChatUsageState}, sceVoice{GetResourceInfo,ResetPort,EnableChat,DisableChat}. Names from the shadPS4 aerolib NID list
-
PPSA28416 imports declared without parameters, signatures unknown: sceAudioOut2EnableChat, imported by its bundled
party-ps5-shipping.prx. Name from the shadPS4 aerolib NID list -
PPSA08427 imports declared without parameters, signatures unknown: sceNpEntitlementAccessGetGameTrialsFlag, imported by its bundled
pros.sdk.Prospero.prxand not called before the main menu. Name from the aerolib NID list -
PPSA06888 imports declared without parameters, signatures unknown: sceRudpEnableInternalIOThread2, sceRudpGetOption, sceRudpGetRemoteInfo (libSceRudp), imported by its bundled
Media/Plugins/SceRudp.prxand not called during start-up. Names from the NID table of shadPS4, which declares them without parameters too -
sceVoiceChatRequestCreateVoiceChatGroup, sceVoiceChatRequestJoinVoiceChatGroup, sceVoiceChatRequestLeaveVoiceChatGroup, sceVoiceChatRequestDeleteVoiceChatGroup (libSceVoiceChat) - assumed to take a request id and two pointers like the other
sceVoiceChatRequest*calls; offline, every argument is ignored andSIGNED_OUTis returned, as for those -
sceAvPlayerAddSource (libSceAvPlayer) - requests up to 4 additional decode-ahead video framebuffers from the memory replacement beyond
num_output_video_framebufferswhen memory is available; the console's internal buffering behaviour is unknown -
sceTextToSpeech2Initialize (libSceTextToSpeech2) - the console's error for an unavailable speech engine is unknown; it returns the kernel's
EOPNOTSUPP(0x8002002D). PPSA01317 passes a param that starts with 0x2000000 and only tests the result for non-zero; the other exports it imports are declared without parameters and return the same error -
sceSystemServiceLaunchWebBrowser (libSceSystemService) - the console's error for an unavailable web browser is unknown; it returns the kernel's
EOPNOTSUPP(0x8002002D) for any arguments. The (uri, param) signature follows RommPS, which passes a URL and a null param and only tests the result for zero; the param layout and the console's argument checks are unknown -
Command buffer cursors (libSceAgc) - a null
cursor_downis taken as a buffer without downward allocations, whose limit istop. PPSA16064 builds one-packet buffers of 8 dwords that way; the console's handling is unconfirmed -
sceVideoOutRegisterBuffers2 (libSceVideoOut) - buffer option 8 (STRICT_COLORIMETRY) is presented as option 0, with the stored values unchanged; what the console changes for it is unknown. Only options 0 and 8 are accepted
-
sceAgcGetRegisterDefaultsInternal (libSceAgc) - returns the version 0 internal table, as
sceAgcGetRegisterDefaultsreturns the version 0 public one; OpenAGC returns the table of the version passed tosceAgcInitinstead, and null before it -
sceVideoOutAddBufferAttributeOption (libSceVideoOut, NID
MBlv8YWoyOk) - the signature(VideoOutBufferAttribute2*, uint64_t option)comes from SharpProspero and the call site in PPSA25380, which passes 0x20 and ignores the result. The option is ORed intoattribute->option; whether the console validates the bits, keeps them elsewhere or fails on an unknown option is unknown. A null attribute throws. Option 0x20 makessceVideoOutRegisterBuffers2throw, as every option other than 0 and 8; what it selects for an overlay buffer is unknown -
sceVideoOutRegisterBuffers2 (libSceVideoOut) - DCC buffers (category 1):
dcc_controlis taken as the CB_DCC_CONTROL block layout, only bits 0x10026c are accepted;dcc_cb_register_clear_coloras the register-clear texel, only 32-bit values are presented -
sceVideoOutIsOutputSupported (libSceVideoOut) - only the default mode (1) is reported as supported. The console answers per display and per title: with a 120 Hz TV it also answers 1 for mode 15 (119.88 Hz), and PS5_Vulkan measured that
sceVideoOutConfigureOutputaccepts 15 only from a title whose param.json declares high-frame-rate output (attribute3 0x80040). Modes 4, 7, 8, 12-17 and 19 returnVIDEO_OUT_ERROR_UNSUPPORTED_OUTPUT_MODEhere, as they did on the measured display. Mode 18 throws, because one console answered 0x80290016 and another 0x8029001E. The nameVIDEO_OUT_ERROR_UNKNOWN_OUTPUT_MODEfor 0x8029001E is ours. Word 3 of the output options is accepted with any value, as on the console, and its meaning is unknown. PPSA12544 probes0xd000000a, which the console answers with 0x8029001E, so the title selects 3840 pixels -
sceVideoOutGetResolutionStatus (libSceVideoOut) - the 48-byte layout follows the declarations in ps5-opengl and EVO-PLAYER-PS5 (#1578), which agree; not confirmed on a console.
screenSizeInInchis 0, the value EDID uses for an undefined size, since the host display's size is not read;flagsis 0, its bits are unknown. The pane equals the full size becausesceVideoOutSetWindowModeMarginsapplies no margins -
sceVideoOutOpen (libSceVideoOut) - the open param's first word is unknown (PPSA21564 passes 16; it is not the byte size, since the affinity mask is at offset 16); only 16 is accepted. Whether the param continues past offset 24 is also unknown
-
s_setkill (core/shader/recompiler) - decoded as
s_endpgmfor any immediate: measured on RDNA2 hardware (gfx1035), a store before it is visible and nothing after it runs (#771); whether the KILL status bit it sets is observable differently froms_endpgmis unverified -
sceRtcParseDateTime (libSceRtc) - the console's zone name table is only known from the names measured on a PS5 (firmware 13.60); any other name is assumed to take the military letter offset of its first character, as every measured name outside the table does (
HST,MSK,XYZ), so a name the console's table holds but nobody measured gets the wrong offset -
sceAudio3dPortOpen (libSceAudio3d) - buffer modes 0 and 1 (also selected by the 0x10 and 0x18 parameter sizes) and 3 beds depend on an SDK version check in the module (prosper) and throw. A repeated
sceAudio3dInitialize(NOT_READYin shadPS4, 0 in prosper) andsceAudio3dPortAdvanceon a full queue (NOT_READYin shadPS4, unhandled in KytyPS5) throw too -
sceAudiodecDecode (libSceAudiodec) - a raw M4AAC stream carries no channel configuration, so the decoder tries the mono/stereo configuration and then configurations 3 to 7 within
ui_max_channelsuntil one decodes the first access unit, and keeps that one. No reference documents how the library picks the layout (shadPS4 maps the channel count straight to the configuration; SharpProspero only describes the maximum). With the stereo configuration a mono raw stream decodes as 2 channels, so 2 is reported, not 1 -
sceAudio3dObjectReserve (libSceAudio3d) - object ids, the
max_objectslimit and the checks ofsceAudio3dObjectReserveandsceAudio3dObjectUnreservefollow shadPS4 (PS4), the only reference with a body: ids count up from 1 per port, skipping 0, 0xFFFFFFFF and ids in use, and a failed reserve writes 0xFFFFFFFF -
s_sethalt (core/shader/recompiler) - with SIMM16[0] clear it is a no-op: the RDNA 2 ISA guide describes that value as resuming a halted wave, and a wave that executes it is not halted; measured on a gfx1035 (RDNA 2) wave:
s_sethalt 0followed by a VALU op completes and gives the normal result. Only SIMM16[0] is read; with it set the instruction throws -
s_subvector_loop_begin and s_subvector_loop_end (core/shader/recompiler) - follow AMD's RDNA 2 instruction set reference and a gfx1036 (wave64) measurement, pinned in SubvectorLoop.cpp;
S0in the end instruction'selif(S0 == 0)is read as its SGPR operand. A wave32 shader and a destination other than an SGPR throw because neither is measured. Measured on PC RDNA2 (Radeon 610M), not on a PS5. The specialization pass keeps a constant-condition branch whose untaken target is a loop header, since folding it removes the loop's back edge, which SPIR-V requires exactly once per loop header (SPIRV-Tools rejects the module and the NVIDIA driver 615.78.08 crashes compiling it); a loop whose back-edge block becomes unreachable in another way is not handled -
AMPR WriteAddressFromCounterPairOnCompletion (libSceAmpr) - the pair of an even counter n is assumed to give counter n in the low 32 bits and n + 1 in the high 32 bits. Wait compare values, wait flush and counter index ranges follow the ampr_emu reimplementation; the flush is accepted and has no effect, as commands run in order
-
AMPR command sizes (libSceAmpr) - commands use the emulator's own encoding with an 8-byte header, so
Nop(n)takes 8 + 4n bytes where the console record is n dwords including its header (NopWithData(n): (n + 1) dwords). The measure functions agree with the appended sizes, but a title that pads to an exact offset or the end of the buffer withNop(remaining / 4)getsSCE_AMPR_ERROR_BUFFER_FULLor a shifted offset. The at-start flag of the_04_00writes is ignored; commands run in order, each after the previous one completes -
AMPR object layout and compact gathers - the 24-byte object and offsets (type 0, cursor 4, count 8, capacity 12, pointer 16) follow ampr_emu assertions and its C declaration. AnyPS5 represents the 32-bit type word as low 16-bit type and high 16-bit recording flags. Command encoding is AnyPS5 internal: opcode 29 and three 32-bit words encode the high offset byte, length minus one and low offset word. The 12-byte size reduces HFW's 1 MiB buffer pressure; it is not a claim about console opcode encoding. Existing 40-bit offsets and lengths 1 through 2^32 are retained; console behavior outside those limits is unverified.
-
APR resolve ForEach result (libkernel) -
sceKernelAprResolveFilepathsToIdsAndFileSizesForEachreturns the number of paths that resolved, with the per-path status inresultsand the failed ids/sizes set to the invalid id and 0. The ampr_emu bridge passes the count of its resolver through and does not show what is counted; counting successes is not confirmed on a title. The guest errno of the failing non-ForEachresolves is set through__error_nid_postfix -
AMPR counter access (libSceAmpr) - signatures and checks of
WaitOnCounter_04_00,WriteCounter_04_00,ConstructNopandConstructMarkertaken from the ampr_emu reimplementation, which hands counter commands to the console and does not show their effect. The counters are taken as 32 bits each: the 8-byte access of counter n spans n (low) and n + 1 (high), the 2- and 1-byte accesses select a half or a byte of the counter by its offset, waits compare at the access width (signed and wrapped compares included), the AND mask applies to both sides and the atomic writes wrap within the access. TheConstructNoptype is not recorded -
APR gather and scatter reads (libSceAmpr) - signatures, argument checks and the read cursor taken from the ampr_emu reimplementation, not confirmed on a title: each read leaves the file, the next file offset and the next destination; a gather reads that file at a new offset into the next destination, a scatter continues in the file into a new destination, a gather-scatter takes both. Recording one needs a read file since the last
ResetGatherScatterState; like ampr_emu,sceAmprCommandBufferResetkeeps that state, and a gather or scatter with no read before it in the submitted buffer throws instead of returningSCE_AMPR_ERROR_APR_INVALIDGATHERSCATTERSTATE -
AMM map, map direct and unmap (libSceAmpr) - signatures and the protection mask (CPU, GPU, AMPR and ACP read and write) taken from the ampr_emu reimplementation, which hands the remaining checks and the mapping to the console kernel; the mapper model taken from PS5PCEM:
sceAmprAmmGiveDirectMemoryusage 1 gives the allocated direct memory to the pool plain maps take pages from, usage 0 only allocates it. Not confirmed on a title. The AMM virtual address ranges are a 32 GiB range and a 32 GiB multimap range reserved on first use at the top of the guest arena, above the addresses that maps withoutMAP_FIXEDare given lowest first and that titles derive their next hints from; the console's addresses are not known (ampr_emu takes them fromsceKernelMapperGetParam), and a reservation that cannot be made there throws. Maps outside them throw. Addresses, sizes and direct offsets must be 16 KiB aligned. The memory type and the GPU mask are ignored, AMPR and ACP access maps as CPU access, unmapped pages go back to the pool and stay reserved. Submission runs the buffer before returning, the submit result is always 0 and a failing command throws; the AMM measures return errors sign-extended, as ampr_emu does.sceAmprAmmGetVirtualAddressRangesthrows for a null output -
AMM remap, multimap and protection changes (libSceAmpr) - signatures and the protection and mask checks taken from ampr_emu; the effects are inferred from the names, not confirmed on a title. A remap moves every page of a fully mapped range to the new address with the given protection and leaves the old range reserved; a multimap maps the same pages at a second address, anywhere in the AMM ranges, and a pool page goes back to the pool once its last mapping is unmapped; a multimap onto its own source range throws. A protection change sets the masked bits on every page of a fully mapped range; the memory type is recorded and ignored. A command on a range that is not fully mapped throws
-
sceVideodec2GetAvcPictureInfo (libSceVideodec2) - runs the
sceVideodec2GetPictureInfobody (KytyPS5 binds both NIDs to one function; SharpProspero gives both the sameoutputInfo, first, secondsignature); the second (bottom field) picture info is never written, since only progressive H.264 output is modelled. prosper calls the AVC layout unestablished (no title observed calling it) -
AMM PRT ranges (libSceAmpr) - signatures, checks and their order taken from ampr_emu, where
MapAsPrtis a map with the PRT flag and protection 0 andAllocatePaForPrta memory type and protection change with mask 1019, both checking the buffer memory after its size; the effects are inferred from the names, not confirmed on a title. Unbacked PRT pages are zero-filled pages with GPU read access, so CPU reads see zeros instead of faulting and GPU writes fault instead of being dropped.AllocatePaForPrtbacks each unbacked page with a pool page and sets the type and protection of backed ones;RemapIntoPrtmoves a fully mapped range into a PRT range, its opcode argument (1011 when 0, as in ampr_emu) is recorded and ignored;UnmapToPrtreturns the pages to the pool and zero-fills them again. A plain map, unmap or remap over a PRT range ends it;AllocatePaForPrt,RemapIntoPrtorUnmapToPrtoutside a PRT range throws -
AMM kernel write commands (libkernel) - signatures of
sceKernelWriteModifyMtypeProtectCommandandsceKernelWriteRemapIntoPrtCommandtaken from ampr_emu's libkernel hook targets, which forward to the real kernel; the measure mode (dstnull reports the size,outSizenull skips the report) follows ampr_emu's measure-then-record calls, not confirmed on a title. The range, protection and mask checks mirror thelibSceAmprsiblings, and the recorded bytes match them exactly so the submitted buffer executes on the existing paths -
APR map begin and end (libSceAmpr) - as in ampr_emu,
MapBegin/MapDirectBeginmap when they run andMapEndonly closes the region; while a region is open a second begin and every completion write returnEPERM, the at-start_04_00writes are accepted -
AMPR markers (libSceAmpr) - signatures taken from the ampr_emu reimplementation, not confirmed on a title:
sceAmprCommandBufferSetMarkerWithColortakes the color by pointer, the push and measure variants by value. Colors are not recorded -
sceFontGetRenderScaledKerning (libSceFont) - arguments, the cleared output and the bound renderer check taken from
cellFontGetRenderScaledKerningin RPCS3 (PS3 predecessor of the library), not confirmed on a title. The kerning is thesceFontGetKerningone at the render scale -
sceFontGetPixelResolution (libSceFont) - signature taken from the IDA type database of Orbital, not confirmed on a title. The value is the one the library's driver reports (64 for FreeType); the argument checks and the cleared output follow
sceFontGetLibrary -
sceFontDettachDeviceCacheBuffer (libSceFont) - signature taken from the IDA type database of Orbital, not confirmed on a title. It detaches the cache buffer attached by
sceFontAttachDeviceCacheBuffer, returns the buffer and its size, and reportsSCE_FONT_ERROR_NOT_ATTACHED_CACHE_BUFFERwhen no cache buffer is attached -
sceFontGetFontGlyphsCount, sceFontGetCharGlyphCode (libSceFont) - signatures taken from the IDA type database of Orbital and matching the SharpProspero bindings, not confirmed on a title. The count is the face's glyph count and the glyph code its glyph index, as the library's driver reports them; a code with no glyph returns
NO_SUPPORT_GLYPHand code 0NO_SUPPORT_CODE, assceFontRenderCharGlyphImagedoes. The argument checks and the cleared output followsceFontGetPixelResolution -
sceFontGetFontResolution (libSceFont) - signature taken from the IDA type database of Orbital, not confirmed on a title; the outputs are inferred from the names. The resolution is the face's units per EM and the scale pixel the driver's face scale (units per EM / 64 for FreeType), the pixel scale a font has when opened. Either output may be null, as in
sceFontGetResolutionDpi -
sceFontCreateWritingLine, sceFontWritingLineWritesOrder (libSceFont) - signatures and the
SceFontWritingLineStep/SceFontCreateWritingLineDetaillayouts (detail id0x0FD5) taken from SharpProspero, not confirmed on a title. The 64-bit writing attribute is read as the PS4 11.00libSceFont.sprxreads it: low byte0xFA, embedding level in bits 8-15 (0 to 126), bit 30 and bit 31 marking space before and after the run; the PS5 library was not measured, and the names of the two bits are ours. PPSA01325 builds its attribute the same way (0xFA | level << 8, bits 30 and 31) and passes a null metrics pointer when its run has no metrics object. Attribute 0 is accepted and treated as0xFAwith level 0 and no spacing bits, as before this reading; the PS4 library rejects it and what the PS5 library does with it is unknown. Any other attribute, a level above 126 and a null orderer throw: the PS4 library returns0x80460002for them, not confirmed for the PS5 -
sceFontWritingRefersRenderStepCharacter (libSceFont) - the second argument is an out pointer to the writing's letter step, as in KytyPS5 and the SharpProspero bindings. Measured on PS4 firmware 11.00
libSceFont.sprx(not on a PS5): exactly 8 bytes are written, the address of a step stored inside the writing, and a null writing writes null; shadPS4 and prosper treat the argument as a struct, which the measurement contradicts. The letter step lives in the writing, so the pointer stays valid as long as the writing does, and its contents are rebuilt by each call of this function. On the PS4 library repeated calls on one step walk the characters it covers and then return null; here every call returns the step's one character, so the second call differs. Assumed: each step covers one character and one glyph. PPSA06699 (Hot Shots Golf 2) dereferences the returned pointer for its character counts. -
sceFontWritingLineGetOrderingSpace (libSceFont) - the four outputs are written in the order the PS4 11.00
libSceFont.sprxwrites them (line advance, leading space, space between spaced runs, trailing space); the parameter names in the Orbital IDA type database and the SharpProspero bindings order them differently (head, inline, tail, advance), and the PS5 library was not measured. PPSA01325's only call uses them in the PS4 order: it computes first - second - fourth - 0.25 * third and compares that, divided by a scale, with its width limit. The PS4 library writes the trailing space through its pointer without a null check whenever the leading-space pointer is set; that call throws here -
sceSaveDataTransferringMountPs4, sceSaveDataDirNameSearchPs4 (libSceSaveData.native) - arguments assumed to be those of
sceSaveDataTransferringMountandsceSaveDataDirNameSearch: KytyPS5 binds both NIDs to the PS5 functions, and prosper captured the same result layout on a title for the search. There is no PS4 save area, so the mount returnsNOT_FOUNDand the search reports zero hits -
sceCoredumpWriteUserString and sceSaveDataGetConvertProgress - imported by PPSA16064, not called during its start-up and added without an implementation; unknown signatures
-
sceSaveDataConvert (libSceSaveData.native) - the parameter block (user id at
+0x00,SceSaveDataDirNamepointer at+0x08, 48 opaque bytes after it) is read from PPSA28416's single call, not confirmed by KytyPS5, shadPS4, fpPS4 or SharpProspero, which have no body for it. Host saves have no size limit, so an existing save returnsSCE_OKwithout touching its files and no event is queued; what the console returns for a save that is mounted, already converted or needs no conversion is unknown. The directory name is validated assceSaveDataDeletedoes -
sceSaveDataCancel (libSceSaveData.native) - imported by PPSA23126, which fails to load without it; added without an implementation because its signature is unknown. Every save data call here finishes before it returns, so nothing is ever in flight to cancel, but what the console returns then is unknown
-
sceAudioOutExClose, sceAudioOutExConfigureOutput, sceAudioOutExGetMonitorInfo, sceAudioOutExOpen (libSceAudioOut) - imported by PPSA99505, which fails to load without them; added without an implementation and declared without parameters. PPSA99505 calls them only for its HDMI bitstream output, an option that is off by default, to read the formats the TV or receiver lists, switch the HDMI output mode and open a port for IEC 61937 bursts (Jelly5); EVO-PLAYER-PS5 also calls
sceAudioOutExOpen,sceAudioOutExConfigureOutputandsceAudioOutExClosefor HDMI bitstream output. The two declare the arguments ofsceAudioOutExConfigureOutputdifferently and neither is confirmed on a console. Audio reaches the host device through SDL as PCM, so there is no encoded HDMI output to switch to -
sceOpusCeltDecCreateEx, sceOpusCeltDecDecode, sceOpusCeltDecDestroy, sceOpusCeltDecGetSize, sceOpusCeltDecInitialize, sceOpusCeltDecTerminate (libSceOpusCeltDec) - imported by PPSA99001, which fails to load without the module; added without an implementation. Their signatures match libSceOpusDec's in ProsperoRadio. PPSA99001 opens this decoder only as a fallback when libSceOpusDec reports a retryable error for a CELT packet, which libSceOpusDec here never returns, so the fallback is not reached
-
sceContentDeleteById (libSceContentDelete) and sceContentSearchGetContentLastUpdateId, sceContentSearchOpenMetadataByContentId, sceContentSearchGetTotalContentSize, sceContentSearchGetNumOfContent (libSceContentSearch) - imported by PPSA06465, which fails to load without them; added without an implementation because their signatures are unknown
-
sce::Json::Parser::parse with a read callback (libSceJson2) - the callback's contract is taken from PPSA04540's: it returns 0 with the next character, and at the end of its data writes
'\0'and returns -1. Characters are read until the callback returns non-zero or gives'\0', and the text read is then parsed as by the(text, size)overload, so trailing characters after the value are rejected as there. Whether the console stops reading at the end of the top-level value, and what it returns when the callback fails before the end, are unknown -
sce::Json::Parser::parse (libSceJson2) - a number that overflows a double (e.g.
1e309) throws: whether the console rejects the document or stores an infinite real is unknown -
sceUserServiceGetNpAccountId (libSceUserService) - the account id for a user with no linked PSN account is assumed to be 0 with success; libSceNpManager's
sceNpGetAccountIdAanswers the same question withSCE_NP_ERROR_SIGNED_OUT -
sceUserServiceGetUserColor (libSceUserService) - the default profile colour is assumed to be blue (0)
-
libSceVdecsw (libSceVdecsw) - structure layouts follow shadPS4's
vdecsw.hand were checked against PPSA05684's movie decoder (movie-decoder-vdecsw.cpp), which assertspictureCount == 1at offset 0xb ofOutputInfoand readsInputResultoffset 0x10 as the number of frames an access unit produced. The compute, decoder memory and decode input structures and the first 0x28 bytes of the 0x50-byte decoder config are those of libSceVideodec2, and decoding goes through it. The 0x78-byte AVC picture info is filled with Videodec2's leading fields and the cropping fields only. OUTPUT_PENDING (0x81510115), INPUT_QUEUE_EMPTY (0x81510116) and DECODE_PENDING (0x81510117) follow from the codes each call's assert accepts. At most four decoded pictures are queued and the last one is held untilsceVdecswFinalizeDecodeSequence; the console's queue depth is unknown -
sceGameLiveStreamingGetCurrentStatus2 (libSceGameLiveStreaming) - the status layout (user id, on-air flag, spectator, text and command message counts, broadcast resolution, 48 reserved bytes) is taken from shadPS4's
OrbisGameLiveStreamingStatus2; the call reports that no stream is on air, with an invalid user id -
Depth clear draws (AGC driver) - a draw with
DB_RENDER_CONTROL.DEPTH_CLEAR_ENABLEis taken to writeDB_DEPTH_CLEARto every pixel it covers whatever the depth test, depth bounds and depth bias say: it is drawn with an always-passing depth write and the viewport depth range pinned to the clear value. The draw is rasterized as submitted, so its coverage is the draw's own. Whether the DB still applies the depth test or HiZ to such a draw is not measured -
Alpha-to-coverage (AGC driver) - only
DB_ALPHA_TO_MASK = 0xaa01is accepted: the enable bit with the four quad offsets at 2 and noOFFSET_ROUND, the undithered setting radeonsi programs. Draws are single-sampled, so the pixel shader writesSampleMask0 when its MRT0 alpha is below one half or NaN and all ones otherwise, and runs with late fragment tests. That rule was measured on a Radeon 660M (gfx1035, RADV withRADV_DEBUG=noatocdithering, which programs the same register) for 0, -0, 0.25, the two floats below one half, one half, the two above, 0.75, 1, 2, -1, both infinities and both NaNs, and is pinned in AlphaToCoverage.cpp; it is not measured on gfx1013. Vulkan'salphaToCoverageEnableis not used: the NVIDIA driver 615.78.08 dithers single-sample coverage (an alpha of 0.25 writes half the pixels of an RTX 3050 Laptop target). Other offsets,OFFSET_ROUND, a sample-mask export, and an MRT0 that is missing, swizzled, packed or exported without a floating-point alpha throw -
GPU flips (libSceVideoOut) - a command-buffer flip of a buffer index with no registered buffer when the GPU reaches it presents black and completes like any flip (flip event, count,
flipPendingNum). The console's behaviour is unknown; PPSA05684 requires that it completes: its renderer submits a flip of buffer 0 while another thread waits forsceVideoOutIsFlipPendingto reach 0 before registering the buffers, andflipPendingNumcounts that flip from its submission as in shadPS4 -
sceAgcDriverGetEqContextId (libSceAgcDriver) - returns
ident: an end-of-pipe interrupt is delivered only to the registration whose id equals the raising queue, soidentis that context's id (titles register 0 or 1 for graphics and0x20 + 8 * pipe + queuefor compute). The console's value is not known; KytyPS5 returns the event'sdata, which it fills with the interrupt's context id, whereasdatahere is the EV_CLEAR trigger count. Other event filters throw -
sceAgcSetSubmitMode (libSceAgc) - mode values unknown; only 0 is accepted
-
User data registers (AGC driver) - a
SPI_SHADER_USER_DATA_*orCOMPUTE_USER_DATA_*register the title never wrote reads as 0 when a stage's RSRC2 count covers it, as Kyty (zeroedUserSgprInfo) and SharpEmu (missing registers read 0) do, and as AMD PAL and Mesa initialize them; the console's value is not confirmed -
SET_PREDICATION (AGC driver) - boolean predication follows the AMD PM4 encoding Mesa uses: operation 3 reads 64 bits and 4 reads 32 bits, and bit 8 runs predicated packets when the value is non-zero (clear: when it is zero); the bit 12 hint is ignored. The address must have its low 4 bits clear, as
sceAgcDcbSetPredicationwrites it. Query predication (Z-pass, primitive count), a predicated COND_EXEC, predicated command buffer chains and flips in predicated command buffers throw -
sceAgcGetGsOversubscription (libSceAgc) - signature and occupancy formula (base and expanded vertex/export capacities, budget shift,
GE_PC_ALLOC/SPI_SHADER_PGM_RSRC4_GSencoding) follow KytyPS5 only, not confirmed on hardware or a title; a negative or NaN factor that gives a negative target, a missing GS context register or a zeroGE_MAX_OUTPUT_PER_SUBGROUPthrows -
Vertex entry merged wave info (recompiler) -
s3of every vertex-path shader is set towaveSize | waveSize << 8(vertex and primitive count of a full wave, wave index 0), or to32 | 32 << 8for a wave64 program on a 32-lane host subgroup, which runs it at one lane per invocation and holds no lanes 32-63. Layout taken from the prologue Mesa's ACO emits for NGG vertex shaders (s_bfe_u64 execfroms3), not measured on hardware. The driver gives every graphics program user data froms8, so the condition does not tell NGG from legacy vertex shaders: they just never reads3. A draw whose last wave is partial still reports a full wave, and so does a host wave with idle invocations (an RTX 5070 ran every vertex warp of a non-indexed triangle list with 30 of its 32 invocations). -
NGG vertex programs on the mesh path (AGC driver) - an unregistered vertex program with
PRIMGEN_ENthat uses LDS ors_barrierruns on the geometry (mesh) path. Each input primitive is assumed to yield at most one output primitive, the subgroup is bounded byGE_MAX_OUTPUT_PER_SUBGROUPas a vertex budget, and the GS/ES VGPR count checks are skipped, because the merged inputs keep their positions. Taken from the code Mesa's ACO emits for NGG culling and from PPSA59322 and PPSA99010 draws, not measured on hardware. Registered programs keep the vertex path -
s_barrier in vertex-path programs (recompiler) - emits no instruction when the program has no LDS or GDS access and no memory write or atomic, so no wave of the subgroup can observe another; the
GS_ALLOC_REQsuch a barrier orders on NGG passthrough programs is already dropped on the vertex path. The Vertex execution model has no workgroup barrier. Programs with LDS, GDS or memory writes throw. Not measured on hardware -
Strided buffer overhang (libSceAgcDriver) - a strided buffer descriptor that ends less than one stride past the end of the readable registered allocation holding its base is bound only up to that allocation's end, even when another readable allocation starts right there. This assumes the bytes past the end are the rounded-up
num_recordsof the last record (RADV rounds it up), which no fetch inside the buffer reads; a guest that really keeps a vertex split across two adjacent allocations would read zeros for the cut tail. Taken from the RetroArch Dolphin core case in #2912, not measured on hardware. -
Zero-stride vertex fetch range (libSceAgcDriver) - for a stride-0 V# with OOB_SELECT 2 the whole fetch reads memory unless NUM_RECORDS is 0; with OOB_SELECT 3 it reads zero when NUM_RECORDS is 0 and throws when the fetch only partly fits. Rules taken from the GFX10 OOB_SELECT table in Mesa ac_descriptors.c, not measured on hardware. Whether OOB_SELECT 3 checks each dword of a multi-dword fetch separately is unknown. OOB_SELECT 0 and 1 keep the structured record checks.
-
sceAgcCbCondWrite (libSceAgc) - argument order and the 9-dword COND_WRITE layout follow the clean-room OpenAGC and sharpemu, which agree on them; SharpProspero lists another order. The write space is accepted only as 1 (memory), the one value both encode the same way, and other values throw.
-
sceAgcAcbAtomicGds_0900 (libSceAgc) - signature, control/mode bit mapping and the 11-dword ATOMIC_GDS (0x1d) layout follow the clean-room OpenAGC only, which derives them from the library's disassembly; KytyPS5 and shadPS4 have no body for it. Not confirmed on hardware or a title (PPSA07286 imports it, nothing was run), and the driver has no ATOMIC_GDS handler (opcode 0x1d is not executed as an atomic GDS operation)
-
sceAgcGetIsTrinityMode (libSceAgc) - signature from the only PPSA26344 call (a pointer to a one-byte flag, result ignored); a null pointer throws because its error code is unknown
-
sceAgcDcbAtomicGds_0900 (libSceAgc) - name from its NID (
zARR5aCmkoY), the DCB counterpart ofsceAgcAcbAtomicGds_0900, signature unknown -
sceAgcDcbContextStateOpGetSize (libSceAgc) - sizes from KytyPS5 only (5, 27, 27 and 32 dwords), equal to what
sceAgcDcbContextStateOp_0100writes; KytyPS5 returns 0 for an operation above 3, here it throws -
sceAgcBranchPatchSetThenTarget_0300, sceAgcBranchPatchSetElseTarget_0300 (libSceAgc) - names from their NIDs (
7Wa3aeJgeVU,rP5xLdOf26k); the(packet, cachePolicy, target, sizeInDwords)signature is inferred from PPSA28416's calls (a branch packet, 0, an aligned target, 4), with the policy stored wheresceAgcCbBranchputs it -
sceAgcDcbSet{Cx,Sh,Uc}RegistersIndirectGetSize (libSceAgc) - the count argument is ignored: PPSA28416 calls them with leftover register contents (0xf5f5039c), so the real functions likely take none; the size is 20 bytes either way
-
sceAgcUpdateInterpolantMapping_0100 (libSceAgc) - name from its NID (
k0E7vkgqAuE); the(regs, vs, ps)arguments are the declared ones, behaviour unknown -
sceFontCharacterGetSyllableStringState (libSceFont) - the signature
(textCharacter, int* syllableStringState)follows SharpProspero. Measured on PS4 firmware 11.00libSceFont.sprx(not on a PS5): the state is 0 for Latin, CJK, Hangul, Arabic, Hebrew, Devanagari and the other scripts tried, and the library sets 1, 3 or 4 (never 2 on real text) for Thai while it creates the string; a null character or a null result returnsSCE_FONT_ERROR_INVALID_PARAMETER, and a null character writes 0 to a non-null result. This returns 0 for every character outside the Thai block (U+0E00 to U+0E7F), as KytyPS5 does, and throws for Thai characters, whose cluster states are not modelled. SharpProspero'sSceFontSyllableStringnames 0 NonDetection, 1 Starting, 2 Following, 3 Depending and 4 Connecting. PPSA06699 (Hot Shots Golf 2) calls it. -
sceAgcWriteDataPatchSetDst, sceAgcWriteDataPatchSetCachePolicy and their Async forms (libSceAgc) - the signatures
(packet, uint8 value)are inferred from the other patch functions, as no public declaration was found; the value is taken in the encoding of thedstandcachePolicyarguments ofsceAgcDcbWriteData(graphics) andsceAgcAcbWriteData(Async, compute), and the patched packet is the one those calls would write.sceAgcAsyncWriteDataPatchSetAddressOrOffsetis assumed to patch the address likesceAgcWriteDataPatchSetAddressOrOffset, as the compute WRITE_DATA packet keeps it in the same dwords -
dbOlWdppb4o (libSceAgc) - unknown name; same arguments as
sceAgcCreateInterpolantMapping_0100; theSPI_PS_INPUT_CNTLbits foris_f162 inputs follow KytyPS5, not confirmed on hardware -
sceAgcGetDataPacketPayloadRange (libSceAgc) - signature, the
{base, size in bytes}output and the type 0 range (header + 1, one dword longer than the type 1 payload) from KytyPS5 only, matchingsceAgcGetDataPacketPayloadAddress_0090; prosper returns header + 2 for both types from that address function -
sceAgcAsyncCondExecPatchSetCommandAddress, sceAgcAsyncCondExecPatchSetEnd (libSceAgc) - no reference has a body for them; they are assumed to patch the COND_EXEC packet like
sceAgcCondExecPatchSetCommandAddressandsceAgcCondExecPatchSetEnd, sincesceAgcAcbCondExecwrites the same packet assceAgcDcbCondExec, assceAgcAsyncRewindPatchSetRewindStatedoes for REWIND -
sceAgcAcbAtomicGds_0900 (libSceAgc) - name from its NID (
gQkqkLttcpw), signature unknown -
sceAgcDcbPrimeUtcl2 (libSceAgc) - assumed to write the packet
sceAgcAcbPrimeUtcl2writes: PRIME_UTCL2 has the same 5 dwords on the graphics and compute rings. Not confirmed on a title. Both write a NOP of that size, as there is no TLB to prime -
sceAgcDcbQueueEndOfShaderActionGetSize (libSceAgc) - the builder is inline in the SDK and not exported; the size is assumed to be that of the RELEASE_MEM packet
sceAgcCbReleaseMemwrites (32 bytes), the same assceAgcAcbQueueEndOfShaderActionGetSize, as in OpenAGC and REmu -
sceKernelInternalMemoryGetModuleSegmentInfo (libkernel) - unknown signature
-
sceKernelGetModuleInfoForUnwind (libkernel) - on Linux the tables come from
sceKernelGetModuleInfoFromAddr, whoseeh_frame_sizeincludes the zero terminator, as measured on firmware 13.60 (reported in #2419, not reproduced here); on Windows it is assumed to stop before the terminator. LLVM libunwind'sCFI_Parser::findFDEstops at the terminator or the length, whichever comes first, so it finds the same FDEs either way. Only the main executable and.guest.prximages report tables; other host images report none, as on Windows -
sceKernelGetModuleInfoFromAddr (libkernel) - the 0x1A8-byte info layout follows the shadPS4 reimplementation; a title's
libc.prxreads onlyid(PPSA14632). The meaning offlagsis unknown; only 2 is accepted. The inputst_sizeis ignored, because PPSA21703'slibc.prxpasses an uninitialized 0x1A8-byte buffer; the full size is written back. The id is thesceKernelLoadStartModulehandle of an image opened through the loader and otherwise a stable id from the same range. The name is the host file name without.guest.prx. An image with more than 4 load segments (the converted executable has 7) reports its first 4.tls_offsetis 0 andref_countis 1, as the host loader exposes neither. On Windows the module is the PE image holding the address: a relinked image reports its.elfsections as segments and the eh_frame_hdr recorded in.ehmeta, any other image its first 4 sections with memory access and the.ehframsection without an eh_frame_hdr; the TLS fields andinit_proc_addr/fini_proc_addrare 0 -
sceKernelGetModuleList (libkernel) - lists the main program and every loaded
.prximage in load order; host runtime libraries are left out. The handles are the idssceKernelGetModuleInfoFromAddrreports, not the console's. The(int32_t* handles, size_t count, size_t* actual)signature and returningENOMEMwithout writingactualafter filling the firstcounthandles when more images are loaded follow shadPS4; whether the console writes any handles in that case is unknown -
sceKernelGetModuleInfo (libkernel) - the 0x160-byte layout (
st_size,name[256], 4 segments,segment_count,fingerprint[20]) follows fpPS4 and shadPS4. Only thatst_sizeis accepted, as in shadPS4; other sizes returnEINVAL, a null pointerEFAULTand a handlesceKernelGetModuleListdoes not listESRCH. Name and segments are the onessceKernelGetModuleInfoFromAddrreports, on Windows from the same PE sections, soprotuses the read/write/execute bits 1/2/4, while fpPS4 and shadPS4 store the ELFp_flags. The fingerprint is left zero, as the host image does not carry it -
sceKernelReleaseFlexibleMemory (libkernel) - unmaps the range like sceKernelMunmap, as fpPS4 and prosper do; whether the console keeps the virtual range reserved after releasing its pages is unverified
-
sceKernelAvailableFlexibleMemorySize (libkernel) - the segments of the title's executable and of its
.guest.prxmodules count against the 448 MiB flexible budget while they are loaded, for this size and for the flexible maps, as shadPS4 maps every segment of a module outside its system module directory as flexible memory on the PS4. Counted are the segments the title's ELF gives permissions, each rounded to 16 KiB pages; not counted are segments without permissions, the relinker's own blocks (on Linux both are the read/write/executePT_LOADs, plus the header block at file offset 0; on Windows everything outside the.elfsections) and the host system libraries. The Linux image carries no marker for the relinker's blocks, so they are told apart by those flags and that offset only: a title segment that is writable and executable, or starts at file offset 0, is not counted. A module whose segments exceed what is left still loads, and the available size then reads 0; shadPS4 fails the segment map instead (memory.cpp returnsEINVAL, module.cpp asserts). Which segments the PS5 charges, its rounding, whether system modules use the title's budget and when an unload releases the charge are not measured. PPSA15508 subtracts the reported size and a 10 MiB module allowance from its own 448 MiB budget at start-up and stops when the result exceeds its 146 MiB code and data limit (#2883) -
Memory protection bits 0x100 and 0x200 (libkernel) - taken as audio coprocessor (ACP) read and write, as in the KytyPS5 and etaHEN headers; the coprocessor work runs on the host CPU, so they grant host read and read/write access like the GPU bits
-
_umtx_op (libkernel) -
UMTX_OP_WAIT,UMTX_OP_WAKE,UMTX_OP_WAIT_UINT,UMTX_OP_WAIT_UINT_PRIVATE,UMTX_OP_WAKE_PRIVATEandUMTX_OP_NWAKE_PRIVATEfollow FreeBSD 11's kern_umtx.c: a timeout whose size argument is at most 16 is a relativetimespec, a larger one an_umtx_time, and a wake of 0 or fewer wakes one waiter.UMTX_OP_NWAKE_PRIVATEreads the value as anintcount of pointers at the object and wakes every waiter on each one; a count of 0 or fewer reads nothing, and a null list fails withEFAULT, where FreeBSD'scopyinwould also fail for any other unreadable list. Waiters share the queue ofsceKernelSyncOnAddressWait. Operation 0 fails withEOPNOTSUPPand operations above 26 withEINVAL, as in FreeBSD 11;UMTX_OP_WAIT_UINTwith a value that does not fit in 32 bits returns 0 at once, as FreeBSD's zero-extended compare does. Operation 1 throws, since PPSA12544's call_once uses it in a way FreeBSD rejects; the other operations throw, and so does a misaligned object. PPSA12544'slibc.prxpassesUMTX_OP_WAITandUMTX_OP_WAIT_UINTa pointer to a 4-byte microsecond timeout with size argument 0, which FreeBSD reads as atimespec, and waits for a running call_once with operation 1; itsPS5Util.prxpasses atimespec. Whether the console reads a microsecond timeout there, and what operation 1 does on it, is unverified. A libc call cannot be told apart from atimespeccall by the size argument alone, so a timeout with size argument 0 is read as atimespecand only throws when it is not a valid one (negative seconds, nanoseconds outside [0, 1e9)), which is where FreeBSD would returnEINVAL; a microsecond value that happens to read as a validtimespecis waited on as one -
sceKernelSyncOnAddressWait (libkernel) - the only known caller passes a null timeout and a name string as the fourth argument; the timeout is assumed to point to microseconds like the other kernel waits, and the name is ignored
-
sceKernelSyncOnAddressWait8 / sceKernelSyncOnAddressWait16 / sceKernelSyncOnAddressWait32 / sceKernelSyncOnAddressWait64 (libkernel) - libc's
__std_atomic_wait_direct_8/16/32/64pass a microsecond timeout or null and ignore the result; the by-value comparand, return values and the 2- and 8-byte alignment of Wait16 and Wait64 are assumed -
scePthreadRwlockDestroy, pthread_rwlock_destroy (libkernel) - a rwlock held for reading or writing returns
EBUSYand keeps its handle, as KytyPS5 does; FreeBSD's libthr and shadPS4 free it without checking, and the console's answer is unverified. Destroying a rwlock while another thread is acquiring it is not guarded -
scePthreadCondWait / scePthreadCondTimedwait (libkernel) - before waiting, FreeBSD libthr's
cond_wait_commonchecks ownership through_mutex_owned: an unowned mutex returnsEPERM, while its destroyed marker returnsEINVAL. An untouched adaptive static initializer (slot value 1) therefore returnsEPERM; the test covers this, an uninitialized slot, a mutex owned by another thread, and the destroyed marker for both timed and untimed sce and POSIX waits. A recursive mutex locked several times is released completely for the wait and relocked to the same depth afterwards, as FreeBSD libthr does (_mutex_cv_unlock,_mutex_cv_lock). These FreeBSD-derived behaviors remain unverified on console hardware -
sceKernelAioSubmitReadCommandsMultiple / sceKernelAioSubmitWriteCommandsMultiple / sceKernelAioWaitRequests / sceKernelAioPollRequests / sceKernelAioCancelRequest / sceKernelAioCancelRequests / sceKernelAioDeleteRequests (libkernel) - behaviour from shadPS4 (one id per request for the Multiple submits, cancel turns any request aborted and id 0 reports processing, wait mode 2 returns once one request completed, poll copies every state without waiting); the 128 requests or ids per batch limit is from SharpProspero, with an unknown error, so larger batches throw; wait modes other than 1 (and) and 2 (or) throw; null pointers, negative counts and invalid ids return the codes the single-request siblings use, checked before any state is written
-
sceKernelGetAvailableCpumask (libkernel) - returns the default thread affinity, 0x1FFF (CPUs 0 to 12), as KytyPS5 does. Titles pin threads within it (PPSA02664 passes 0x1FFB, Hades II PPSA36082 0x3 and 0x3F); whether CPU 13 is available to a title is not confirmed
-
sceKernelGetCurrentCpu (libkernel) - guest affinities are not applied to host threads, so the host CPU index is mapped into the calling thread's affinity clipped to
sceKernelGetAvailableCpumask(the available mask when they do not overlap): host CPU n reports the (n modulo the CPU count)-th CPU of that mask, so a thread pinned to one CPU reports that CPU, as a FreeBSDcpusetguarantees on the console. Which CPU the console reports for a thread allowed on several is not known; shadPS4 returns 0 -
pthread_attr_setsolosched_np (libkernel) takes
(attr, int)and stores the value throughscePthreadAttrSetsolosched, returningEINVAL(22) for a null or uninitialized attribute like the other POSIX attribute setters. Only the name is public (aerolib2+pVfgiEd7A); the signature and behaviour follow the SCE twin, which KytyPS5 and sharpemu store as anintwithout a range check, and PS5PCEM implements this alias over it. Any value is accepted and threads created from the attribute are not scheduled differently; what solo scheduling does on the console and which values it rejects are unverified. Returnal (PPSA01285 v03.000.005) stopped on it withwhat(): pthread_attr_setsolosched_np_nid_postfix not implemented(#2872, #1155); LEGO Horizon Adventures (PPSA14632, #734) and Palworld (PPSA23126, #2598) import it -
sceKernelMapNamedFlexibleMemoryInternal (libkernel) - flag 0x8000 is accepted and ignored; its meaning is not established. KytyPS5 (
GUEST_MAP_UNKNOWN_8000) and sharpemu accept it without reading it. Every known caller is the SDK 9libc.prxheap (Astro Bot PPSA21564, PPSA22520), which passes it with read/write protection and uses the mapping as an olderlibc.prxusessceKernelMapNamedFlexibleMemorywith flags 0 -
sceKernelMtypeprotect (libkernel) - sets the memory type of the direct mappings in the page-rounded range and of the direct memory behind them, as shadPS4 and prosper do (KytyPS5 ignores the type); the type is not validated, flexible pages in the range only get the protection, and a later map of the retyped direct memory reports the type it was allocated with.
sceKernelBatchMap2operation 4 takes the same path with the entry type -
Map hints inside a reservation (libkernel) -
sceKernelMapDirectMemoryand the flexible and anonymous maps place a mapping withoutMAP_FIXEDat its hint address when the whole range lies in a range still reserved bysceKernelReserveVirtualRange, as ifMAP_FIXEDwere set. Taken from PPSA01474, which reserves 64 GiB and then maps its heaps inside it with hints and noMAP_FIXED, and uses the hint addresses afterwards; not measured on the console. Hints outside a reservation, or over a range that is partly mapped, stay hints -
Guest arena (libc) - the application map area is assumed to end at 0xFC_0000_0000, as
SCE_KERNEL_APP_MAP_AREA_END_ADDRdoes on the PS4. On Windows, host allocations made in the arena before libc loads stay, and a fixed guest mapping over one throws -
sceLibcInternalBacktraceForGame (libSceLibcInternal, implemented in libc) - unknown signature
-
sceLibcInternalHeapErrorReportForGame (libSceLibcInternal, implemented in libc) - unknown signature
-
malloc_usable_size (libc) - with the default allocator it returns the size the block was requested with (the range registered for it), not the rounded-up chunk size Sony's allocator reports; both satisfy "at least the requested size", and bytes past the request would not be write-watched. With an application allocator it calls entry 9 of the replacement table (
malloc_usable_sizein KytyPS5'sMallocReplaceorder) and throws when the table leaves it null, likemalloc_stats_fast -
reallocf (libSceLibcInternal, implemented in libc) - follows FreeBSD 11
lib/libc/stdlib/reallocf.con top of this libc'srealloc, not measured on the console: size 0 frees the block and returns null asreallocdoes here, so the block is not freed twice; whenreallocfails because the application allocator returns null or the default heap rejects the size, the block is freed through the same allocator,errnoisENOMEMand null is returned. Other failures (an exhausted guest arena, an unknown pointer) throw, as they do forrealloc -
_sceLibcInternalThreadAtexit, _sceLibcInternalThreadDtors (libSceLibcInternal) - FreeBSD
__cxa_thread_atexitsemantics assumed; a null or non-image destructor and an allocation failure throw -
_sceKernelRtldThreadAtexitIncrement, _sceKernelRtldThreadAtexitDecrement (libkernel) - the argument is the
dsoaddress a title'slibc.prxpasses to__cxa_thread_atexit(PPSA14632), which fails when Increment returns nonzero. As in the fpPS4 reimplementation, Increment takes a reference on the loaded image containing the address and Decrement releases one; the variants without the leading underscore are assumed to match -
sceImeGetPanelPositionAndForm (libSceIme) - the output is taken to be the
PositionAndFormthatsceImeDialogGetPanelPositionAndFormfills; it is never written, since no panel can be open. That a closed panel is reported before a null output is assumed by analogy withsceImeSetCaret, not confirmed on a PS5 title -
_sceLibcInternalForceTlsDestructor (libSceLibcInternal) - behaviour follows
sceLibcForceTlsDestructor(int)in a title'slibc.prx(disassembly): the calling thread's destructors whose dso belongs to the module run newest first, only if the dso's module is loaded and the dso points to itself, in up to 4 passes. The return type is unknown (that function returns nothing), 0 is returned. The module of each dso is looked up when the destructors are forced, not when they are registered aslibc.prxdoes -
acosl (libc) - computed by the host's math library, like the other libc math functions here, not by the console's (FreeBSD msun ld80 code in Sony's
libc.prx): results can differ from the console's in the last bit, and on Linux glibc setserrnotoEDOMforacosloutside [-1, 1] where msun only raises the floating-point exception.long doubleis the x87 80-bit format, as Sony'sfrexpluses it (fldt 0x8(%rsp), result inst(0)) -
atanl, sinl, cosl, tanl, sinhl, coshl, tanhl, expl, exp2l, logl, log10l and powl (libc) - computed by the host's math library, as
acoslis, not by the console's FreeBSD msun ld80 code: results can differ from the console's in the last bit (glibc'slog10l(1000)is not exactly 3), and on Linux glibc setserrnotoEDOMorERANGEwhere msun only raises the floating-point exception.ldexplandtrunclare exact operations and give the console's result;logbandremaindergive the console's value too, but on Linux glibc setserrno(ERANGEforlogb(0),EDOMforremainderby zero or of an infinity) where msun only raises the floating-point exception -
std_execute_once (libc) - assumed to be the plain-named twin of
std::_Execute_once(_ZSt13_Execute_onceRSt9once_flagPFiPvS1_PS1_ES1_, the callee of Dinkumwarecall_once): it delegates there and gets the [thread.once.callonce] semantics already verified for that symbol (one invocation per flag, concurrent callers block until it completes, and a failing or throwing invocation leaves the flag unready so the next caller runs it). The name equivalence is not confirmed on a title, and the callback convention (called with (null, arg, null), non-zero return meaning success) is the twin's, unverified for this symbol -
Dinkumware mutexes and conditions (libc) use pointer-to-handle arguments, matching the console aerolib signatures reported in #3079. The title's
_Mtx_lockmaps0to_Thrd_success(0),0x8002000bto_Thrd_busy(3), and other failures to_Thrd_error(4); its internal mutex init recognizes recursive flag0x100, while every other type uses default attributes. The observed relock failure for a plain mutex suggests those defaults are error-checking, but that has not been confirmed on hardware. The title's_Mtx_unlockand_Cnd_waitreturn success regardless of their internal result. The host implementation treats invalid ownership preconditions as no-ops, and throws for invalid handles, host wait errors and destroying a locked mutex as debug guards; those cases are not confirmed against the console. -
random, srandom, initstate, setstate (libc) follow FreeBSD 11 random.c: the additive feedback generator on a default 128-byte
TYPE_3table,good_randseeding, state sizes rounded down to 8, 32, 64, 128 or 256 bytes, andsetstatereturning the previous state or null for a rear position past the degree.initstatebelow 8 bytes returns null without setting errno, as that file and its manual do (glibc setsEINVAL). FreeBSD does not lock the generator; here every call is serialised by one lock, so concurrent callers draw the serial sequence between them. A null state throws, where FreeBSD faults. That the console'slibSceLibcInternaluses this FreeBSD code and not another generator is unverified -
tcgetattr, tcsetattr (libkernel) - every file and pipe descriptor is taken as not a terminal (
ENOTTY), and a socket getsEADDRNOTAVAILforAF_INETandEOPNOTSUPPotherwise, as FreeBSD'sin_controlandpru_control_notsuppanswer a termios ioctl; what descriptors 0 to 2 of a title are on the console, and whether any of them is a terminal there, is unknown -
select (libkernel) - descriptor 0 is never reported readable and descriptors 1 and 2 are always writable, as for a console title with no input; reads from descriptor 0 still go to the host stdin.
/dev/randomand/dev/urandomare always readable and writable, as FreeBSD reports a seeded random device. Other descriptors that are not libSceNet sockets throw. Dungeons (PPSA16064) selects on descriptor 0 -
select (libkernel) - a descriptor the socket poller reports as unknown that is below
GuestSockets::FirstDescriptoris polled on the host instead of throwing, except on Windows where it still throws; an invalid host descriptor fails withEBADF, and mixed host and socket sets are polled in short alternating slices so neither side waits out the full slice alone. Wobbly Life (PPSA29413) selects on file descriptors while streaming its bundles -
__progname (libkernel) - unknown data export
-
environ (libkernel) - data export pointing to a fixed empty environment so titles that import it load; it is not the environment libc's
getenvreads, so it lists none of those variables andsetenv/putenvchanges do not appear in it -
seteuid, setegid (libkernel) - the guest process is assumed to run as root, with real, effective and saved user and group ids 0. As in FreeBSD's
sys_seteuidandsys_setegid, id 0 is then accepted without a privilege check and changes no credential, so 0 is returned; any other id would change the effective id, which is not modelled, and throws. The ids and privileges a title has on a console are unverified -
pthread_barrierattr_setpshared (libkernel) - PTHREAD_PROCESS_SHARED is accepted on the assumption that the console follows FreeBSD 11.0 libthr, which accepts it (9.0 rejects it with EINVAL); unverified on hardware. Guest code runs in one process, so a shared barrier behaves as a private one
-
pthread_getname_np (libkernel) - a thread that has already been joined returns
ESRCH(3) on a PS5 (firmware 13.60), but its object is freed after the join here, so the pointer cannot be told apart from a live thread and its name is read as for a live one -
sceSslClose (libSceSsl) - unknown signature
-
sceSslGetSerialNumber (libSceSsl) - unknown signature
-
sceAudioInIsPadEmbeddedMic (libSceAudioIn) - name from its NID (
X+4jdIS75P0); signatureint32_t(int32_t handle)from the Ghost of Yotei (PPSA26344) call site in #2355; the result's meaning is unconfirmed, so it still throws rather than invent one -
sceAudioOut2Set3DLatency (libSceAudioOut) - assumed to take
(user_id, latency): KytyPS5 reads(user_id, output, latency_us), but the known calls set just edi and esi; only(0xFF, 2)(PPSA26344) and(0xFF, 1)(PPSA14632) are accepted -
sceAudioOut2MasteringInit (libSceAudioOut) - flag values unknown; only 0 is accepted. Whether the console reports an error for a repeated
sceAudioOut2MasteringInitor forsceAudioOut2MasteringTermwithout a matching initialization is unknown; both return 0. PPSA01289 creates the audio device of its next world before it destroys the previous one, so it calls Init twice before Term twice, and only logs a non-zero result -
sceAudioOutSetMixLevelPadSpk (libSceAudioOut) - effect of a negative mix level unknown; only 0 to 32768 (0 dB) is accepted
-
sceAudioOutSetMixLevelPadSpk (libSceAudioOut) - no source applies the level (shadPS4 only stores it); it is assumed to be a linear gain on the port's own output, and the -9 dB default (11626) is applied to every pad speaker port, including those of titles that never call the function
-
sceAudioOutGetLastOutputTime (libSceAudioOut) - signature and behaviour taken from the shadPS4 and fpPS4 reimplementations of the PS4 library, not confirmed on a PS5 title: the time is the process time at which
sceAudioOutOutputorsceAudioOutOutputsaccepted the port's last block, not the time the block reached the device -
sceAudioOutSysClose, sceAudioOutSysConfigureOutput, sceAudioOutSysOpen (libSceAudioOut) - imported by PPSA99051 and PPSA99997, which fail to load without them; added without an implementation and declared without parameters. EVO-PLAYER-PS5, whose audio code both titles share, calls
sceAudioOutSysOpen,sceAudioOutSysConfigureOutputandsceAudioOutSysCloseonly to open a port for HDMI bitstream passthrough. Its declared arguments are not confirmed on a console. Audio reaches the host device through SDL as PCM, so there is no HDMI output to switch -
sceAudioOut2PortCreate (libSceAudioOut) - MAIN (type 0) format validation follows PS5 firmware 13.60 measurements: bits 8-11 accept 1, 2, 8 or 12, bits 0-6 accept 0 or 1, bit 7 requires 8 channels, and bits 12-31 do not affect validation. The sample types are still read as float and int16; bit 7's layout, the PCM effect of bits 12-31 and the port
flagsare unverified. Other port types retain unverified format validation, including 6 channels and rejection of bits 12-31 -
sceAudioOut2PortCreate (libSceAudioOut) - 12 channels are assumed to be L R C LFE Ls Rs Lb Rb Ltf Rtf Ltb Rtb as in KytyPS5's 12-to-8 fold, and 6 and 8 channels to be its first 6 and 8; no title or SDK header confirms the order
-
sceAudioOut2PortCreate (libSceAudioOut) - the stereo fold is assumed, not the console's downmix: C at -3 dB into both sides, Ls/Rs, Lb/Rb and Ltf/Rtf at -3 dB and Ltb/Rtb at -6 dB into their own side, LFE dropped
-
sceAudioOut2PortSetAttributes (libSceAudioOut) - each PCM buffer set (attribute 0) is taken as one grain: buffers set between two pushes are queued and played one per grain, at most 16 queued. A grain with no new buffer repeats the last one only when the port has always been given that same buffer (rewritten in place); a port whose buffers move on plays silence instead. Inferred from PPSA12544, whose object port (type 6) is given one grain of a 64-grain ring per set, often two or three between pushes and then none for a few; the console behaviour for several sets per push and for a push without a new buffer is not documented
-
scePsmlMfsrGetContextBufferRequirement1100, scePsmlMfsrCreateContext1100, scePsmlMfsrGetDispatchMfsrPacket1100 (libScePsml_debug) - argument layouts unknown; only 0x8A810001 (not initialized) is returned
-
scePsmlMfsrGetDispatchMfsrPacket1000 (libScePsml) - unknown signature, imported by PPSA25344; declared without parameters. libScePsml and libScePsml_debug are built from the same source
-
scePsmlMfsrCreateContext1300, scePsmlMfsrGetDispatchMfsrPacket1300 (libScePsml) - unknown signatures, imported by PPSA28416 next to
scePsmlMfsrGetContextBufferRequirement1100; declared without parameters. The names are not in the aerolib NID list; they hash to the imported NIDskLF7WtQ1-DgandDDVUyPyYHTA(tools/nid_names.py) -
scePngEncEncode (libScePngEnc) - whether rows may stay unfiltered when
filter_typenames a subset of the filters is unknown; as in shadPS4, they may only for 0 and for the all-filters mask -
sceJpegEncEncode (libSceJpegEnc) -
restart_intervalfollows SharpProspero's field doc (0 none, -1 every row of blocks, positive a block count); a positive value is taken as the JPEG DRI interval in MCUs and -1 as one restart per MCU row, which no reference confirms. Other negative values throw -
sceVoiceQoSInit (libSceVoiceQoS) -
0x804E0905for a second initialization comes from prosper's reading of the module and was not measured: on a PS5 a valid call blocks inside a homebrew payload, so it never returns there. The app type and the block are not used, as no endpoint is implemented -
AudioIn and NpSessionSignaling exports added without an implementation have assumed signatures
-
sceNpSessionSignalingGetConnectionFromPeerAddress (libSceNpSessionSignaling) - imported by PPSA01289 and added without an implementation; unknown signature
-
vieBRwlh1Lw (libSceAgc) - unknown name; the
(regs, gs, ps)arguments ofsceAgcCreateInterpolantMapping_0100come from OpenAGC only -
scePadIsRemoteController (libScePad) - the name hashes to NID
fCWdlnmB1Ks; the signature(int handle, bool* remote)comes from PPSA16064, which zeroes a byte, passes its address afterscePadGetControllerInformationand ignores the result. The error codes follow the other pad calls. Controllers are local devices, so the answer is always false -
scePadSetAngularVelocityBiasCorrectionState (libScePad) - inferred signature
(int handle, bool enabled)followsscePadSetTiltCorrectionStateandscePadSetAngularVelocityDeadbandState; an invalid handle returnsPAD_ERROR_INVALID_HANDLE, disabling is a no-op, and enabling throws because bias correction is not modelled -
sceKernelGetOperationMode (libkernel) - the signature
(int* mode, int* submode)comes from PPSA12544, which logs both values after the call and ignores the result. A homebrew payload on a PS5 (firmware 13.60) reads mode 2 and submode 0, nothing else is written, and the result register holds no status, so the function is taken to return nothing. Whether a title process reads the same values is unverified. Null outputs throw -
Font, Http2, Net, Ssl, SystemService and libkernel exports imported by PPSA12544 and added without an implementation have unknown signatures
-
sceHttp2GetMemoryPoolStats, sceSslGetMemoryPoolStats, sceNetGetMemoryPoolStats (libSceHttp2, libSceSsl, libSceNet) - the signatures
(int id, stats*), the layouts (pool size, peak and current use, and for Http2 and Ssl a 32-bit reserved field) and the error codes were measured on a PS5 (firmware 13.60). The pool size is the one given at init or pool creation; nothing is allocated from these pools, so the peak and current use are 0, where the console already reports use right after initialization (0x15C0 bytes for Ssl, 0x1640 for Http2 and 4 for a Net pool) -
sceNpWebApi2GetMemoryPoolStats (libSceNpWebApi2) - imported by PPSA21703's Unity PSN plugin. The signature
(int libCtxId, stats*)and the layout of the Http2 statistics above (measured on a PS5 for Http2, Ssl and Net) are assumed for this library, not measured. The pool size is the one given tosceNpWebApi2Initialize, and the peak and current use are 0. The error codes are unknown, so a null output or an unknown context throws -
sceSslGetCaList, sceSslFreeCaList, sceSslUnloadCert (libSceSsl) - signatures and the 16-byte
SceSslCaListlayout (an array of certificate handles and a 32-bit count) follow SharpProspero and shadPS4'sOrbisSslCaList, not confirmed for the PS5. On the console the list holds the certificate authorities the SSL service has; shadPS4 returns a placeholder certificate fromsceSslGetCaCertsbecause Rise of the Tomb Raider fails its initialization checks without one. No root certificate bundle is shipped and no loaded certificate is kept, so here a context holds none:sceSslGetCaListclears the list and returnsNOT_FOUND, assceSslGetCaCertsdoes,sceSslFreeCaListaccepts only that cleared list, andsceSslUnloadCert(imported by PPSA15508) has nothing to drop and is assumed to return 0. A null list returns0x8095177A, whichsceSslGetCaCertsand KytyPS5 return for a null argument (shadPS4, PS4, returns0x8095F007). An unknown context throws (KytyPS5 returnsSSL_ERROR_INVALID_ID,0x8095F006, fromsceSslGetCaCerts), and so does a listsceSslGetCaListdid not return -
sceHttp2SetResolveRetry (libSceHttp2) - signature
(int id, int32_t retry)from libSceHttp'ssceHttpSetResolveRetry; the value is accepted and ignored like the other Http2 settings, since no request reaches the network -
sceHttp2WebSocketCreateRequest, sceHttp2WebSocketCloseAsync, sceHttp2WebSocketSendTextMessageAsync, sceHttp2WebSocketSendDataMessageAsync (libSceHttp2) - imported by PPSA16064 and not called during its start-up; unknown signatures
-
The Share, NpTrophy2, NpEntitlementAccess and WebBrowserDialog exports imported by PPSA12544's Unity plugins and added without an implementation have unknown signatures
-
sceNetShowNetstat (libSceNet) - imported by PPSA11386 and not called during its start-up; unknown signature, declared without parameters
-
sceAjmDecWVorbisCreateHeaderPacket, sceAjmDecWVorbisCreateSetupPacket (libSceAjmWVorbis, implemented in libSceAjm.native) - unknown signatures
-
Acm, GameLiveStreaming, Net, NpEntitlementAccess, NpManager, NpWebApi2, VoiceQoS, WebBrowserDialog and libkernel exports imported by PPSA14632 and added without an implementation are declared without parameters
-
libSceAudioPropagation (libSceAudioPropagation) - signatures and struct descriptors recovered from PPSA21567's calls (#481), not from documentation. The system options layout is unknown (only checked for non-null); the fourth argument of
sceAudioPropagationSourceCalculateAudioPathsis unknown;sceAudioPropagationSourceGetAudioPathis assumed to output an 8-byte path handle. The meaning of theRenderInfoword at +0x28 is unknown (PPSA21567 and PPSA21564 pass 2); only 2 is accepted. Both titles pass oneRenderInfoper call: a count of 0 throws, and larger counts are handled element by element without proof. No error code is known, so invalid input throws instead of returning one -
NGS2 mastering voice gain (libSceNgs2.native) - the param id 0x30000004 is taken from PPSA22520 and the layout from shadPS4's
OrbisNgs2MasteringVoiceGainParam; no reference gives the units or range. The levels are assumed to be linear factors applied when the mastering voice is mixed into the render buffer, so the voice's own samples stay unscaled; the LFE level applies to channel 3 of 6- and 8-channel voices, assuming the L R C LFE order of the AudioOut2 entries above, and the full-band level to the rest. Negative levels are accepted, and a new setup resets both levels to 1 -
NGS2 stereo mastering voice into a surround buffer (libSceNgs2.native) - PPSA21402 renders a 2-channel mastering voice into a 6- or 8-channel render buffer, which the mixing stage rejected. The console's conversion is unknown: the left and right channels are assumed to go to the first two buffer channels (front left and right) and the remaining channels stay silent, with no centre, LFE or surround content. Any other channel count mismatch still throws
-
NGS2 silent waveform blocks (libSceNgs2.native): flag
0x10(namedSILENCEhere; no public reference names it) lets a waveform block declare samples without data. PPSA04867 adds one block with flags0x11,data_size0 andnum_samples16385, then another with flags0x11and a fully specified 0x800-byte, 1024-sample mono block, which takes the ordinary path. A dataless block under the flag outputsnum_samplesframes of silence, reports them throughdecoded_data_size, and finishes like a complete block; a dataless block without the flag still throws as not fitting its data. The flag's real name, its interaction with ATRAC9 and repeats, and the console'swaveform_datafor silent blocks are unverified on hardware -
NGS2 streaming PCM waveforms (libSceNgs2.native) - PPSA21402 streams its music by adding one block whose
num_samplesis the whole track and whosedata_sizeis a 16 KiB first piece, withCONTINUE, and then adds each following piece with flag0x2(calledAPPENDhere) and the samenum_samples. No reference describes flag0x2. A 16-bit PCM block without skipped samples or repeats whosenum_samplesexceed its data is assumed to start such a stream; flag0x2is assumed to append the block's data to the last streaming block, ignoring itsnum_samples; the voice is assumed to output silence without advancing while it has played all appended data andCONTINUEis set; and the waveform is assumed to end atnum_samplesor, onceCONTINUEis cleared, at the end of the appended data.sceNgs2VoiceGetStatereports the bytes played asdecoded_data_size, which the title uses to release its queued data, and the read position aswaveform_data. Appending to a block that is not a stream, or other formats, skipped samples, repeats and partial frames, throw -
NGS2 matrix levels (libSceNgs2.native) - levels are clamped to -4..4 and NaN is kept, as the PS4 firmware 11.00
libSceNgs2.sprxstores them; not yet confirmed on the PS5 library. That library rejects a level count of 0 and keeps the matrix; the PS5 error code is unknown, so a count of 0 throws.sceNgs2VoiceRunCommandsis not in that library, so its matrix levels command is assumed to clamp the same way -
sceAvPlayerStartEx (libSceAvPlayer) - start info layout unknown; it is ignored and playback starts as with
sceAvPlayerStart -
sceAvPlayerInit / sceAvPlayerInitEx (libSceAvPlayer) - behaviour without a memory replacement unknown; frame and sample buffers then come from the guest heap
-
sceAvPlayerInitEx (libSceAvPlayer) - the PS5 init data layout (
this_size0x230: auto start at 0x74, nine 0x30-byte thread parameter blocks from 0x78, output video frame buffer count at 0x228) follows KytyPS5, prosper, SharpProspero and sharpemu, which agree on it. PPSA25063 fills the same fields, writes auto start 0 and starts playback withsceAvPlayerStart; a title that sets auto start has not been seen. A smallerthis_sizeis read with the PS4 offsets. The thread parameters are ignored -
AvPlayer auto start (libSceAvPlayer) - the auto start that
sceAvPlayerAddSourcequeues for a player with auto start or without an event callback starts the player only while it is still ready: a title that starts the player itself before the auto start runs keeps its playback and the frames it holds. Not confirmed on a title. -
SceAvPlayerVideoEx (libSceAvPlayer) - frame rate field and encoding unknown; it is left zero in frame and stream info
-
sceRazorCpuFlushOccurred (libSceRazorCpu) - signature and return values (1 = flush since the last call, 0 = none) from SharpProspero; without a capture nothing is flushed, so it returns 0 and writes 0 cycles to the optional out pointer (whether the real library writes it when nothing was flushed is unknown)
-
sceRazorCpuPushMarkerStatic, sceRazorCpuPopMarker (libSceRazorCpu) - signatures from PPSA26344's calls; (name, color, flags) assumed for the push; both do nothing without a capture
-
sceRazorCpuPlotValue, sceRazorCpuWriteBookmark (libSceRazorCpu) - signatures (series, float value) and (label, optional description) from SharpProspero, matching PPSA06320's calls; both do nothing without a capture and return 0
-
sceAjmBatchJobGetInfo (libSceAjm.native) - writes the result and format sideband of a run job without buffers with the
SIDEBAND_FORMATflag (0x400000000000), as KytyPS5 does, not confirmed on a PS5 title; the format reports bitrate 0 for ATRAC9 as in KytyPS5, while shadPS4 derives it from the superframe size; before the instance is initialized it returns the not-initialized result (1) and no format, like the other run jobs here, while KytyPS5 returns result 0 with the format of the uninitialized decoder -
sceAjmDecMp3ParseFrame (libSceAjm.native) - signature, result layout and rate tables taken from the shadPS4 reimplementation of the PS4 library, not confirmed on a PS5 title: the layer field is not checked and MPEG-2.5 stops at 64 kbps; the original file length (
parse_ofl) layout (Xing/Info + LAME tag, VBRI, Fraunhofer0xB4block with its CRC, encoder delay = samples per frame + LAME delay + 529) also comes from shadPS4 only, and the Fraunhofer block has no other public description -
NGS2 port matrix (libSceNgs2.native) - a port without a matrix, or with a selected matrix whose levels were never set, mixes through a default channel map: mono reaches both stereo channels at -3 dB and the 5.1 and 7.1 centre, stereo folds to mono at -3 dB per side, and wider sources fold down with 0.5 and -3 dB gains. The map and the equivalence of an unset matrix with no matrix were measured from the PS4 firmware 11.00
libSceNgs2.sprx, not yet from the PS5 library. That library only accepts submixer and mastering voices with 1, 2, 6 or 8 channels, so the map into 3, 4, 5 or 7 channels throws. A matrix set with fewer levels than the destination needs still mixes only the rows it has -
sceAjmBatchJobGetCodecInfo, sceAjmBatchJobGetGaplessDecode (libSceAjm.native) - the
RUN_GET_CODEC_INFOflag (0x800), the ATRAC9 codec info layout and its next frame size are taken from the shadPS4 and RPCSX reimplementations, not confirmed on a PS5 title; a run job without buffers returns result 0, as in shadPS4. The gapless sideband reports the total and skip counts the title set and does not count them down: RPCSX does the same, shadPS4 counts them down and BryKytyPS5 returns its current counts -
AJM Opus decoder (libSceAjm.native, codec 24) - the initialize parameter layout (
u32 channels, u32 sample rate, u32, seen as2, 48000, 0) and the little-endianu16byte count before each packet come from one title (The Smurfs Dreams); only 48000 Hz and a zero third word are accepted -
sceAjmBatchJobSetResampleParametersEx (libSceAjm.native) - the
(info, instance, float ratio_start, float ratio_change_per_sample, flags, result)signature is inferred from the name and fromsceAjmBatchJobSetResampleParameters; with a zero change per sample it sets the ratio assceAjmBatchJobSetResampleParametersdoes (Watch Dogs: Legion, PPSA01500, calls it so). How a non-zero change ramps the ratio is unknown and throws -
sceAjmBatchJobControl (libSceAjm.native) - RESET (bit 13), INITIALIZE (bit 14) and the sideband input order (gapless decode, then initialize parameters) come from shadPS4 (PS4); other flags throw
-
sceAjmBatchJobControl (libSceAjm.native) - RESET is assumed to clear the context as sceAjmBatchJobClearContext does
-
sceAjmBatchJobControl (libSceAjm.native) - initialize parameters are 8 bytes for ATRAC9, 12 for Opus and none for MP3, as one title passes them; other codecs and sizes, and an output other than the 8-byte result, throw
-
sceAjmBatchJobControl (libSceAjm.native) - SIDEBAND_GAPLESS_DECODE with RESET overwrites both counts as in RPCSX; shadPS4 ignores a zero count when the other is nonzero. Without RESET they differ, so it throws
-
NGS2 custom submixer rack (libSceNgs2.native, rack 0x4002) - structure layouts from shadPS4's
ngs2_custom.h; module id 0x1f for UserFx2, the voice parameter id0x40001f00 | module index, the process flags (1 on the first process call after setup, 2 after a parameter change, 0 otherwise) and the call order (setup per voice at rack creation, process after the inputs are mixed, cleanup at destruction) come only from KytyPS5. Only UserFx2 modules on a single buffer are accepted: other module ids, more buffers, a module control handler, different input and output channel counts, setup flags and default rack options throw. Each module's state is a separate buffer, not thestate_offsetslice of the voice state, andsceNgs2VoiceGetStatestill throws for this rack. As in KytyPS5, process runs only on grains where an input produced samples, so an effect tail stops with the input and a pending flag 2 waits for the next audible grain -
NGS2 reverb rack (libSceNgs2.native, rack 0x2001) - follows the PS4 firmware 11.00
libSceNgs2.sprx, read and checked against its output at 11.025 to 48 kHz, including parameter changes during playback (differences at float rounding level); not yet compared with the PS5 library. Structure layouts come from shadPS4'sngs2_reverb.hand the param ids 0x20010000 (setup) and 0x20010001 (I3DL2) from PPSA22520. Only the defaultreverb_sizeof 1 is handled, with its 14400-sample reflection buffer; other sizes and the library's half-rate mode throw. System sample rates below about 7.5 kHz, where an allpass delay would have no samples, throw. Setup only accepts equal input and output channel counts -
sceHttpParseResponseHeader (libSceHttp) - signature follows SharpProspero; parsing and error codes follow shadPS4's reverse-engineered PS4 library, not confirmed on a PS5 title or hardware. Folded values retain their line breaks and whitespace; an empty first line starts the value scan after its line feed. A consumed byte count above
INT_MAXthrows instead of wrapping. -
sceHttpParseStatusLine (libSceHttp) - behaviour and error codes follow the shadPS4 reimplementation of the PS4 library, not confirmed on a PS5 title; unlike it, no byte past
lineLenis read -
sceHttpUriMerge (libSceHttp) - signature follows SharpProspero; validation, size formula, absolute/relative split and path join follow the disassembly-like body in shadPS4, not confirmed on a PS5 title or hardware. The base URL goes through our
sceHttpUriParse, which removes dot segments from the base path, while the relative part is appended unswept; base query and fragment are dropped. The relative reference is only classified by its scheme and a leading//, and only references with//are validated; as in shadPS4,//host/xis returned unchanged instead of taking the base scheme, a reference with a scheme but no//(mailto:x) is joined onto the base directory, and?qand#fare appended to the base directory instead of the base path. -
sceHttpUriUnescape (libSceHttp) - signature follows SharpProspero; percent decoding, invalid sequences and error codes follow shadPS4, not confirmed on a PS5 title or hardware. Size includes the final NUL; malformed escapes and
+remain unchanged, and decoding runs once. -
sceHttpUriSweepPath (libSceHttp) - behaviour follows the shadPS4 reimplementation of the PS4 library and its tests (including the PS4 SDK example), not confirmed on a PS5 title or hardware. It is not RFC 3986 5.2.4: a path that doesn't start with
/is copied unchanged and a trailing.or..without a slash is kept. Unlike shadPS4, nothing at or pastsrcSize - 1is read, andsrcSize == 1writes only the terminator -
sceHttpSetResponseHeaderMaxSize, sceHttpRedirectCacheFlush, sceHttpsUnloadCert (libSceHttp) - signatures follow shadPS4 (PS4); no PS5 reference has them
-
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 -
sceHttpSetRequestStatusCallback - the three-argument ABI follows shadPS4. Registrations and user data are retained and removed on request deletion; the offline backend never dispatches callbacks. Invalid ids return
0x80431100, an uncited assumption, not a verified console error. Handle hierarchy, inheritance and deleted-handle validation remain incomplete; callback statuses and dispatch timing are unknown. -
sceHttpSetRedirectCallback, sceHttpSetCookieRecvCallback, sceHttpsSetSslVersion, sceHttpsGetSslError (libSceHttp) - signatures follow shadPS4 (PS4), which only logs and returns 0; a null
errNumordetailinsceHttpsGetSslErroris assumed to returnSCE_HTTP_ERROR_INVALID_VALUElikesceHttpGetLastErrno -
sceHttpSetAuthInfoCallback (libSceHttp) - signature and callback type follow shadPS4 (PS4); no PS5 reference has them. The
idis not checked, as in the other libSceHttp setters -
libSceHttp2 cookie boxes (libSceHttp2) -
sceHttp2CreateCookieBoxis taken to take the library context id first, as in the prosper reimplementation; further arguments are unknown and ignored.sceHttp2SetRequestNoContentLengthis assumed to take only the request id. Cookies are never stored, sosceHttp2CookieFlushhas nothing to discard -
sceNpSessionSignalingGetMemoryInfo (libSceNpSessionSignaling) - unknown signature
-
sceNpSessionSignalingGetConnectionStatistics (libSceNpSessionSignaling) - unknown signature
-
sceUserServiceGetAgeLevel (libSceUserService) - on a PS5 (firmware 13.60) the value is the age set in the user's parental restriction (0, 7, 12 and 15 were measured) and
0xFFFFFFFFwithout one; a user who is not logged in returns0x80960009with or without an output. Parental restrictions are not modelled, so the initial user is always reported as unrestricted. PPSA12544 (Unity) only stores the value for its user profile -
sceGameUpdateGetAddcontLatestVersion (libSceGameUpdate) - a null
entitlement_labelthrows: KytyPS5 accepts it, prosper returns0x80412803. Bytes afterfoundare zeroed as in KytyPS5; prosper leaves them untouched -
sceSystemServiceParamGetString (libSceSystemService) - the system name (parameter 6) is the fixed
PS5, not the console's name; other parameters and buffers of 1 to 64 bytes throw -
sceSystemServiceParamGetInt (libSceSystemService) - console language numbers 0 to 29 follow the PS4 SDK enum in OpenOrbis (21 Arabic). 30 (Ukrainian) is not in it and follows PPSA99505 (Jelly5) and PPSA99002 (ProsperoLight), whose numbers agree with the enum. Not confirmed on a console, and neither title starts on
mainyet. WithoutANYPS5_LANGUAGEthe language is English (United States); the date format, time format, time zone, summer time and enter button stay fixed -
sceNgs2ReportRegisterHandler, sceNgs2ReportUnregisterHandler (libSceNgs2.native, NIDs
uBIN24Tv2MI,nPzb7Ly-VjE) are throwing stubs. The signatures (report type, handler, user data, out handle) and (report handle) follow SharpProspero and shadPS4'sngs2_report.h. No report is produced yet, so registering a handler cannot be honoured. PPSA04540 imports both and registers a CPU load handler (type 5) -
sceNgs2SystemSetSampleRate, sceNgs2SystemSetUserData, sceNgs2SystemGetUserData, sceNgs2SystemLock, sceNgs2SystemUnlock (libSceNgs2.native) - shadPS4 only checks the system handle (
INVALID_SYSTEM_HANDLE) and SharpProspero names what each call does; neither gives the other limits. A sample rate of 0 and a null user data pointer throw, any other rate is accepted, and changing the rate while a sampler filter is enabled throws because the filter coefficients were computed for the old rate. Lock and unlock take the same lock assceNgs2RackLock -
sceNgs2RackGetInfo (libSceNgs2.native) - field order from shadPS4's
OrbisNgs2RackInfowith the 64-byte name of the other info structures (216 bytes);typeis assumed to be the rack id divided by 0x1000,min_grain_samples64 (the system minimum) andstate_flags1;uidcomes from a per-process rack counter,render_countis the owning system's render count andactive_voice_countcounts voices that are not empty (paused and stopped voices included). The last process ratio and tick andactive_channel_work_countare left zero -
sceNgs2VoiceQueryInfo (libSceNgs2.native) - only info id 0x4001 is known: PPSA22520 passes an 8-byte buffer and branches on the first word being 1 or 2, so it is assumed to be the voice channel count (0 before the voice is set up); the second word is zeroed and other ids throw
-
sceNgs2VoiceGetPortInfo (libSceNgs2.native) - layout from shadPS4; the delay and destination input are zero because ports have neither yet
-
sceNgs2ParseWaveformFile (libSceNgs2.native) - the signature
(path, offset, info)is taken from the call site of PPSA21402, which sets only three argument registers; the file is read fromoffsetto its end, the data and block offsets are taken to be relative to the start of the file, not ofoffset, and an unreadable file throws. The audio unit fields of a 16-bit PCM waveform are assumed to be one sample frame per unit and per frame;INVALID_WAVEFORM_DATAfor adatachunk that runs past the buffer or ends inside a frame is assumed, and looped PCM and other PCM formats throw -
sceSaveDataDirNameSearch (libSceSaveData.native) - the sort keys (0 directory name, 1 user parameter, 2 blocks, 3 modification time, 5 free blocks) and orders (0 ascending, 1 descending) follow shadPS4, not a hardware run; saves with equal keys keep directory-name order before a descending reverse. Every native save reports
SAVE_DATA_BLOCKS_MAXblocks, assceSaveDataGetMountInfodoes, so the two block keys keep directory-name order. Keys other than 0, 1, 2, 3 and 5 (including 4) and orders above 1 returnSCE_SAVE_DATA_ERROR_PARAMETER; shadPS4 and KytyPS5 only reject keys above 5, so key 4 is rejected here because no source names it -
sceSaveDataInitialize3 (libSceSaveData.native) - a repeated initialize succeeds: PPSA12544's executable and its Unity SaveData plugin both initialize, and the plugin fails on any error. Initializations are counted and
sceSaveDataTerminateends the session at the last one; how the console pairs them is unknown -
sceTextToSpeech2GetSystemStatus (libSceTextToSpeech2) - unknown signature; returns
EOPNOTSUPPlikesceTextToSpeech2Initialize -
sceCoredumpAttachUserMemoryFile (libkernel) - unknown signature
-
sceCoredumpAttachMemoryRegion (libkernel) - unknown signature
-
sceKernelAddTimerEvent (libkernel) -
usecis taken as the period in microseconds; re-adding an existing timer keeps its pending expiration count and restarts the period from the time of the call, where FreeBSD 12+filt_timertouchclears pending expirations onEV_ADD;usec == 0fires on every wait. None of this is confirmed on a PS5 title -
sceKernelWaitEqueue (libkernel) - a level-triggered user event (
sceKernelAddUserEvent) is reported at most once per call, as in FreeBSDkqueue_scan(sys/kern/kern_event.c), which re-queues a reported knote withoutEV_CLEARorEV_DISPATCHbehind the scan marker, and kevent(2), where several triggers do not produce several kevents. Not measured on a console. Events are scanned in list order and the list is not rotated, so whennumis smaller than the number of ready level events the later ones can starve, where FreeBSD moves a reported level knote to the tail. Several completions of one AMPR or VideoOut event within one call are returned as separate entries, where FreeBSD would aggregate them; the Orbis behaviour is unconfirmed -
sceRtcFormatRFC2822, sceRtcFormatRFC2822LocalTime, sceRtcFormatRFC3339LocalTime (libSceRtc) - only shadPS4 (PS4) has bodies. A null tick returns
INVALID_POINTERlike the existingsceRtcFormatRFC3339, where shadPS4 formats the current time instead; offsets outside ±1439 minutes returnINVALID_VALUElikesceRtcFormatRFC3339; the local-time variants use the host's offset at the given instant (shadPS4 usessceKernelGettimezone, the current offset) -
snwprintf_s (libc) - follows C11 K.3.9.1.3 with
RSIZE_MAXassumed to beSIZE_MAX >> 1. A runtime-constraint violation only returns a negative value:set_constraint_handler_sis not exported and the console's default handler is unknown. An invalid multibyte%sargument is copied byte by byte instead of being reported as an encoding error, as invswprintf -
vsnprintf_s and vsscanf_s (libc) -
vsnprintf_sforwards tovsnprintfsemantics: the C11 K.3.7.1.5 runtime constraints (null buffer,size == 0,%n, null%s) are not checked, sosize == 0returns the would-be length instead of a negative value, and no constraint handler is invoked.vsscanf_sreturns the count of items converted before an undersized%s/%c/%[destination (0 when it is the first), not EOF. Neither is confirmed on a PS5 title -
libSceUlt ulthreads -
_sceUltUlthreadRuntimeOptParamInitialize,_sceUltUlthreadRuntimeCreateand_sceUltUlthreadCreateare assumed to take the same arguments as the existing exports without the underscore, including the trailing build version.sceUltUlthreadTryJoinis assumed to returnULT_ERROR_BUSYwhile the ulthread runs, andsceUltUlthreadRuntimeDestroyto returnULT_ERROR_BUSYwhile an ulthread created on the runtime is not joined. Neither error has been confirmed on PS5 hardware -
libSceUlt queues - the added
sceUltQueuePop,sceUltQueueTryPush,sceUltQueueDestroyandsceUltQueueDataResourcePoolDestroysignatures are inferred from the existing push/pop and object APIs. Queue destruction is assumed to reject blocked callers withULT_ERROR_BUSYand otherwise discard queued data; pool exhaustion returnsULT_ERROR_AGAIN. These rules, alignment checks and shared slot limits have not been confirmed on PS5 hardware or a title. Non-null queue and data-pool option parameters throw because their layouts are unknown. -
localeconv (libc, re-exported by libSceAmpr) - the 0x90-byte Dinkumware struct (empty monetary strings,
CHAR_MAXfor the 14charfields,decimal_point".",_False/_True"false"/"true") is read from thelibc.prxthat Astro's Playroom ships. It is a fixed C-locale table: whether the console changes it withsetlocaleis not known, and_Frac_grouping,_Frac_sep,_No,_Yesare empty strings as in that dump -
set_constraint_handler_s (libc, re-exported by libSceAmpr) - the default handler is assumed to abort; each module keeps its own handler state, so a handler set through one library is not seen by the other.
ctime_sandasctime_sfollow the Dinkumware 26-byte format withEINVALfor a buffer under 26 bytes, a null pointer or an out-of-range weekday/month;ctime_suses the guest time zone oflocaltime_s, and the console's exact checks are not verified -
__udivti3 (libc, re-exported by libSceAmpr) - the hardware traps on a zero divisor; this throws instead
-
AC1FtjqMCL0 (libkernel) - unknown name, signature
-
0iEKNAvT600 (libkernel) - unknown name, signature
-
2cELEBPdYQ0 (libkernel) - unknown name, signature
-
5xYxiOtOccA (libkernel) - unknown name, signature
-
6W+shIH315Q (libkernel) - unknown name, signature
-
7ilObq815O4 (libkernel) - unknown name, signature
-
7iq7Hfs8HBk (libkernel) - unknown name, signature
-
AMJZhpC+siY (libkernel) - unknown name, signature
-
E9XkHowt+dY (libkernel) - unknown name, signature
-
GADjreszOgM (libkernel) - unknown name, signature
-
Giyg2xGrXDU (libkernel) - unknown name, signature
-
KC3y21wrqzc (libkernel) - unknown name, signature
-
Qb8wS4GZUsw (libkernel) - unknown name, signature
-
aAQZSjb2fho (libkernel) - unknown name, signature
-
pnz21I6VjDs (libkernel) - unknown name, signature
-
qk043QPsrZU (libkernel) - unknown name, signature
-
uDGXwUKqi8s (libkernel) - unknown name, signature
-
LinuxProtFromSce (libkernel) - protection bits 0x100 and 0x200 are accepted and assumed not to affect host CPU access; host protection is derived only from the read, write and execute bits
-
_sceUlobjmgrRegisterObject (ulobjmgr) - parameters taken from shadPS4 (PS4): a nonzero 64-bit object, a nonzero 32-bit kind and a 32-bit id output; the meaning of the first two and the PS5 signature are unverified. The id bound of
_sceUlobjmgrUnregisterObject(below 0x4000) and the rawEINVAL(22) return also come from shadPS4 -
sceShareGetCurrentStatus (libSceShare) - validation (feature flag non-zero, status non-null) and the all-zero 16-byte status taken from the KytyPS5 reimplementation, not confirmed on a PS5 title; the meaning of the recording status values is unknown
-
sceShareGetRunningStatus (libSceShare) - only the first 32-bit word of the status is known: PPSA01317 treats bits 0x3c of it as a running share feature and gives the call a 40-byte buffer. The host never records or broadcasts, so it stores 0 in that word and leaves the rest untouched; a null status returns
INVALID_PARAMby analogy withsceShareGetCurrentStatus -
sceShareSetContentParamForApplicationTitle (libSceShare) - imported by PPSA12544's Unity plugins; the signature follows KytyPS5, not confirmed on a PS5 title. The application title is only checked for null, as KytyPS5 does, since nothing is captured
-
sceSharePlayInitialize (libSceSharePlay) - the library keeps no state, so the heap is not used. A null heap is accepted: PPSA11386 passes a null heap and 0x1800 bytes and stops on any non-zero result. The error for a zero size is unknown, so it throws
-
sceAgcDcbSetZPassPredicationEnableGetSize, sceAgcDcbSetPredicationDisableGetSize, sceAgcDcbSetBoolPredicationEnableGetSize (libSceAgc) - the builders are inline in the SDK and not exported; the size is assumed to be that of the SET_PREDICATION packet
sceAgcDcbSetPredicationwrites (16 bytes) -
Resource registration (libSceAgcDriver) - registration always fails with
RESOURCE_REGISTRATION_UNAVAILABLE, so the owner and resource queries,sceAgcDriverSetResourceUserData,sceAgcDriverFindResourcesPublicandsceAgcDriverUnregisterAllResourcesForOwnerreturn the same error without reading their arguments. Their parameter lists follow the libSceGnmDriver counterparts and are unverified.sceAgcDriverGetResourceRegistrationMaxNameLengthwrites 0xfc and returns 0, as prosper does from a title's registration configuration; theuint32_t*parameter matches the SDK wrappersce::Agc::ResourceRegistration::getMaxNameLength(unsigned int*). sharpemu writes 256 and KytyPS5 returnsRESOURCE_REGISTRATION_UNAVAILABLE, so the value is unverified; a null output throws -
vieBRwlh1Lw (libSceAgc) follows OpenAGC only, not confirmed on hardware: the
dbOlWdppb4otransform without the identity tail, so it writes one register per pixel shader input and none for a pixel shader without inputs, and a null pixel shader throws. For anis_f161 or 3 input whosedefault_valueanddefault_value_hidiffer it throws: OpenAGC takesDEFAULT_VALfromdefault_value_hi, while KytyPS5, sharpemu anddbOlWdppb4ohere take it fromdefault_value -
sceAgcDriverRegisterMultipleResources uses the existing unavailable-registration state and leaves caller memory untouched. Its four arguments (uint32 handle output, uint32 owner, descriptor pointer, uint32 count) follow the original PPSA34502 / 01.010.000 codzm call. The caller builds 40-byte descriptors and explicitly accepts 0x8A6C9018 with an invalid output handle. Enabled registration and console argument-validation precedence are unverified.
-
Shader registration (libSceAgcDriver) - a shader header is accepted at any address: PPSA26344 passes headers 4 and 1 bytes past an 8-byte boundary; whether the console refuses an alignment is unknown
-
NGG vertex workgroups (libSceAgcDriver) - type-2 PRIMGEN programs using DS instructions or
s_barrierare prepared with the draw's routing and primitive registers on the existing mesh path. The workgroup requirement follows Mesa's NGG lowering; the mesh path supplies LDS and two guest lanes per host invocation for wave64 on a 32-lane host subgroup. Console routing has not been measured. Passthrough and tessellation keep their existing paths; unsupported mesh assembly and subgroup budgets throw. -
Shader header copies (libSceAgcDriver) - a header bound for a draw or dispatch at another address than the registered one is accepted when its fixed fields match the registered header except
user_data; the registered header's metadata is used. PPSA21567 binds such a copy of a vertex shader header withuser_dataset to null. Whether the console reads the copy'suser_datais unknown -
HtileFillCovers (libSceAgcDriver) - a fill is taken to cover a depth surface's whole HTILE when it spans 32 KiB per 1024x512 pixel block from DB_HTILE_DATA_BASE, the pipe-aligned SW_64KB_Z_X metadata extent AMD PAL's gfx10 addrlib gives for GB_ADDR_CONFIG 0x00100044 (1-8 samples, D16/D32); other metadata layouts are not decoded. A partial fill is ignored (the surface keeps its contents); not measured on the console.
-
Depth fast clear through HTILE (libSceAgcDriver) - a surface cleared by an HTILE fill is cleared to DB_DEPTH_CLEAR, also when it is next sampled. For a depth-only HTILE the clear word also carries a value (radv writes
minz = maxz = round(depth * 0x3fff),HTILE_Z_CLEAR_REGin Mesa'ssrc/amd/common/ac_descriptors.h, and allows TC-compatible fast clears only to 0.0 or 1.0); which of the two the texture unit returns for a cleared tile was not measured. -
Depth-only and stencil HTILE fill (libSceAgcDriver) - in a whole-HTILE fill, ZMask (bits 0-3) 0 clears the depth and SMem (bits 8-9) 0 clears the stencil, while SMem 3 leaves the stencil alone (
HtileFillClears); other SMem values are taken to leave it alone too. The bit meanings follow the gfx10 HTILE layout as the code reads it, not a measurement;agc_driver_depth_fast_clear_submitpins them for the paths the Driver takes. -
HTILE address of a depth array slice (libSceAgcDriver) -
decodeDepthadds theDB_DEPTH_VIEWslice offset to the Z and stencil addresses but not tohtileAddress, so every slice of a layered depth target shares slice 0's HTILE address and a fill of slice 0's HTILE marks all slices cleared. Astro's Playroom fills the HTILE of each of its three shadow cascades 0x40000 apart (0x24000 bytes of tiles each) back to back before drawing, so the result is still right there; a title that clears one slice between draws to another would lose depth. The per-slice HTILE stride is not derived yet. -
sceNgs2VoiceControl sampler filter (libSceNgs2.native) - param
0x1000000a, its layout and meaning follow KytyPS5 only: location 1 type 1 is an RBJ low-pass biquad at the system sample rate after resampling, scaled bylevel, a setchannel_maskbit bypasses that channel, type 0 turns the filter off. Other locations and types throw. The voice keeps playing a filter tail after its last block until the history is zero, with outputs below 1e-20 flushed to zero (a KytyPS5 choice); the console's tail length is unknown -
sceNgs2PanInit / sceNgs2PanGetVolumeMatrix (libSceNgs2.native) - follow the PS4 firmware 11.00
libSceNgs2.sprx, read and checked against its output for 2, 4, 5 and 7 speakers into 1, 2, 6 and 8 channels; not yet confirmed on the PS5 library. Speakers are taken in the order L R, L R Ls Rs, L R C Ls Rs or L R C Ls Rs Lb Rb and kept in a fixed circular order, not sorted; without angles the defaults are 90/270, 40/110/250/320, 0/40/110/250/320 and 0/40/110/150/210/250/320 degrees. As in that library, defaults converted to radians keep the wrap-around entry in degrees, so angles past the last speaker pan almost fully to it. Error codes are not known for the PS5, so invalid arguments throw, including a speaker angle equal to the unit angle, on which that library loops forever. Angles so large that adding or subtracting a turn leaves them unchanged throw for the same reason -
sceRtcGetDosTime, sceRtcSetDosTime (libSceRtc) - bit layout from shadPS4 (PS4, the standard FAT date/time). A year outside 1980-2107 makes
GetDosTimereturnINVALID_YEARafter writing 0 for an earlier one and0xff9fbf7d(2107-12-31 23:59:58, the largest encodable time) for a later one, andSetDosTimedecodes the year as the unsigned 7-bit FAT field (1980-2107) without validating the fields, as the disassembly-derived fpPS4 reimplementation of the PS4 library does; not confirmed on a PS5 title, and shadPS4 instead masks out-of-range years into the packed value and sign-extends the 16-bit date -
sce::Json::InitParameter2 (libSceJson2) - layout inferred, not known: assumed to start with the allocator, its user data and the file buffer size, in that order, and the whole struct is assumed to fit in 40 bytes;
Initializer::initialize(InitParameter2)ignores them asinitialize(InitParameter)does -
sceAjmBatchJobSetResampleParameters, sceAjmBatchJobGetResampleInfo (libSceAjm) - the ratio is taken as decoded samples per output sample and num_samples as the decoded samples the resampler holds, both inferred from FMOD (Hades II); the console's interpolation is unknown, a 4-point Catmull-Rom is used. The flags argument is ignored, as in shadPS4 and Kyty
-
scePlayerReviewDialogOpen, scePlayerReviewDialogGetResult (libSceCdlgPlayerReview) - the PS5-only dialog has no public reference: the parameter is not read and the result is assumed to start with the 32-bit common dialog result, as
sceWebBrowserDialogGetResultassumes -
sceHttpWaitRequest (libSceHttp) - the timeout is assumed to be in microseconds and a negative timeout to wait without limit; the invalid-value error for a null handle or event array or a non-positive event count is assumed, not measured. No request is ever pending, so a wait returns 0 events when its timeout passes
-
sceVideoOutAddPreVblankStartEvent (libSceVideoOut) - how long before the vblank the console signals pre-vblank start is unknown. The event is triggered on each emulated vblank tick immediately before the vblank event, with its own count as the event data
-
sched_get_priority_max, sched_get_priority_min (libkernel) -
SCHED_OTHER(2) reports the same 256 to 767 range asSCHED_FIFOandSCHED_RR; the console's answer is unverified. FreeBSD acceptsSCHED_OTHERwith its own range, and shadPS4 rejects it withEINVAL.pthread_setschedparamignores the policy, so a priority taken from this range applies -
inet_pton, inet_ntop (libkernel) - the text forms are assumed to be those of FreeBSD 11.4 and are unverified on a console:
inet_ptonaccepts only four decimal parts without leading zeros forAF_INETand the RFC 4291 forms forAF_INET6(one::standing for at least one group, a dotted-quad tail only as the last 32 bits, no zone id), andinet_ntopprints lowercase hex with the first longest run of two or more zero groups compressed, and a dotted tail only for::a.b.c.dand::ffff:a.b.c.d. They no longer depend on the host resolver library -
gethostbyname (libScePosixForWebKit) - numeric IPv4 forms, trailing whitespace and 64-bit accumulation follow FreeBSD 11.4 inet_aton; clearing the resolver error on numeric success follows fakeaddr. Exact PS5 behavior is unverified; hostname lookup still uses the host resolver
-
sceAppContentGetAddcontDownloadProgress (libSceAppContent) - imported by PPSA08755, which fails to load without it; added without an implementation because its behavior is unverified. SharpProspero lists
(uint32_t serviceLabel, entitlementLabel, SceAppContentAddcontDownloadProgress*), but no PS5 reference gives the progress layout or the error codes -
_sceFiberGetThreadFramePointerAddress (libSceFiber, NID
0dy4JtMUcMQ) forwards tosceFiberGetThreadFramePointerAddress; that the argument list matches is inferred from the export without the underscore, as for the underscore Ult exports, not measured
Functional
-
sceAudioInHqOpen, sceAudioInAsyncOpen (libSceAudioIn) open the same port as
sceAudioInOpen, sosceAudioInInput,sceAudioInGetSilentStateandsceAudioInCloseaccept their handles. The signatures agree across shadPS4, SharpProspero and KytyPS5. HqOpen is limited to 128 samples at 48 kHz; AsyncOpen rejects sizes above 384 and throws for currently unverified inputs. Host capture pacing and console behavior remain unverified. -
sem_timedwait (libkernel) consumes an available count before checking the timeout and waits indefinitely for a null timeout, following FreeBSD 11's
sem_timedwait. Console behavior for null and invalid timeouts when a count is available is unverified. -
getc_unlocked, putc_unlocked (libc) - byte I/O uses the host unlocked operations; guest EOF/error flags and macro counters follow
FileStream. Linux status queries usefeof_unlocked/ferror_unlockedbecause glibcfeofandferrorcan acquire the stream lock. Windows uses the CRT no-lock byte operations andfeof/ferror, verified under a held stream lock on UCRT. Console behavior and other host CRTs remain unverified. -
ftrylockfile (libc) - tries the host CRT stream lock that
flockfile,funlockfileand each locking host stdio call on the stream take, so it returns -1 while another thread holds the stream throughflockfileor is inside such a call, and 0 when it acquires the lock or already owns it (recursively, released by as manyfunlockfilecalls), as FreeBSD 11_ftrylockfiledoes. A libc export holds the lock only for each host call it makes, not across several host calls or while it updates the guestFILEprefix. Linux uses glibcftrylockfile. UCRT has no try variant of_lock_file, so Windows callsTryEnterCriticalSectionon theCRITICAL_SECTIONthat_lock_fileenters, found through the private UCRT stream layout (__crt_stdio_stream_datainucrt/inc/corecrt_internal_stdio.h, unchanged from Windows SDK 10.0.19041 to 10.0.26100); another CRT or a change of that layout breaks it. A null or closed stream throws where FreeBSD dereferences it -
libSceOpusDec uses FFmpeg for 48000 Hz mono/stereo signed-16 decoding. The six signatures, 640-byte opaque state allocation and byte-count return follow public PS5 decoder research and ProsperoRadio. Console PCM equivalence and error codes are unverified. Other sample rates, packet loss concealment, invalid inputs and termination with live decoders throw. Context identifiers and host decoder state are private registries; the firmware's opaque state layout and error recovery are unknown.
-
mkstemp and isatty (libScePosixForWebKit) follow FreeBSD's temporary-file API and terminal check, without console verification.
mkstempreplaces all trailingXcharacters, accepts a fixed name, and creates files through the guest path resolver with exclusive read/write access and mode 0600. Windows file permissions follow the existing kernel file implementation.isattytests Windows console handles rather than all character devices; files, pipes and guest sockets returnENOTTY, closed descriptors returnEBADF. -
arc4random (libScePosixForWebKit) returns four bytes of host OS entropy (
getentropy,rand_son Windows), asarc4random_bufdoes, uniform over the 32-bit range like FreeBSD 11.4's RC4 keystream in arc4random.c. The console's generator and its reseeding are unknown;arc4random_uniform,arc4random_stirandarc4random_addrandomare not in the module's export set and are absent -
fnmatch (libScePosixForWebKit) follows FreeBSD 11 fnmatch.c in the C locale: each byte is one character,
FNM_CASEFOLDfolds ASCII letters only, and bracket ranges compare byte values.[:class:]names are not character classes: as in FreeBSD 11 through 14,[[:digit:]]is the set of[,:,d,i,g,tfollowed by a literal](classes were added tofnmatch.cafter 14). Multibyte characters and locale collation are not modelled. A null pattern or string throws -
Dinkumware thread exports (libSceAmpr) follow the Dinkumware threads library shipped with Visual C++ 2013 (
cthread.c,xtime.c) and itsatomic.c, microsoft/STLcthread.cppand C11 Annex K, without console verification._Thrd_tis taken to be the guestpthread_t, as thestd::_Pad::_Launch(pthread**)export suggests:_Thrd_joinreturns_Thrd_error(4) whenpthread_joinfails and stores the thread's return value truncated toint._Thrd_sleepreads a 16-byte xtime (64-bit seconds and nanoseconds) on the guestCLOCK_REALTIME, normalizes the nanoseconds and sleeps throughnanosleep, so it is a cancellation point; a null xtime or one whose normalization overflows throws. The console's_Thrd_sleep(disassembled from a title'slibc.prx) also takes an optionalxtime*of remaining time and returnsint; here the sleep is never cut short, so it returns 0 and leaves the remaining time untouched._Thrd_join(32-bit store of the result, 0 or 4) and the spin lock (byte exchange loop, no yield) match that disassembly. The shared_ptr spin lock is one process-wide flag that yields while it spins.wcstombs_siswcsrtombs_swith a fresh conversion state, so*retvalexcludes the terminating null as in Annex K, not as in the Microsoft CRT, and_TRUNCATEhas no meaning -
_Cnd_signal, _Cnd_init_with_name (libSceAmpr) - take a pointer to the handle slot like the libc
_Cnd_*exports from #3079 and act on the same conditions._Cnd_signalwakes one waiter and returns_Thrd_success(0), as_Cnd_broadcastdoes; whether the console maps a failing internal signal to_Thrd_erroris not known. The signature_Cnd_init_with_name(_Cnd_t*, const char* name)is inferred from fpPS4ps4_mtx_internal.pas, where the PS4_Mtx_initis_Mtx_init_with_namewith the nameSceLibcI_Mtxand the name only reaches the pthread object; here it is_Cnd_initand the name, which may be null, is ignored. Neither is confirmed on a PS5libc.prx._Thrd_idstill throws: microsoft/STL returns anunsigned intthread id, but whether the PS5 returns thepthread_tor a kernel thread id, and at what width, is not known -
libSceZlib completes RFC1950 decompression during submission and supports one outstanding request, null-timeout waits and one result retrieval. Timed waits, multiple outstanding requests, repeated retrieval and finalization with an unread result throw. The 64-bit initialization length and 64 KiB output limit with 2 KiB destination alignment follow SharpProspero; the PS4 initialization length is 32 bits. shadPS4 also requires the output length to be a multiple of 2 KiB and returns
0x81120016for invalid arguments; this implementation accepts any length up to 64 KiB (SharpProspero documents only the pointer alignment) and throws on invalid arguments. Scratch memory is not used, and its firmware size/alignment requirements are unknown. The initialization errors follow SharpProspero; malformed/checksum/truncated streams report0x811200FFand insufficient output0x8112001Cas in shadPS4. PS5 error precedence, scheduling, completion selection, result consumption and cancellation are unverified. The payload SDK's FreeBSD kernelz_streamand host errno are not this library's ABI. -
Windows file timestamps use the host filesystem's timestamp range and resolution.
utimesandfutimesreject timestamps outside nonnegative signed 64-bit Windows file-time ticks withEINVAL, including exactly 1601-01-01 00:00:00 UTC, whose zero value means "leave unchanged" toSetFileTime. Guest directory descriptors still resolve through their recorded path. Filesystems with coarser timestamp resolution cannot retain every guest microsecond -
fchdir (libkernel_sys) changes the guest working directory to the descriptor's directory: on Windows through the path recorded when the descriptor was opened, on Linux through the
/proc/self/fdlink target. It returnsEBADFfor a descriptor that is not open andENOTDIRfor one that is not a directory. FreeBSDchange_dir's search-permission check (EACCES) is not modelled, and a directory renamed after it was opened is still reached through the recorded path. Console behaviour is unverified -
openat (libkernel_sys) passes
AT_FDCWD(-100) and absolute paths toopen. Any other relative path is joined to the descriptor's host directory, found the same way as forfchdir, so guest path aliases and case-insensitive name matching do not apply to it, and a..component is not kept inside the guest root. It returnsEBADFfor a descriptor that is not open andENOTDIRfor one that is not a directory. As withopen,O_NOFOLLOWandO_NONBLOCKare ignored. PPSA99003 opens directory entries this way. Console behaviour is unverified -
Windows file identity (libkernel) -
statandfstatreport the volume serial number asst_devand the 64-bit file index folded into the guest's 32-bitst_ino(never 0), so two different files can in principle share anst_ino; the fold is not taken from a reference.st_nlinkis clamped to 65535, the width of the guest field. The call keeps the_wstat64values whenGetFileInformationByHandlefails -
On Linux, direct memory lives in one sparse memfd at file offset = physical address, so the GPU imports can share one udmabuf buffer object per 64 MiB of it. Released direct memory is not punched out of the file, because a live import of its chunk pins the pages and the GPU would keep reading the old ones: its pages stay committed (the process keeps the high-water mark of the direct memory it used) and are zeroed when the range is allocated again.
-
Per-face depth bias (libSceAgcDriver): Vulkan has one depth bias per draw, so a draw that rasterizes both faces with different front and back bias (PA_SU_SC_MODE_CNTL, PA_SU_POLY_OFFSET_FRONT/BACK_*) is recorded twice, front faces with the back faces culled and then back faces with the front faces culled. The vertex stages run twice, so a vertex shader that writes memory writes twice, and all front faces land before all back faces instead of in primitive order, which differs only for blending or stencil updates that depend on the order.
-
Partial rect-list primitives (libSceAgcDriver): a rect-list draw whose vertex or index count is not a multiple of 3 draws its complete rectangles and leaves out the 1 or 2 vertices after them, because rect lists are drawn as Vulkan patch lists of 3 control points, which generate ⌊vertexCount/3⌋ patches. What the console draws for the incomplete rectangle is not measured; Palworld (PPSA23126) draws 4 vertices × 9 instances as a rect list when its character creation opens.
-
Separate alpha blend into 8_8 SWAP_ALT targets (libSceAgcDriver): the second channel of a two-channel target with
COMP_SWAP1 holds the alpha export, but Vulkan blends it with the color equation of the R8G8 attachment, so a draw whose alpha equation differs from its color equation is recorded twice, the first channel with the color equation and the second with the alpha factors and operation moved into the color equation. The vertex stages run twice, so a vertex shader that writes memory writes twice, and occlusion counts include both passes. Draws that write depth or stencil, pixel shaders that write memory and factors of the destination alpha throw. That the hardware blends the second channel with the alpha equation is taken from Mesa'ssi_translate_colorswapand radeonsi's use of it for luminance-alpha formats, not measured on hardware. -
Unexported pixel inputs (libSceAgcDriver): a pixel input whose
SPI_PS_INPUT_CNTLparameter the previous stage does not export is programmed as a default-value input (OFFSETbit 5,DEFAULT_VAL0, FP16 high half too) and reads (0, 0, 0, 0), as radeonsi'sSI_PS_INPUT_CNTL_UNUSEDdoes and as rect-list draws already do. The console's value for an unwritten parameter cache entry is not measured on hardware. -
Compute LDS beyond the device's shared-memory limit (libSceAgcDriver) lives in a coherent storage buffer with one slice of
LDS bytes / 4 + 1dwords per workgroup (the last dword is the atomic lock), shared by all such dispatches and grown in 1 MiB steps up tomaxStorageBufferRange; a dispatch whose slices do not fit throws. It is slower than shared memory and its cost was not measured. An indirect dispatch of such a program always reads its group counts on the CPU. Its results are pinned against the in-limit semantics inagc_driver_lds_beyond_device_limit, not measured on hardware. -
AGC buffer allocations retry host/device out-of-memory once after reclaiming idle pool buffers and fully unused slab blocks. Live buffers and blocks with live slots are retained. Live images and other retained resources have no global memory bound; allocation failure still throws when reclaim cannot satisfy the request.
-
Graphics pipeline libraries (libSceAgcDriver): a pipeline is fast-linked at the draw and relinked with
VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXTon a background thread, and binds the optimized one from the next draw on. Draws recorded before that use the fast link, whose vertex stage keeps the outputs the fragment stage does not read: on RADV (Radeon 660M, Mesa 26.2.4) 346 of 483 Astro's Playroom vertex shaders paired with a fragment stage that reads none of them used more VGPRs (median 8 more, up to 2.5 times), and on an RTX 4090 13 of 15 PPSA36082 vertex shaders up to 68 instead of 38 (#2242). The optimized link compiles to the same code as a whole pipeline -
sceAvPlayerGetVideoData (libSceAvPlayer) in sync mode
SCE_AVPLAYER_AV_SYNC_MODE_NONEskips queued frames that the audio clock has already passed while the title pulls audio, so a title that requests video slower than the film's frame rate keeps the picture with the sound. Whether the console hands out every frame in this mode is unknown. PPSA12544 requests 7-19 frames per second for a 30 fps cinematic -
APS5_THREAD_PRIORITY=rt(libSceAgcDriver) lowers the process's hardRLIMIT_RTTIMEwhen it is aboveAPS5_THREAD_RTTIME_USor rtkit'sRTTimeUSecMax, because rtkit (verify_process_rttime) reads the hard limit from/proc/<pid>/limitsand refuses real-time scheduling when it is higher. An unprivileged process cannot raise the hard limit again, so it stays lowered for the process and its threads even when rtkit then refuses the request (burst limit, user or start-time checks) and the thread throws. rtkit'sMaxRealtimePriorityandRTTimeUSecMaxare read first, so an unreachable rtkit or a priority above its maximum leaves the limit untouched. The lowered limit only matters for threads that later run under a real-time policy -
On a device without VK_EXT_robustness2's
nullDescriptor, such as MoltenVK, a null image descriptor in a typed heap is a placeholder image of that heap's type, 1×1 and cleared to zero, which every null descriptor of the heap shares. Reads give zeros, asnullDescriptorallows, but stores and atomics to it are kept, so a later read of a null storage image can return them, and a depth comparison compares against depth 0. A heap whose placeholder the device cannot create, for example 1D or 3D depth, 64-bit atomics without 64-bit image atomics, or multisampled storage withoutshaderStorageImageMultisample, throws when a null descriptor reaches it. -
libSceHttp2 asynchronous requests (libSceHttp2) never reach the network:
sceHttp2SendRequestAsyncaccepts the request, queues a completion whose result is the library's network error and triggers the user event named by the kqueue option (equeue at offset 0, event id at 8, user data at 16, layout inferred from PPSA17221);sceHttp2WaitAsyncreturns that completion. The completion'sevent_typevalue is unknown and left 0. PPSA17221 completes its request object only aftersceHttp2SendRequestAsyncreturns, and its handler for a synchronous failure callsshared_from_thisbefore that, so a send must not fail synchronously. A kqueue option or user event that is missing, an extra option, and a wait with no completed operation throw -
sceHttpAbortWaitRequest, sceHttpWaitRequest (libSceHttp) - the abort takes only the epoll handle, as in Orbital and SharpProspero; behaviour and error codes follow shadPS4 (PS4), not confirmed on a PS5 title or hardware. An abort stays set: every later wait on the handle, a poll included, returns
SCE_HTTP_ERROR_ABORTED(0x80431080) until the handle is destroyed. A wait woken bysceHttpDestroyEpoll, or by thesceHttpTermthat ends the last context, returns 0 events. The epoll calls returnBEFORE_INIT(0x80431001) while nosceHttpInitcontext is alive andINVALID_ID(0x80431100) for an unknown context or handle, andsceHttpTermreturns the same errors instead of succeeding for any id. Handles are pointers, so a stale handle whose address a newer epoll reuses is taken as that epoll -
system (libkernel) runs no command. It follows FreeBSD 11's
lib/libc/stdlib/system.cfor a sandbox without/bin/sh: a null command returns 1 unconditionally, as that version does, and any command returns the wait status of a child that could not exec the shell and called_exit(127)(0x7f00). Whether the console's application sandbox has no shell, and whethervforksucceeds there (FreeBSD returns -1 when it fails), is unverified -
sceKernelWriteThrottlingStatus (libkernel) reports no write throttling: the host SSD has no write budget, so the first qword of the 32-byte status is set to
UINT32_MAXand the rest is zeroed. PPSA17221 reads only that qword: it multiplies it by 64 KiB and compares the product with byte thresholds up to 0x4AF00000 to pick one of five tiers. When the call fails the title assumes 0x4B000001 bytes, which selects the same top tier asUINT32_MAX. What the value measures on hardware (a remaining budget or a rate) and the meaning of the other three qwords are unknown -
Windows directory descriptors (libkernel) take one snapshot of the directory, on the first
getdents,getdirentriesor non-zerolseek(SEEK_SETorSEEK_CUR), and keep it until it is discarded;lseekto offset 0 only discards the snapshot, and the next read lists the directory again, so every rewind costs O(entries) on the next read.lseektakes the offset as an entry index andSEEK_CURwith offset 0 only reports the index.SEEK_ENDthrows, where the NUL descriptor used to return 0, because FreeBSD defines it relative to the directory size, which is not modelled. A negative result returnsEINVALand aSEEK_CURoffset that overflows returnsEOVERFLOW, as FreeBSDvn_seekreports them.getdirentriesstill reports 0 throughbasepinstead of the position of the block it read, so only 0 and values returned bylseekare valid offsets; FreeBSD offsets are filesystem cookies -
/dev/random and /dev/urandom (libkernel) opened for reading return a descriptor backed by the host null device whose reads are filled with host OS entropy (
getentropy,rand_son Windows); both paths behave the same, never block, and positioned reads ignore the offset (FreeBSDrandom(4)). Only the exact paths are recognised, aduped descriptor reads as an empty file,fstat,lseek,mmapandselectsee the null device, and opening them for writing throws -
Wide-character conversions (libc) - The wide
wcsto*functions parse the ASCII prefix of the guest string, as the C locale accepts only ASCII white space and digits.wcsrtombsuses the guest's single-byte C locale throughwcrtomb; other encodings and shift states are not supported -
realpath (libc) follows FreeBSD 11's
realpath.cexcept for symlinks. The console's guest filesystem has none, so a host symlink under the guest root is followed for existence and type but not expanded, and..drops the previous component lexically, asResolvedoes for every guest path. Through a host linklinkdir -> sub/deep,linkdir/../xgivesxbeside the link, not beside its target. -
nan and nanf (libc) return fixed quiet NaN values (
0x7fc00000and0x7ff8000000000000), ignoring the tag argument as observed in the console'slibc.prx(both exports load a global constant viamov rax,[rip+..]; vmovsd xmm0,[rax]; ret); VLC (PPSA85300) stops on nanf at start-up after strsep. -
Draw input snapshots (libSceAgcDriver):
PrepareDrawBindingscaps read-only input buffer snapshots at 64 MiB (overridable viaAPS5_DRAW_SNAPSHOT_MAX_MIB). Larger inputs (streaming heaps, bindless pools) or draws exceeding the cumulative budget skip the per-draw snapshot and bind in place, avoiding multi-gigabyte CPU copy stalls (such as Ratchet & Clank: Rift Apart PPSA01474 stalling at frame ~380 copying 36 GB every 5 s). If the title rewrites those large ranges on the CPU before GPU completion, the in-place binding observes the modification, as verified bydrawSnapshotCapTests. -
pthread_attr_getinheritsched, pthread_attr_setinheritsched, pthread_attr_getscope, pthread_attr_setscope, pthread_attr_getstackaddr (libkernel) follow FreeBSD 11 libthr (thr_attr.c, thr_create.c), not measured on the console: the scope defaults to
PTHREAD_SCOPE_SYSTEM(2), only it andPTHREAD_SCOPE_PROCESS(0) are accepted and other values returnEINVAL, and an inherit value other thanPTHREAD_INHERIT_SCHED(4) orPTHREAD_EXPLICIT_SCHED(0) returnsENOTSUP.pthread_attr_getstackaddrreturns the configured stack address pointer (null by default). A null output ofpthread_attr_getinheritschedthrows, since libthr writes through it unchecked. A thread keeps the scope it was created with, taken from the creating thread underPTHREAD_INHERIT_SCHED, andpthread_attr_get_npandscePthreadAttrGetreport it, but every guest thread is a host thread at system scope, so process scope changes nothing -
SPIRV-Tools optimization skips CCP and Simplification for modules with storage-only 8- or 16-bit types because the pinned folder produces illegal narrow constants. This also disables unrelated constant folding; the restricted full pipeline mirrors the pinned performance recipe.
-
SRT signed comparison evaluates
SLessThan32as signed 32-bit less-than, matching the existing SPIR-V backend and SPIR-VOpSLessThan. Signed boundary descriptor expressions are tested on the host; native RDNA2/PS5 execution and title behavior remain unverified. -
On macOS the write watch write-protects watched pages and records the first write to each from a SIGBUS/SIGSEGV handler, because macOS has no counterpart to
userfaultfdwrite-protect orMEM_WRITE_WATCH. The protection is real, so:- a system call that writes into a protected page fails with
EFAULTinstead of faulting.GuestArena::HostWritelifts the protection for the calls it brackets (the file reads); a host call that writes guest memory without it (sockets,clock_gettimeand the like into a watched page) fails; - code that changes the protection of watched pages, or maps over them, has to call
GuestWriteWatchProtectionChanged, and code that asks the kernel for a page's protection has to askGuestWriteWatchProtectionfirst, since a watched page is read-only between a collection and the next write. Nothing calls either yet: the macOS memory paths are not in the tree; - the handler is installed when libc loads and passes other faults to the handler installed before it. A handler installed later has to do the same.
- a system call that writes into a protected page fails with
-
Pending storage-image results (libSceAgcDriver) are stored when something reads their memory, not when the GPU work that wrote them completes. A title that waits for that work, frees the image and reuses its memory can have the new data overwritten by the late store (#1970).
APS5_STORE_AT_FLIP=1stores every pending result at each flip; storing them at the title's GPU waits (labels, fences) is unimplemented. -
Windows host-pointer imports of the guest mapping itself are compared instead of write-watched: a driver can mark imported pages dirty after the synchronous import window. Shared memory imported through a separate writable alias retains protection-based tracking on the guest views; driver access to the import alias does not disarm those views. GuestMemory excludes every overlapping 64 KiB tracker block while its backing is retained. A full block replaced by fresh private backing regains tracking and gets a new generation; protection changes, partial replacements and shared remappings do not restore it. This preserves CPU edits through byte comparisons but disables snapshot reuse and unit shadows for excluded blocks; restoring tracking on import retirement without replacing the backing and measuring the comparison cost remain unimplemented.
-
Storage-image units under a Linux import window (libSceAgcDriver) that the window stamped as a possible CPU store (
BlockMaybeWritten) are compared with the bytes the image was uploaded from or written back as, and are unchanged when those still match. A CPU store of the bytes already there within the window cannot be told apart from an import that resolves the write protection without storing, as the NVIDIA driver (610.57.04) does for every imported page, so such a store does not win over pending results. Images tracked by layer instead of by 64 KiB unit still read the window as a change and upload again. -
Shared memory (libkernel) on Linux implements anonymous and named objects, bounded descriptor writes and seeks, and
shm_unlinkwith effective read/write permission checks from FreeBSD 11. Named paths up to 1023 bytes use/anyps5-shm-plus SHA-1; collisions are not detected, and the namespace is shared across processes in the host mount namespace. Named creation applies the guest umask without changing the host mask. Linux procfs and/dev/shmare required. Operations use an advisory directory lock; external host operations bypass it, unrelated objects serialize, and descriptor operations require two spare host descriptors and compare device/inode with the initial descriptor identity on both the pinned-object and ordinary-file fallback paths. Guest mappings support shared and private mappings of these descriptors through the allocation tracker and pin a duplicate descriptor during validation and mapping; mapping requires one spare host descriptor; file-backed mappings use the write-watch scan fallback because aliases and descriptor writes bypass per-mapping tracking. Named objects and file-backed mappings on Windows remain unsupported. Invalid non-null name pointers, console behaviour and title compatibility remain unverified. -
sceKernelAddReadEvent and sceKernelAddWriteEvent (libkernel): a write event reports the socket's send buffer size (
SO_SNDBUF) indata, not the free space left in it, as Windows has no query for that space. Only guest sockets are supported; other descriptors and a low watermark above 1 throw -
sceNetSendmsg and sceNetRecvmsg (libSceNet) copy the scatter/gather list through one host buffer and accept only the flags
sceNetSend/sceNetRecvaccept. Sending control data throws; a receive never returns control data (msg_controllen0), since no socket option that queues it is supported -
Additional content (libSceAppContent) is not installed or mounted:
sceAppContentAddcontMountanswersNOT_FOUNDfor every entitlement label andsceAppContentAddcontUnmountfor every mount point, as no add-content mount is ever handed out;sceAppContentGetAddcontInfoanswersDRM_NO_ENTITLEMENTfor every label andsceAppContentGetAddcontInfoListreports 0 entries -
Content export sessions (libSceContentExport):
sceContentExportStarthands out positive session ids, at most 10 live, whichsceContentExportFinishcloses. The signatures follow Orbital and the limitMaxExecutionSharpProspero; the parameter layouts follow shadPS4. The host has no media library, sosceContentExportFromDataWithThumbnailthrows once the session is checked, before calling either data callback, and no export ever runs.sceContentExportGetProgressandsceContentExportCancelthrow for a live session, as their result with no running export is unknown. An eleventhsceContentExportStartandsceContentExportTermwith live sessions throw: whether the console answersEXECUTION_MAXorBUSYthere, or ends the sessions, is unverified. Session id values and error precedence are unverified -
Runtime-loaded modules (
--module-dir) that another module needs are initialized at startup with no start arguments, before the module that needs them is loaded; the console is assumed to start them when that module is loaded. -
sceKernelPread, sceKernelPwrite, sceKernelPreadv, sceKernelPwritev (libkernel) on Windows transfer at the given offset with an overlapped
ReadFile/WriteFileand restore the descriptor's file pointer afterwards, so a concurrentread/writeon the same descriptor can see the moved pointer in between, unlike on the console. Handles that are not disk files returnESPIPE.readvon a pipe or console handle stops after the first iovec read, a short read the console is assumed to allow; each iovec is transferred separately, so a failure after the first transfer returns the bytes already done -
sceKernelAioSubmitReadCommands, sceKernelAioSubmitWriteCommands and their Multiple variants (libkernel) on Windows transfer through the same positioned path as
sceKernelPread/sceKernelPwriteand restore the descriptor's file pointer afterwards, so a concurrentread/writeon the same descriptor can see the moved pointer in between, unlike on the console -
sceKernelAioSetParam (libkernel) writes the five values into the 20-byte scheduling struct the first argument points to, following the declarations in Orbital, SharpProspero and ampr_emu. Whether the console checks the values is unknown, so a null struct, a scheduling window or delayed count limit outside 0..128, a split flag other than 0 or 1 and a split size or chunk size above 0x1000000 (SharpProspero's maximums) throw. The scheduling settings are not used:
sceKernelAioInitializeImplignores the struct and requests run synchronously on submit -
sceKernelGetFsSandboxRandomWord (libkernel) returns a fixed directory name,
gkbHtXc3Wq. On the console the name is the process's randomized path (syscall 602,randomized_path), and the sandbox exposes system files under it, such ascommon/libandcommon/cert. Nothing is mounted under the name here, so/gkbHtXc3Wq/common/...resolves under the guest root like any other path and does not exist -
sceKernelSync (libkernel) flushes only the host files and directories recorded through
RecordWrittenPath_nid_no_patch(the libc, libkernel, save data and app content file functions) and their changed parent directories. A host write in a library that does not record its path is not flushed bysceKernelSync -
sceKernelSync (libkernel) on Windows skips a recorded file it cannot open for writing (read-only, or held open by a handle that denies write sharing), since
FlushFileBuffersneeds a writable handle. On Linux, it skips a recorded file it cannot open for reading. Such a file's data may not reach the disk before a host crash; the guest reads the same data either way -
getcontext and setcontext (libkernel) and makecontext (libSceLibcInternal) use FreeBSD 11's amd64
ucontext_t(mcontextat 0x10,mc_len800,uc_linkat 0x330,uc_stackat 0x338, 0x370 bytes), the layout homebrew built against FreeBSD's headers passes: PPSA99039's OpenSSLASYNC(crypto/async/arch/async_posix.c) captures into a 0x370-byte stack buffer.getcontextwrites the 0x330 bytes beforeuc_link, as FreeBSD'sUC_COPY_SIZE. The console's own layout for these functions is not verified; the exception handler's context is a different one (seesceKernelRaiseException) -
makecontext (libSceLibcInternal) follows FreeBSD 11's
lib/libc/amd64/gen/makecontext.c: at most six arguments, a stack of at leastMINSIGSTKSZ(2048) bytes, andexit(0)when the function returns with nouc_link. The console's version is not verified -
getcontext and setcontext (libkernel) keep the 512-byte FXSAVE image in
mc_fpstate(x87, MXCSR, XMM0-15), so the upper halves of YMM0-15 are neither saved nor restored, andgetcontextleavesmc_xfpustateandmc_xfpustate_len0.getcontextsetsmc_fpformatandmc_ownedfpto FreeBSD's_MC_FPFMT_XMMand_MC_FPOWNED_FPU,mc_csandmc_ssto the host selectors, andmc_flags,mc_fsbaseandmc_gsbaseto 0.setcontextloadsmc_fpstatewhatevermc_fpformatandmc_ownedfpsay, and restores neither the segment selectors,mc_fsbaseandmc_gsbasenor the extended state, which FreeBSD restores whenmc_flagsasks for them -
makecontext (libSceLibcInternal) on Windows pins its stack writable until a later
makecontextstack overlaps it, since nothing tells the library when the guest frees the stack -
setcontext (libkernel) and longjmp (libc) on Windows set the thread's stack bounds in the TEB to the stack they switch to: a
makecontextstack, or else the committed region around the target stack pointer. A switch to any other guest stack, such as a context built by hand, gets the bounds of that region only -
sceKernelInstallExceptionHandler records the handler, but a host fault still ends the process: only signals raised with
sceKernelRaiseExceptionare delivered. Unity's PS5Util module installs a SIGUSR1 handler that readsuc_mcontext.mc_rsp(offset 0xf8 of the context) and raises SIGUSR1 on other threads to stop them for garbage collection -
The Windows libc exception unwinder reads the project's
.ehmetaand.ehframtables, not PE.pdata/.xdata. WinLibs GCC 15.2'slibstdc++-6.dllandlibwinpthread-1.dllhave empty.eh_framesections, so guest exceptions cannot currently cross their frames (for example, thestd::call_oncepath throughpthread_once);RtlVirtualUnwindstepping and Windows cleanup handlers are not implemented -
sceKernelRaiseException on Linux sends the host SIGUSR1, which the library takes over, to the target thread, so the handler runs wherever the thread was interrupted, emulator code included. On the console kernel objects are system calls and libthr defers signals while a thread holds its internal locks; here a handler that needs a host lock the interrupted code holds deadlocks, and a thread that the handler keeps waiting keeps its host locks. Host waits resume after the handler. The host calls Linux does not restart end early: sleeps that do not retry return before their time, and the poll of
sceNetEpollWaitand socket calls with a send or receive timeout returnEINTRto the guest -
sceKernelRaiseException builds the handler's
ucontextwith FreeBSD's amd64 layout (16-byte sigmask,mcontextat 0x40,mc_rspat 0xf8); the console's layout is not verified beyond the fields PS5Util reads -
sceKernelRaiseException does not consult the target thread's signal mask
-
pthread_sigmask (libkernel) shares the process-wide mask of
sigprocmaskand_sigprocmask, which keeps only the first 32 signals; FreeBSD keeps a mask per thread -
sceKernelRaiseException reaches a thread that waits in an alertable
TimedWaitwait through an APC. A thread blocked anywhere else, including all waits underAPS5_COARSE_TIMED_WAITSand host waits inside the emulator, is redirected and runs the handler only when that wait returns -
sceKernelRaiseException on Windows runs the handler wherever the target thread was interrupted. It waits only while the thread is inside winpthreads or restoring a context through
NtContinue, and throws if that lasts 1 s, so a handler that calls into other host code the thread was interrupted in, such as the C runtime's heap or a lock of the emulator, can deadlock on it or reenter it -
sceAgcDebugRaiseException (libSceAgc) - logs the exception id and returns 0, as retail hardware does nothing per OpenAGC; the trap (
ud2) OpenAGC describes for development hardware is not reproduced. Neither is verified on a console. Theuint32exception id is KytyPS5's claim; OpenAGC declares no arguments, so the logged id may be leftover register contents -
sigaltstack (libkernel) records each thread's alternate signal stack and reports it back, following FreeBSD's
kern_sigaltstack(EINVALfor flags other thanSS_DISABLE,ENOMEMbelowMINSIGSTKSZ2048), but handlers never run on it, soSS_ONSTACKandEPERMare never reported -
libSceUlt queues use preallocated host storage instead of the supplied guest work area; its existing size formula and the 512-byte object layouts remain unverified. Waiting-queue pool thread limits and waiter priority ordering are not implemented. Finalization wakes blocked queue callers with
ULT_ERROR_STATE. -
Thread cancellation (libkernel) follows FreeBSD libthr (states and types 0/1 and 0/2,
PTHREAD_CANCELED1, the_pthread_cleanup_infonode layout), not measured on the console. A request is acted on only inscePthreadTestcancel, the condition variable,semandscePthreadSemwaits,scePthreadJoinand the sleeps, and their POSIX names; file and socket calls are not cancellation points. A sleep is not interrupted: the thread exits when it ends. The asynchronous type acts like the deferred one, except at the two set calls. -
cpuset_setaffinity (libkernel) - only the calling thread or the calling process is handled. Bits outside
sceKernelGetAvailableCpumaskare dropped, and a mask with none of those bits fails withEDEADLK, as FreeBSD does when the new set has no CPU in common with the parent set -
cpuset_getaffinity (libkernel) - only the calling thread or the calling process is handled. For the process the mask is the union of the affinities of the live guest threads, as FreeBSD 11.4 ORs the mask of every thread in the process; threads the guest did not create through libkernel are not included, and the console result is unverified
-
dup and dup2 (libkernel) throw for the combinations they do not model:
dup2between a guest socket and a host descriptor in either direction, and on Windows duplicating a directory descriptor. Guest sockets share one socket object between the duplicates and the descriptor numbers come from the guest socket counter, not the lowest free number as in FreeBSDkern_dup. The errno values for descriptor exhaustion are not verified against the console. -
Cancellation coverage checks deferred request handling and recovery, not full asynchronous support or console ABI compatibility. Cancellation during file/socket I/O, sleep interruption, cancellation versus exit/detach, condition signal conservation under cancellation, and safe rejection of non-null invalid or reclaimed thread handles remain unverified. No console title or homebrew establishes the cleanup NIDs or buffer layout. Accepted asynchronous mode currently has no diagnostic for its deferred behavior.
-
MIMG
tfeandlwenever write the status VGPR after the data. On hardware it is written only when a texel fetch hits an unmapped page of a partially resident texture, or, forlweon sample/gather, when the LOD is below the T#MIN_LOD_WARN; texture memory is always resident here, the LOD warning (texture-streaming feedback, like the T#MIN_LOD_WARNitself) is never reported, andlweonimage_get_lodthrows. -
Packed horizontal gathers (
image_gather4h_pck, MIMG opcode 98): the four window texels are read raw and concatenated into a little-endian bitstream, with DMASK bit i writing stream word i to the next destination register; measured on RDNA2 (gfx1031) at every edge: the anchor is floor(x-0.5) with elements at -1, 0, +1 and +2 clamped horizontally into the width, the row is floor(y), negative rows clamp to row 0, rows at or past the height return zeros, sampler addressing modes do not affect the window, and formats wider than 32 bits per texel write zeros in every register. The emitter fetches each window texel at LOD 0 and packs its bits likeimage_load_pck, so the sampler's filter, addressing and LOD state are not used; formats whose bits are not recoverable from the view and D16 data throw. The anchor and row multiply the normalized coordinate by the image size without contraction. The stream rule was measured for R8_UNORM, RG8_UNORM and RGBA8; only RGBA8 has an execution test.image_gather8h_pck(opcode 99) never returns texel data on this hardware - across dmasks 0x1 to 0xFF including the upper nibble, RGBA8, RGBA16 and RGBA32 formats, 1D, 2D and 3D descriptors and normalized and unnormalized sampling it only zero-fills popcount(dmask) registers (sentinel-prefilled destinations) - so it decodes but throws at translation; its eight-texel semantics remain unmeasured. -
waitpid (libkernel) returns -1 with
ECHILD(EINVALfor unknown options): nothing here creates a child process; child processes would need a realwaitpid. -
execv (libkernel) throws: replacing the process image is not supported, the same as
execvp. PPSA97358 imports it and fails to load without it. -
kern.proc.pathname (libkernel) returns
/app0/eboot.binfor pid -1 and the calling process, following FreeBSD'ssysctl_kern_proc_pathname; the exact pathname on retail consoles remains unverified. -
machdep.cacheline_size (libkernel) returns -1 with
ENOENT, matching FreeBSD amd64 where this sysctl OID is not defined. -
execvp (libkernel) throws: replacing the process image is not supported. PPSA85300 imports it and fails to load without it; its
forkandvforkfail withENOSYS(libc_missing.c), so the child process that would call it is never created. -
fork (libkernel_sys) throws: creating a child process is not supported. PPSA19111 imports it and fails to load without it. Its engine calls
forkinPosix_Daemonize, only with-daemonize, and inPlatform_ShellExecutebeforeexecvp("xdg-open"), which the main menu's Previews button reaches, so pressing Previews ends in this throw. setsid fails withEPERM, as FreeBSD's does for a process group leader, since the guest is taken to lead its own process group (seekill). umask keeps the guest's mask (initially 022, masked to 07777) and returns the previous one, Linux named shared-memory creation applies it, but ordinary files are still created with the host process's mask -
MIMG BY2/BY4 loads (
image_load[_mip]_by2/by4, opcodes 0x42, 0x43, 0x4a and 0x4b) were measured on RDNA2 (gfx1035) with the hardware oracle for 2D images with identity swizzle. They read N texels (BY2: 2, BY4: 4) fromx & ~(N - 1)on row y, texel by texel and component by component within each texel, with each texel converted likeimage_load. Every register is zero when the mip level is past the last level,x + N - 1is outside the level's width (unaligned x, unsigned), or y is outside its height. Data only comes back when the N texels fit in one dword: R8 and R16 (DMASK 0x3) or RG8 (0xf) for BY2, and R8 (0xf) for BY4. With 32-bit texels (R32, RG32, RG16, RGBA8) the hardware returns zeros. Other formats, masks, dimensions, swizzles, D16/A16 and indirect descriptors throw. The stores (0x52, 0x53, 0x5a and 0x5b) decode but throw at translation. Measured on hardware, they write from the unaligned x up to the end of its dword, which is not implemented. -
2D stores to 1D storage images: an
image_storewith DIM 2D through a 1D T# writes texel x and ignores y, as measured on RDNA2 (gfx1035) for y from 0 to 4 and 0xffffffff, single- and four-component formats and a 1x1 8_8_8_8_UNORM T#: the T# type decides the addressing, DIM only how many address VGPRs are read. Storage loads, atomics andimage_store_mipthrough such a pair still throw -
MIMG PCK2/PCK4 loads (
image_load[_mip]_pck2/pck4, opcodes 0x70, 0x71, 0x73 and 0x74) were measured on RDNA2 (gfx1035) with the hardware oracle for 2D images with identity swizzle. With data mask 0x1, they write one dword: the raw bits of the N texels (PCK2: 2, PCK4: 4) fromx & ~(N - 1)on row y, concatenated (element k at bitk * texel bits) and zero-extended. The dword is zero when the mip level is past the last level,x + N - 1is outside the level's width (unaligned x, unsigned), or y is outside its height. Data only comes back when N texels fit in 32 bits: R8, R16 or RG8 for PCK2, R8 for PCK4. Wider texels (R32, RG16, RGBA8) and masks other than 0x1 write zeros on hardware. Those masks throw at decode, and formats outside UNORM/UINT/SINT R8, R16 and RG8 throw. #1314's earlier measurement saw only zeros because it used masks 0x3 and 0xf. The stores (0x76, 0x77, 0x79 and 0x7a) decode but throw at translation. They are not measured, and opcode 0x76 on 32_32_32_32_FLOAT hung the GPU (#1314). -
3D image accesses bound to a 2D or 2D-array T# follow CouchRiv's hardware oracle measurement on RDNA2 (gfx1036, #2023) and adriadam10's (gfx1035, #2140), not the PS5's gfx1013. On a 2D T#,
image_sample_lzignores r and reads the (u,v) texel,image_loadandimage_load_mipread the (x,y) texel when z is 0 and return zero otherwise, andimage_get_resinforeturns (width, height, 1, levels). On a 2D-array T#, these accesses behave like dim 2D-array: r or z is the layer, andimage_get_resinforeturns the layer count as its third component. Every other access of such an image, including samples with an LOD, bias, derivatives, offset or comparison, gathers,image_get_lodand stores, keeps throwing because it is not measured. -
Unnormalized S# coordinates (libSceAgcDriver) -
FORCE_UNNORMALIZEDuses a VulkanunnormalizedCoordinatessampler, so the S# LOD range, LOD bias and mip filter are not applied, which is exact only on a one-level view. -
Unnormalized S#s are accepted only when direct and used only by explicit-LOD
image_samplewithout comparison, derivatives or_a, on a single-level, single-layer 1D or 2D view of mip 0, even when the image is also sampled through a normalized S#. -
An unnormalized S# (libSceAgcDriver) throws with unequal minification and magnification filters, anisotropy,
TRUNC_COORD,MC_COORD_TRUNCor X/Y clamping other than last-texel or border. -
Unnormalized texel offsets are added to the f32 coordinates: exact on RDNA2 (gfx1035), which applies the offset before the clamp (measured by adriadam10).
-
Image atomics on 32_SINT and 32_FLOAT surfaces act on the raw dword through an R32_UINT storage view; their float results are assumed to match those measured on 32_UINT surfaces. Other formats throw.
-
s_memtimeon RADV with a GFX10.3 to GFX11.7 GPU (RDNA 2, RDNA 3, RDNA 3.5) reads the Vulkan device clock instead of the subgroup clock, which ACO reads from the 20-bitSHADER_CYCLESregister there and which wraps every 2^20 cycles. The device clock is a monotonic 64-bit counter, but it counts the 100 MHz reference clock (the same one ass_memrealtime), not shader cycles, sos_memtimedeltas are about 20 times smaller than on hardware. The families are matched by the name RADV reports (NarrowSubgroupClock); a family added to Mesa later reads the subgroup clock until it is listed. AMD's proprietary Windows driver also exposes a 20-bit subgroup clock on device 0x1114 (Radeon 860M, measured in #1615), device 0x744c (Radeon RX 7900 XT, measured in #1632), and device 0x747e (Radeon RX 7800 XT, measured in #1632); other AMD proprietary devices remain unverified. -
Background link-time-optimized relink of library pipelines (libSceAgcDriver) is skipped on every GPU under NVIDIA's proprietary Vulkan driver (
VK_DRIVER_ID_NVIDIA_PROPRIETARY), so those pipelines keep their fast-linked form. The optimized link loses the device when bound on an RTX 3080 (Ampere, #2866) and an RTX 4060 (Ada, #3434); an RTX 5060 and an RTX 5080 (Blackwell) on the same driver do not, so the scope is wider than the evidence. No standard Vulkan query tells the architecture apart, and the driver version that fixes it is unknown.APS5_NO_PIPELINE_LTOdisables the relink on every driver. -
s_memtimeands_memrealtimeon llvmpipe read only the low 32 bits of the host's nanosecond clock at either scope: Mesa'semit_clockbuilds the high dword with a left shift by 32, so it is always 0 and both counters wrap every 2^32 ns (about 4.3 s). The shader clock test compares them modulo 2^32 there -
ds_wrxchg2_rtn_b32,ds_wrxchg2st64_rtn_b32,ds_wrxchg2_rtn_b64andds_wrxchg2st64_rtn_b64are translated as two separate 32-bit or 64-bit atomic swaps per invocation. RDNA2 hardware (measured on gfx1035) performs every lane's first exchange before any lane's second one, so when lanes of the same wave or of different waves overlap addresses, the result can differ from hardware.offset0 == offset1throws, although on hardware it is two exchanges in order. -
ds_condxchg32_rtn_b64uses two 32-bit atomic conditional exchanges. RDNA2 (gfx1035) measurements confirmed aligned return values, conditional bit clearing and 16-bit offsets; out-of-range accesses return zero without modifying LDS. Misaligned accesses fault the wave on gfx1035; the recompiler does not model this fault. Radeon 780M (gfx1103, RDNA3) measurements confirmed aligned return values, conditional bit clearing, EXEC masking and operand overlap in wave32 and wave64; contended cases passed per-dword conservation checks. Contended lane ordering and gfx1013 remain unmeasured; pair-wide indivisibility is not assumed, and concurrent 64-bit LDS atomics use a separate lock. GDS throws. VGPR pairs extending beyond v255 throw; allocated-VGPR EXEC nullification is not emulated. -
64-bit image atomics (
image_atomic_*with a two-dword data mask) needVK_EXT_shader_image_atomic_int64and act on 32_32 UINT, SINT and FLOAT surfaces through an R64_UINT storage view. 64-bitimage_atomic_inc,image_atomic_decand the float atomics throw, as does any other access in the same shader to an image it updates with 64-bit atomics. -
8_SRGB and 8_8_SRGB loads on a device that cannot sample R8_SRGB or R8G8_SRGB return the sRGB EOTF rounded to nearest even at bf16 precision, as adriadam10 measured on RDNA2 (gfx1035) in #866; the PS5's gfx1013 is not measured.
-
8_SRGB and 8_8_SRGB textures (libSceAgcDriver) that the device samples as R8_SRGB or R8G8_SRGB use its own decode, which need not match gfx1035: NVIDIA's R8_SRGB is one bf16 step off in 29 of 256 codes.
-
Samples and gathers of 8_SRGB and 8_8_SRGB textures throw on a device that cannot sample R8_SRGB or R8G8_SRGB.
-
Bindless image table entries of 8_SRGB and 8_8_SRGB textures read zeros, like converted formats, on a device that cannot sample R8_SRGB or R8G8_SRGB.
-
Shader MODE register access reads the initial rounding fields from
GuestContext::floatMode; missing metadata retains the legacy round-to-nearest-even assumption. Immediate rounding writes are accepted only when they preserve that state. State-changing or SGPR-sourced MODE writes throw until runtime mode tracking and affected arithmetic are implemented. Non-rounding register reads still throw;s_setreg_b32writes to other hardware registers are still ignored. Tests follow the public RDNA2/LLVM contract, not console measurements. -
A flat SRT read through a null or unmapped pointer loaded from memory raises a BDA fault only if the program executes it, then stops or reads zero like a BDA read.
-
Repeated
s_loads of one flat SRT dword through a null or unmapped pointer report one of their pcs, and ans_loadwhose inaccessible dwords are all unused, or only address repeated loads, reports no fault of its own. -
A value read through a null or unmapped pointer still throws at record time if a branch condition, uniform fill or table base needs it, or if the pointer comes from user data and is not null, even if the console skips the read.
-
A V# or flat SRT word read through a null pointer taken from user data is zero and counts as a poisoned SRT read, so a dispatch that reads it is not cached. The console faults if the program executes the read; PPSA28416 branches around it with
s_cbranch_execz. The fault is not modeled. -
A V#, T# or S# loaded through a null or unmapped pointer read from memory is zero when the work is recorded, and the capture throws if no flat SRT slot records that read.
-
2D accesses through a 1D T# read the texel the 1D addressing selects and ignore the second coordinate, as simonbbby measured on RDNA2 (gfx1036) in #2237 for
image_sample_lzand mip-lessimage_loadwith point filtering and wrap, clamp and border addressing; the PS5's gfx1013 is not measured. A plainimage_sample(implicit LOD) through such a pair takes its LOD from the derivatives of the first coordinate alone, measured on RDNA2 (gfx1036) with the hardware oracle on the quads of a compute kernel (wave32 and wave64, IEEE off, DX10 clamp on, denormals preserved, round to nearest even): on a 16-texel, 5-mip 32_UINT T# with point filters it picks the same mip and texel as DIM 1D for first-coordinate steps of 0, 1, 2, 4 and 8 texels per lane along x or along y, whatever the second coordinate does (normalised steps up to 16 per lane), while the same rows on a 16x16 2D T# move the mip with the second coordinate. Outside the pixel stage a plainimage_sampleis emitted with LOD 0 for every image type, so this pair reads mip 0 there, where the kernel measurement shows the quad's derivatives being used. Other 2D accesses through a 1D T# (storage, depth, packed, BY loads, mips, explicit LOD, bias, offsets, derivatives, comparison) still throw. -
Emulated comparison of a 2D-array access through a 2D T# samples the 2D image and ignores the slice, as the native modes of a 2D-array access through a 2D T# already do. This follows the T# type deciding the addressing; it is not measured on hardware for comparison samples
-
Scalar aperture base sources (core/shader/recompiler) -
src_shared_base,src_shared_limit,src_private_baseandsrc_private_limit(scalar source codes 235 to 238) are not modelled: decoding throwsunsupported scalar source operand codewith the code and the program counter, so a shader that reads one does not compile. Operand 235 (src_shared_base) was reported on #1182 from PPSA26344; the flat aperture routing does not read the base, so a shader that builds its own flat addresses from it stops at decode. -
Flat aperture bases (core/shader/recompiler) - the layout follows the gfx9+ one in the AMD KFD driver's
kfd_flat_memory.c(MAKE_LDS_APP_BASE_V9,MAKE_LDS_APP_LIMIT): each aperture is a 4 GB window whose base is the high dword, so a flat address is routed by its whole high dword, as measured on RDNA2 (gfx1035:src_shared_base0x00010000_00000000,src_shared_limit0x00010000_ffffffff). The PS5's base values, high dwords 0x80000000 (shared,SharedApertureHigh) and 0x70000000 (private,PrivateApertureHigh), are inferred from GTA V's traversal addresses, not measured on a console or read from SH_MEM_BASES -
Flat accesses outside the aperture routing (core/shader/recompiler) - only compute stages route flat accesses, so graphics-stage flat accesses to the shared or private aperture still go to BDA. In compute, a 64-bit flat atomic whose address is in the shared aperture takes the workgroup lock (
ldsLock) for its two-dword update, and every such atomic requests that lock, so a shader with one pays for it even on global addresses (the path is exercised byagc_driver_global_atomics_float). Inferred, not measured on LDS or scratch: an aperture access that is not inside one dword is done byte by byte, an unaligned aperture atomic records the BDA unaligned fault, and LDS or scratch accesses past their end are dropped or read zero. -
On a host subgroup narrower than 32 lanes,
threadBitreads an EXEC written as a value (s_mov_b32/s_mov_b64) at bit (subgroup invocation id) of EXEC_LO, so lanes at or above the subgroup size read a lower lane's bit. -
EXEC read as a value (
s_mov_b64 sN, exec, thes_*_saveexeccopy, ALU sources) holds only lanes with a host invocation; the console's also holds the wave's other lanes, e.g. 32-63 of a wave64 on 32 host lanes. -
v_readlane_b32and fetch-inactivev_permlane16_b32/v_permlanex16_b32read undefined data from a lane that the host subgroup does not hold or whose host invocation is inactive; the console reads the lane's VGPR. -
Without fetch-inactive,
v_permlane16_b32andv_permlanex16_b32take a source lane that the host subgroup does not hold as inactive and keep the old value (0 with bound_ctrl); the console reads that lane's VGPR. -
On a host subgroup narrower than the wave,
v_readlane_b32of a constant lane outside it builds only as lane 63 of a half-wave scan (DPP row_shr 1/2/4/8,v_permlanex16_b32, EXEC -1) or, in a program whose entry EXEC is every lane (vertex, local and tessellation stages), as 0 when the value is 0 in lanes 32-63; other such reads throw. A value is 0 there when it is built from 0 through selects under a lane index (lane id orv_mbcntof -1) below at most 32,v_cmp_ne_u32against 0, OR, DPP and permlanes; the counts ins3give such a bound on a 32-lane host. On a 32-lane host a half-wave scan may also run unders_mov_b64 exec, -1, use bound_ctrl:1 steps for an OR, add or unsigned max, and take keys that are 0 in lanes 32-63; its lane 31 is then the subgroup reduction of the host's invocations (a shuffle of the scan on a device without subgroup arithmetic): idle invocations add the identity, where the console would add the keys of the laness3claims. -
NGG mesh entry uses the guest wave size (32 or 64) for wave indices, per-wave vertex and primitive counts, and the workgroup wave count in
s3. The four-bit wave fields follow Mesa's get_wave_id_in_tg, get_tgsize and get_thread_id_in_tg; partial waves and groups exceeding 15 waves throw. Indexed and non-indexed wave32 mesh rendering with 32, 64 and 128 threads was checked by pixel readback on Windows with an NVIDIA RTX 4070 Laptop GPU. The guest register values have not been compared with console hardware. -
Shader recompilation currently occurs right before it was transferred to Vulkan with caching, but should be moved to the relinker stage. For this purpose, shader/recompiler was written completely independently from libs/prx.
-
v_interp_p1ll_f16, v_interp_p1lv_f16 and v_interp_p2_f16 read the 16-bit halves of each vertex's parameter through
VK_KHR_fragment_shader_barycentricand throw without it, as fixed-function interpolation cannot split a 32-bit attribute. P10 and P20 are the vertex differences rounded to f16 to nearest even, which is not confirmed on hardware. v_interp_p1ll_f16 and v_interp_p1lv_f16 round the exactP10 * I + P0once to f32 and v_interp_p2_f16 rounds the exactP20 * J + S2once to f16, as measured on RDNA2 (#697); the exact sums are computed in f64, so these instructions need the Float64 capability. They follow the shader's float mode, measured on RDNA2 (gfx1035) in all eight combinations ofIEEE_MODEand kept/flushed f32 and f16 denormals over 768 special and 1,024 random rows. With IEEE=1 a NaN operand is returned quieted; with IEEE=0 it is returned unquieted, except that v_interp_p2_f16's f16 result is always quiet. Flushed f32 denormals flush I/J, v_interp_p2_f16's f32 S2 and the f32 result; flushed f16 denormals flush P0, P10/P20, v_interp_p1lv_f16's f16 S2 and the f16 result. Denormal modes 1 and 2 (flush only inputs or only outputs) and rounding other than to nearest even are not measured and throw. An unknown mode follows IEEE=0 with denormals kept. Lavapipe has no barycentrics, so the draw test is skipped in CI;agc_driver_interpolation_modeschecks the arithmetic in every mode against the hardware rows on any device with Float64. -
Without
VK_KHR_fragment_shader_barycentric, a pixel shader whose I/J VGPRs only feedv_interp_p1_f32/v_interp_p2_f32of their own pair reads the attribute Vulkan interpolated. Any other read of them or of a raw vertex parameter takes the weights and the three vertex values from a generated geometry stage, which needsgeometryShaderand a vertex shader before it: tessellation, mesh and rect-list pipelines, primitives other than triangles, more than 32 fragment input locations and interfaces beyond the device's geometry limits throw. -
v_fma_f64 and v_div_fmas_f64 with a subnormal operand or result round once, as IEEE 754 fusedMultiplyAdd does with f64 denormals kept, measured on RDNA2 (gfx1035) at IEEE=0 and IEEE=1,
v_div_fmas_f64with VCC clear and set. The f16/f64 denormal field ofFLOAT_MODE(bits 7:6) is not read: when it flushes, the hardware flushes the operands and the result ofv_fma_f64(tininess before rounding) and only the result ofv_div_fmas_f64, while these keep them. Shaders with f64 instructions declareDenormPreservefor 64-bit floats only whenshaderDenormPreserveFloat64is true and Vulkan reportsdenormBehaviorIndependenceasALL; other independence modes are not handled by the current backend because they require coupled execution modes. See VkShaderFloatControlsIndependence. Elsewhere (including lavapipe), the driver may flush f64 subnormals, andagc_driver_f64_fma_subnormalsis skipped. -
SINT storage images of 8- and 16-bit components saturate each stored 32-bit value to the component range, as adriadam10 measured for image stores on RDNA2 (gfx1035) in #944 (448 rows match); the PS5's gfx1013 is not measured.
-
StoreTexelwrites channel 1 of a two-channel format from the data slot whose DST_SEL is Y, for SINT and UINT alike. With DST_SEL X,Y,Z,W, gfx1035 writes it from the W slot, as adriadam10 measured in #944. -
WAIT_REG_MEM reports a diagnostic after
APS5_GPU_WAIT_TIMEOUT_MSwithout treating the timeout as completion. An unsatisfied wait keeps polling and checking driver failures; a missing producer can therefore leave its queue waiting indefinitely. Existing recorded-label shortcuts remain in use. -
COND_EXEC reads its condition after the earlier packets of its queue complete. Without PFP_SYNC_ME the console's graphics PFP reads it ahead of the ME, so a title that races the read sees a later value here.
-
A flip inside a COND_EXEC range throws: the flip is reserved with the video output when the buffer is submitted, and how the console withdraws a skipped one is unknown.
-
A COND_EXEC range must hold whole packets and end inside its command buffer. A chained INDIRECT_BUFFER or a REWIND inside a range throws, as what the CP does with the skipped dwords then is unknown.
-
A COND_INDIRECT_BUFFER (
sceAgcCbBranch) runs only with the always-pass compare function; a comparison or a predicated packet throws. Modes 1 and 2 run the first buffer, assumed to be the if-then and if-then-else modes of AMD's PM4 packet. sceAgcCbBranch does not check the compare address of an always-pass branch or the address of an empty buffer, as PPSA14632 passes an uninitialised compare address and a null else buffer of 0 dwords. -
A label or store (
RELEASE_MEM,WRITE_DATA,DMA_DATA) into guest memory the device has no host import of waits for all recorded work and is then written by the CPU, so the queue worker stalls once per such label. The console's CP stores it in stream order without that stall. -
WRITE_DATA with DST_SEL 3 (libSceAgcDriver) writes guest memory like DST_SEL 5. AMD's GFX10 header names 3 the GDS, but Killzone: Liberation (PPSA11142) writes its frame fence with
sceAgcDcbWriteData(dst 6, cache policy 3, write confirm), which the SPRX-confirmed encoding (OpenAGC) turns into DST_SEL 3 with a 40-bit label address in the title's own memory thatRELEASE_MEMandWAIT_REG_MEMthen use; the console must write that label or the title would wait on it forever. Whether the console routes it through the GDS or a cache is unknown -
SET_*_REG_INDIRECT (libSceAgcDriver) reads its register list when the command buffer is submitted, with the packets. The console's graphics PFP reads it when it reaches the packet, so a list written after the submission (by the CPU, or by GPU work ahead of the packet behind PFP_SYNC_ME) is read here before that write.
-
The shader float mode (
FLOAT_MODE,DX10_CLAMP,IEEE_MODEandFP16_OVFLofCOMPUTE_PGM_RSRC1andSPI_SHADER_PGM_RSRC1_PS/GS/HS, bit positions from Mesa'sgfx10.jsonandgfx103.json) is decoded intoGuestContext::floatModeand is part of the shader cache keys and the serialized request (#981).IEEE_MODEis read byv_min_f32,v_max_f32,v_min3_f32,v_max3_f32andv_med3_f32, their f16 forms,v_min_f64andv_max_f64,IEEE_MODEand theFLOAT_MODEoutput denormal bits by the output modifier,DX10_CLAMPby the clamp modifier,FP16_OVFLby every instruction with an f16 result (see its entry), and the whole mode by the 16-bit interpolation instructions (see their entries). With IEEE=1 a signaling NaN operand returns that NaN quieted (the first operand checked first, min3/max3 as two nested pairs, med3 as min3 when any operand is NaN), measured on RDNA2 (gfx1035) over every combination of ±0, ±1, ±inf, denormals, quiet and signaling NaNs with f32 denormals kept and flushed. IEEE=0 and unknown modes keep the previous f32 lowering, which matches IEEE=0. The f16 forms choose their NaN results on the bits: a NaN operand returns the other operand unchanged (src0 when both are NaN), and with IEEE=1 a signaling NaN operand returns that NaN quieted, in the same order as f32.v_min_f64andv_max_f64quiet a signaling NaN operand the same way with IEEE=1; with IEEE=0 they return src0 unchanged when src1 is NaN, otherwise src1 when src0 is NaN. Both were measured on RDNA2 (gfx1036) at IEEE=0 and IEEE=1 with f32 denormals kept and flushed and f16/f64 denormals kept; RDNA2 has no f64 min3, max3 or med3. Unknown modes follow IEEE=0.v_min_f16andv_max_f16flush each denormal input to its signed zero when bit 0 of the f16/f64 denormal field is clear (0 and 2); fields 1 and 3 preserve inputs, even when output flushing is enabled. Measured on RDNA2 (gfx1036) at IEEE=0 and IEEE=1, including signed zeros, NaNs and neg/abs modifiers. Unknown modes keep f16 denormals. With f16/f64 denormals flushed the hardware also flushes denormal inputs of f64 min/max, which those lowerings still do not. NaN quieting in f16 arithmetic (the unary instructions and the f32 arithmetic follow it, see below) andFLOAT_MODE(f32 denormals flushed before the min/max compare in Astro's Playroom's 0xc0) still follow a single mode, as the entries below record. The mode comes from the registered shader header'ssh_registers, the same source at registration and at draw/dispatch so the prepared artifact keys match. A title that rewrites RSRC1 at run time, or a raw compute program with no header, compiles with that mode or none. -
v_ldexp_f16 follows the
FLOAT_MODEf16 denormal field: bit 0 preserves the half input and bit 1 the half result. Otherwise a denormal input is flushed to its signed zero, and a result whose exact scaled value is below the minimum normal (2^-14) is flushed to its signed zero before rounding, sov_ldexp_f16 0x07ff, -1gives +0 instead of 0x0400. Measured on RDNA2 (gfx1036) with round to nearest, IEEE 0 and 1 and denorm16 0..3, over every half magnitude 0x0000..0x0fff of both signs scaled by 2^-1 and 2^0 (16384 rows per mode): no mismatch. NaN and infinity handling and destination high-half preservation are unchanged. Shaders without a known float mode keep the previous lowering. -
A WAIT_REG_MEM (libSceAgcDriver) that a compute queue passes on another queue's recorded label store, before the GPU has executed it, is landed before the queue's next dispatch, draw, COND_EXEC or predicated packet reads guest memory: the worker polls until memory satisfies the wait or no unfinished batch writes the label. The graphics queue (queue 0) is exempt, as landing its waits costs PPSA01341 about a quarter of its frame rate; a title that fills memory a graphics command buffer reads after it submits the buffer behind such a wait reads it early there.
APS5_LAND_WAITS_ALL_QUEUES=1lands the graphics queue's waits too. -
The dispatches that follow a compute queue's wait (libSceAgcDriver), up to the next wait that memory does not satisfy, a packet that writes guest memory other than a label, or a conditional packet, are resolved (memory captured, shader recompiled) when the wait passes, as the CP reads them right after it; the graphics queue is exempt (
APS5_GROUP_CAPTURE_ALL_QUEUES=1includes it). The device still reads guest memory when the dispatch is issued; when that memory no longer matches the capture, the dispatch is resolved again from current memory. -
v_mullit_f32 follows the hardware measured with the MODE register at IEEE=1 and denormals kept (a signaling NaN src0 is quieted only with IEEE=1, as measured at IEEE=0 too; a positive denormal src2 counts as positive); with f32 denormals flushed it follows the f32 denormals entry below, and denormal modes 1 and 2 throw.
-
v_mad_legacy_f32 and v_mac_legacy_f32 (VOP3 0x140, VOP2 0x06) round the product to f32 before the add, give a +0 product for a zero factor, and flush their f32 denormal sources, their product and their result to a zero of the same sign in every f32 denormal mode, an exception to the
FLOAT_MODEmodel in f32DenormalFlushFor. Measured on gfx1010 (RX 5700 XT) withtools/hw-oracle/template.s, assembled by the AMD Windows driver'samd_comgr_2.dlland launched through itsamdhip64_6.dllinstead oforacle.cand ROCr, over the 32 rows of the fiveFmaLegacy.cppand the fourMacLegacy.cppencodings: identical in wave32 and wave64 at IEEE 0 and 1 with f32 denormal modes 0 to 3, except that the two signaling NaN rows are quieted only with IEEE=1 (#1281, #1290). A sum of two zeros takes its sign on the bits (+0 unless both are -0), as lavapipe returned -0 for +0 + -0. The PS5's gfx1013 is not measured; LLVM decodes the encoding asv_mad_legacy_f32there, as on gfx1010. RDNA2 differs: on gfx1031 (RX 6700 XT, measured by pandather in #1281) the encoding isv_fma_legacy_f32and fused, with the same zero rule and denormal-source flush, so an RDNA2 measurement is not evidence for the console. -
v_fma_mixlo_f16 and v_fma_mixhi_f16 round the exact product-sum once to f16 with the f64 arithmetic of v_interp_p2_f16, so they need the Float64 capability. On RDNA2 (gfx1036) they follow the
FLOAT_MODEf16 round and denormal fields, not the f32 round field: -1.5 * 2^-24 + 2^-126 from f32 sources (0xbfc00000, 0x33800000, 0x00800000) gives 0x8001 with f16 denormals kept and round to nearest even, 0x8000 with f16 denormals flushed and 0x8002 with f16 round toward -infinity. With f16 denormals kept, every f16 rounding mode is translated: the exact product-sum is rounded once in the mode's direction. All four modes match RDNA2 (gfx1036) on the 2,233 rows of the #2631 sweep, includingFLOAT_MODE0xcc (toward zero, used by ps5-opengl) and the exact cancellations toward -infinity; the PS5's gfx1013 is not measured. A result beyond 65504 becomes infinity or 65504 as IEEE 754 gives for the mode. Flushed f16 denormals still throw, and packed f16 still throws in every mode but round to nearest even with f16 denormals kept.FP16_OVFLset is not measured. -
Signaling NaN inputs of the f32 and f16 unary instructions (
v_sqrt/rcp/rsq/log/exp/sin/cos/fract/floor/ceil/trunc/rndne/rcp_iflag/frexp_mant),v_ldexp_f32/f16,v_frexp_mant_f16,v_div_fixup_f32/f16andv_mullit_f32are returned quieted only with IEEE=1 and unchanged with IEEE=0, measured on RDNA2 (gfx1035) in both modes, and so are those of the f64 forms (v_sqrt/rcp/rsq/fract/floor/ceil/trunc/rndne/frexp_mant/ldexp/div_fixup_f64) andv_cvt_f64_f32, measured on RDNA2 (gfx1036) in both modes; shaders without a known float mode follow IEEE=0.v_pack_b32_f16quiets each signaling NaN half by the same rule, measured on RDNA2 (gfx1036) in both modes. A signaling NaN result ofv_cubesc/cubetc/cubema_f32is quieted by the same rule and keeps the sign the instruction gives it, measured on RDNA2 (gfx1036) in both modes.v_add/sub/subrev/mul/fma/fmac/fmamk/fmaak/mul_legacy_f32andv_fma_mix_f32with f32 sources choose their NaN result on the bits, measured over 1000 operand triples in both modes: the first NaN source in operand order after its modifiers (the subtrahend negated, as the hardware adds its negation), quieted only with IEEE=1, or the default NaN 0xffc00000 for an invalid operation; in the fma forms an invalid product (inf * 0) gives the default NaN even when src2 is a NaN, and in the legacy forms a zero factor makes the product 0 even when the other factor is a NaN (a NaN src2 still wins).v_mad_legacy_f32andv_mac_legacy_f32follow the same rule with their separately rounded product, as measured on gfx1010 (#1281, #1290): a NaN source quieted only with IEEE=1, inf - inf giving 0xffc00000, the zero rule hiding a NaN factor and a NaN src2 winning. The f16 and f64 arithmetic,v_fma_mix_f32with f16 sources and the separately rounded mad/mac forms (not measurable on RDNA2) follow the same rule on hardware but their NaN bits are left to the driver.v_cvt_f16_f32,v_cvt_f32_f64,v_dot2_f32_f16,v_fma_mixlo_f16andv_fma_mixhi_f16always quiet andv_div_scale_f32never does: the f32 signaling NaN 0x7f812345 as src0 or src2 gives 0x7e09 from mixlo and mixhi at IEEE=0 and IEEE=1 on RDNA2 (gfx1036), wherev_fma_mix_f32gives 0x7f812345 at IEEE=0 and 0x7fc12345 at IEEE=1. The payload of an f16 NaN source of mixlo and mixhi is left to the driver's f16 to f32 conversion, which NVIDIA replaces. -
Scalar f16 add, sub, subrev and mul denormals follow the
FLOAT_MODEf16 denormal field at nearest-even: bit 0 preserves inputs and bit 1 preserves the result; otherwise a denormal is flushed to its signed zero. Measured on RDNA2 (gfx1036) with IEEE=0/1 and FP16_OVFL=0/1, over 32 operand pairs in all four denormal modes, including signed zeros, denormals, minimum normals, infinities and NaNs. Multiply detects tininess after rounding to 11 significant bits with an unbounded exponent, before gradual half packing:0x3bff * 0x0400flushes, while0x3c01 * 0x03ffrounds to0x0400and is kept. Directed rounding and ternary arithmetic keep their previous denormal lowering. Shaders without a known float mode keep the previous lowering. Scalarv_sub_f16/v_subrev_f16sharefloat16Binarywith add/mul and were measured on gfx1036 over the same operand set as add (1156 non-NaN-input rows per mode); NaN result bits still depend on the driver as recorded above. -
Packed f16 NaN results (
v_pk_add/mul/fma/min/max_f16) follow the hardware measured on RDNA2 (gfx1035) at IEEE=0 and IEEE=1 with f16 round-to-nearest-even and f16 denormals kept: with IEEE=1 a signaling NaN input is quieted and min/max return the other operand only for a quiet NaN; with IEEE=0 NaN inputs pass through unquieted and min/max ignore signaling. Inv_pk_fma_f16an invalid product (inf * 0) gives the default NaN even when src2 is a NaN. A shader without a known float mode is translated as IEEE=0, the mode titles use; a mode with another f16 rounding or that flushes f16 denormals throws. -
f32 denormals follow the shader's
FLOAT_MODEf32 denormal field (bits 5:4) when it flushes them (0, and shaders without a known float mode, as in the 0xc0 most titles use), measured on RDNA2 (gfx1035) over 1444 rows per instruction at IEEE=0 and IEEE=1.v_add/sub/subrev/mul/mul_legacy/mullit/fma/fmac/fmamk/fmaak/min/max/min3/max3/med3/fract/floor/ceil/frexp_mant/sin/cos_f32flush their f32 inputs and their result to a zero of the same sign (v_mullit_f32measured on RDNA2 (gfx1036) over 6907 rows per mode at IEEE=0 and IEEE=1, so a positive denormal src2 counts as zero); the f32 compares,v_cvt_i32/u32/rpi_i32/flr_i32_f32,v_frexp_exp_i32_f32,v_cvt_f64_f32,v_cvt_f16_f32,v_cvt_pkrtz_f16_f32,v_cvt_pknorm_i16/u16_f32andv_cvt_pk_u8_f32flush their f32 inputs.v_div_scale_f32flushes all three inputs to signed zeros, measured on RDNA2 (gfx1036) over 2744 operand triples per mode at IEEE=0 and IEEE=1 with f32 denormals flushed and kept; its scale-down behaviour and host denormal preservation remain incomplete.v_div_fixup_f32flushes its src1 and src2 and keeps a denormal src0 and result, measured on RDNA2 (gfx1036) over 6859 rows per mode at IEEE=0 and IEEE=1. Tininess is detected after rounding, measured on RDNA2 (gfx1036) forv_mul_f32andv_mullit_f32at IEEE=0 and IEEE=1: a product is flushed when its value rounded to 24 bits with an unbounded exponent is below 2^-126, so0x3f7ffffe * 0x00800001(2^-126 * (1 - 2^-46)) gives0x00800000and0x3f7fffff * 0x00800000(2^-126 * (1 - 2^-24)) gives zero. The check rounds in the f32 round mode ofFLOAT_MODE(bits 1:0), measured in all four modes, while the products themselves are still rounded to nearest even. This applies tov_mul_f32,v_mul_legacy_f32,v_mullit_f32, and tov_fma_f32,v_fmac_f32,v_fmamk_f32,v_fmaak_f32andv_fma_mix_f32when the addend is zero; with a nonzero addend the fused result is kept, so an exact result just below 2^-126 that rounds to it is not flushed. In the three directed modes the check is computed exactly from the significands. To nearest even (0, the mode of shaders without a known float mode) one factor is multiplied by 2^64, which is exact below 2^64, and the product with the other factor is compared with 2^-62. That multiply is a plainOpFMullike the product, and no f32 rounding mode is requested in the SPIR-V, so the check relies on the driver rounding f32 to nearest even by default, as the products do, and a product that rounds up to 2^-126 is the emitted product.v_fma_mix_f32follows this rule with mixed f16/f32 sources too, measured on RDNA2 (gfx1036) with f16 in either multiplicand slot, low and high half selection, and an f32 or f16 zero addend: f320x00801002times f160x3bffgives0x00800000to nearest at IEEE=0 and IEEE=1, while the neighbours0x00801001and0x00801003give zero and0x00800001. The tiny-product boundary was also measured for both signs in all four f32 round modes at IEEE=0; f16 inputs retain their previous conversion and denormal handling.v_fma_mixlo_f16andv_fma_mixhi_f16flush their f32 sources too and keep a product below 2^-126, measured on RDNA2 (gfx1036).v_mad_legacy_f32andv_mac_legacy_f32flush their inputs, their product and their result in every mode, see its entry; their product is still checked for tininess on its exact value, so one below 2^-126 gives zero even when it rounds to 2^-126, as the console's separately rounded encoding is not measured at this boundary. Denormal modes 1 and 2 throw for the other instructions. Not covered, and not measurable on RDNA2 (no such opcodes) or not measured:v_mac_f32,v_mad_f32,v_madak_f32andv_madmk_f32(rounded separately),v_dot2_f32_f16andv_div_fmas_f32(on hardwarev_div_fmas_f32flushes only its result), f32 interpolation andds_add_f32keep the previous lowering;ds_min/max/cmpst_f32flush both operands by the field, see the LDS float atomics entry. With f32 denormals kept (3) the results depend on the driver's default denormal behaviour, as noDenormPreserveexecution mode is requested;v_ldexp_f32is the exception: it preserves subnormal inputs and rounds a subnormal result in the f32 round mode ofFLOAT_MODE, measured on RDNA2 (gfx1036) over 2163 rows in each of the four round modes at IEEE=0 and IEEE=1. An overflow rounds like any other result (infinity, or the largest finite value when the mode rounds that sign toward zero). With f32 denormals flushed it flushes a subnormal input and result, measured over the same rows in each round mode at IEEE=0 only. A device whose driver splitsFmainto a multiply and an add flushes a product below 2^-126 before adding a non-zero addend inv_fma_f32andv_fmac_f32:0x1fffffff * 0x1fffffff + 0x00800000gives0x00800000instead of the fused0x00ffffffon RADV RENOIR (Mesa 26.2.4), whose compiled shader hasv_mad_f32and nov_fma_f32. F32DenormalFlush accepts that sum on such a device. -
The executable file that relinker generates opens the console when launched, which is inconvenient for playability.
-
Overlay output bus (libSceVideoOut) - flips on a port opened with
SCE_VIDEO_OUT_BUS_TYPE_OVERLAYcomplete and signal their events like main-bus flips, but their buffers are not shown: the overlay is not composited over the main output. Presenting them as whole frames made the window alternate between the two buses -
PA_CL_CLIP_CNTL (libSceAgcDriver) -
DX_LINEAR_ATTR_CLIP_ENA(bit 24) clear is drawn like bit 24 set, with Vulkan's clipping ofNoPerspectiveoutputs; what a clear bit changes on the console is undocumented. -
10_11_11 unorm color targets (libSceAgcDriver) render into R32_UINT attachments: the pixel shader packs each export, rounded to nearest even like format-30 image stores, which is assumed to match the CB's conversion.
-
PA_SU_SC_MODE_CNTL.PROVOKING_VTX_LAST (libSceAgcDriver) uses Vulkan's last-vertex mode for native primitives. Bit 19 follows opengnm's
flatshade_firstmapping; vertex selection follows Vulkan, without console measurements. Last mode throws withoutVK_EXT_provoking_vertex, for generated rectangle, mesh or tessellation primitives, explicit per-vertex flat inputs, and triangle strips with per-vertex inputs, whose ordering depends on the device. -
v_rcp, v_rsq, v_sqrt, v_log, v_exp, v_sin and v_cos (f32 and f16) use the driver's approximation for finite results, not the console's: the low bits can differ. Only NaN, invalid, zero and infinite results and the exact sin/cos zeros are chosen on the bits. Measured on RDNA2 (gfx1036) over every f16 input and 32,832 f32 inputs: RADV returns the hardware's bits for every input of rcp, rsq, sqrt and log and all but one of exp (f16 0x11c5, 1 ULP); NVIDIA (615.71.09) stays within 2 ULP except
v_log_f32near 1.0 (next entry). v_sin and v_cos take the driver's sine or cosine of the radians of the exact cycle, except within 2^-12 of a turn from a zero of the function, where the result is the linear term of the exact distance to the zero: the hardware's constant 6.2831826 (0x40c90fd5) at the integers, which the hardware applies exactly to inputs below 2^-12 of a turn, and the f32 2π at the half and quarter turns, where the hardware is within 7 ULP of it. Outside those bands, a driver result more than 4 ULP from a Taylor series in turns of the exact cycle is replaced by the series, which is within 2 ULP of the true sine and cosine; the hardware is up to 9 ULP from them (gfx1035, 243,092 f32 inputs), so results stay within 13 ULP of the hardware on any driver. RADV returns the hardware's bits for every f16 input and for 32,422 sine and 32,486 cosine results of the 32,832 f32 inputs; the rest are 1 ULP off, except up to 14 ULP on either side of non-zero integers and up to 15 ULP beyond ±256 cycles, where the hardware's own reduction differs from the exact fraction, and up to 6 ULP inside the half- and quarter-turn bands. NVIDIA's own sine is within 1 ULP on 93% of the f32 inputs and up to 1,166 ULP off just outside the bands, its cosine within 163 ULP; the series replaces those results. A denormal f32 input with f32 denormals kept gives the hardware the input times 6.2831826; both hosts flush it. -
v_log_f32 and v_log_f16 keep the driver's log2 unless, for inputs within 1/8 of 1.0, it is more than 4 ULP from an eight-term series in x - 1, which then replaces it.
v_log_f16goes through the same f32 lowering and is rounded to half. The series is evaluated for everyv_logand chosen withOpSelectrather than a branch, so its seven fused multiply-adds and two multiplies are an unconditional cost. Measured on RDNA2 over all 3,145,728 f32 inputs within 1/8 of 1.0 (gfx1035, IEEE 0, f32 denormals flushed), the hardware is within 1 ULP of the correctly rounded log2 and the series within 2 ULP of it and within 3 ULP of the hardware (2 except at 0x3f752e47, 0x3f7baab0 and 0x3f7bc4fb), so a kept driver value is within 7 ULP of the hardware and a driver that returns the hardware's bits never triggers the gate; RADV (Mesa 26.2.4) returns the hardware's bits on the 9,280 such inputs measured on gfx1036; NVIDIA (615.71.09) was up to 23,947,836 ULP off at 1 - 2^-24 and is within 6 ULP inside the band after the change; outside it its own log2 stays up to 9 ULP off (measured up to 1.375). Over every f16 input, the change moves onev_log_f16result on NVIDIA (0x3bed, 1 ULP, onto the hardware's bits) and none on RADV. -
Dual-source blending (libSceAgcDriver) takes the MRT1 export as the second source of the MRT0 blend, as RADV and radeonsi program it; what the CB does with other export or target layouts is unknown, so they throw.
-
--to-inteldoes not lower RDPRU/MCOMMIT; the matcher fails the relink instead. -
Ordered not-equal, less-than and greater-than compares (shader recompiler) -
FPOrdNotEqual32is emitted asOpFUnordNotEqual, andFPOrdLessThan32andFPOrdGreaterThan32as their ordered forms, each with both operands checked for NaN on their bits; the results are the same for every input. The AMD Windows driver 32.0.13058.8001 (Radeon 860M, RDNA 3.5) returns 1 for a NaN operand when any float form of not-equal feeds a ballot on a 32-wide subgroup (#825), and so does a less-than or greater-than against an infinity the driver sees as a constant (#3536), presumably rewritten into a not-equal by its compiler -
sce::Job::JobManager (libSceJobManager) is written from the disassembly of the copies PPSA01474 and PPSA36082 ship in
sce_module, andguest_job_manager_testspasses against both of those modules as well: the memory size formula, the error codes, sync point ordering, the per-sequence limits and the priority order are the original's. Only CPU sequences exist:initializeandcalculateRequiredMemorySizewith compute sequences, and both compute dispatches, are not implemented, andcreateComputeanddestroyComputereturn the errors the original returns when no compute sequence was configured. The manager's state lives on the host heap, with only the block header written to the title's memory; the original keeps everything in that block, and a block smaller than 0x2d8 bytes throws here. The worker sleep policy, the spin count and the persistent thread count are validated and stored but change nothing, a factory priority above 1 throws,shutdownthrows while a thread is blocked in a sequence wait, and using a sequence after itsdestroythrows.initializereturns 0 where the original returns the result of its last import (BG26hBGiNlw, not resolved to a name), thesceRazorCpuJobManager*profiler calls are not made, and a worker thread that cannot be created or configured throws where the original does not check. The order of the sequence and factory virtual functions is read from the modules' vtables only, since no title that calls them has been run -
The length-changing path of the instruction rewriter is not used by the converter: it does not adjust data-to-code references (relocations, FDEs, jump tables) or segment sizes, so every substitution keeps the instruction length.
-
In executables with a
PT_SCE_DYNLIBDATAsegment, the PS4 layout, the executable segment also holds read-only data after the code (CUSA00900: 37 MiB after its last function). The relinker pipeline therefore scans for syscalls and import call sites only up to the end of the PLT that follows the last function of the unwind table; code after the PLT without an unwind entry is not scanned.--to-inteland theunused-filter=1andunused-filter=2analyses are not limited this way. -
DB_SHADER_CONTROL.CONSERVATIVE_Z_EXPORT (libSceAgcDriver) becomes
DepthLess/DepthGreater. For a pixel shader that breaks the promise, the host driver decides whether its interpolated Z is depth-tested before shading; what the console does then was not measured. -
DB_SHADER_CONTROL.PRIMITIVE_ORDERED_PIXEL_SHADER (shader recompiler) - the host pixel interlock spans the whole shader, not only up to
s_sendmsgORDERED_PS_DONE. -
POPS collision SGPRs (shader recompiler) - the collision wave ID and intrawave collision mask read 0, so a title skips its POPS wait and runs its per-collision loop once.
-
Image loads (shader recompiler) - an image_load reads a sampled binding, also of an image the shader stores to, so in a primitive-ordered pixel shader it misses an earlier overlapping primitive's image_store in the same draw.
-
PA_SC_CONSERVATIVE_RASTERIZATION_CNTL (libSceAgcDriver) - 0x6001 uses Vulkan overestimation on devices that add at most 1/256 pixel and keep degenerate triangles; the console's uncertainty region and degenerate handling are unmeasured. A value with
OVER_RAST_ENABLEandUNDER_RAST_ENABLEclear is decoded as disabled even whenUNCERTAINTY_REGION_MODEor theOUTER_/INNER_UNCERTAINTY_EDGERULE_OVERRIDEbits (19:16) are set, as PPSA01474 writes 0xe6000; that these fields have no effect without over- or underestimation is assumed from their names, not measured. -
The Linux placement of the
--to-intelstubs in the ELF patcher is covered only by a synthetic test. -
The libc SSE4a trap emulation on Windows is superseded by
--to-inteland remains only until the relinked title has been verified without it. -
getifaddrs (libc) lists the host's IPv4 and IPv6 addresses in FreeBSD's
ifaddrsand sockaddr layouts. FreeBSD's per-interface AF_LINK entries (MAC, index, MTU) and theirif_dataare not produced, so interfaces without an address are omitted. Names are the host's (Linuxlo,eth0; Windows NDIS names such asethernet_32769, orif<index>when one does not fit 15 bytes), not the console's. A Linux point-to-point address without a peer losesIFF_POINTOPOINT, and an IPv4 broadcast address the host omits is computed from the netmask. On Windows the flags are onlyIFF_UP,IFF_RUNNING,IFF_LOOPBACK,IFF_BROADCASTandIFF_MULTICAST, derived from the adapter: PPP and tunnel adapters get neitherIFF_BROADCASTnorIFF_POINTOPOINTbecause their peer address is not reported, and an address whose prefix length the host reports as unspecified gets a host mask. -
gethostname (libc) reports the fixed guest name
AnyPS5without querying the host machine name. Buffer copying, null queries andENAMETOOLONGfollow FreeBSD gethostname; the console's configurable hostname and its integration withsysctland name resolution are unverified and not implemented. -
Descriptor pool chain (libSceAgcDriver) - each pool holds two storage buffer descriptors more than a set can take, as a workaround: RADV (Mesa 26.0 and later) lets a
FREE_DESCRIPTOR_SETpool place a set up to 32 bytes past the pool's buffer (util_vma_heap_initis givenbo_size + RADV_POOL_HEAP_OFFSETas a size), and with a page-multiple pool size those bytes are an unmapped page -
CMASK fast clears (libSceAgcDriver) - each fast-cleared CMASK tile (code 0) is stored as
CB_COLOR_CLEAR_WORDinto its 8x8 texels at the first draw into the target or at its fast-clear eliminate or DCC decompress pass, not as the color block writes the tile, and the CMASK is then stored as expanded (0xF): a texture or copy read of the target after that draw and before the title's eliminate sees the clear value in tiles no draw wrote, where the console keeps their previous bytes. Tile addresses follow the pipe-aligned SW_64KB_Z_X CMASK equation for 16 pipes; other CMASK swizzle modes, codes other than 0 and 0xF, a cleared tile of a DCC target and a fast clear of a mipmapped, 3D or array color target throw. When the clear runs as a compute pass (a resident target whose CMASK is host-imported), an invalid code throws at the next fast-clear materialization, not at the one that read it -
HTILE depth fast clears (libSceAgcDriver) - HTILE is not modeled. Only RADV's
clear_htile_maskcompute kernel (17 GFX10 words, 64x1x1 groups) is recognized, and only when it leaves ZMASK at 0 (user[4]anduser[5]low nibbles both 0); the dispatch still runs, and the host depth image is cleared toDB_DEPTH_CLEARthe next time the surface with thatDB_HTILE_DATA_BASEaddress is bound. The address match is exact, so a clear of a different HTILE range does not hit. HTILE initialization, the stencil-only update, and fast clears made by the SDK's own paths, CP DMA fills or other kernels are not covered and leave the depth image as it was. The kernel words are the ones the PR author saw RADV submit; they are not compared with Mesa's source. -
Host imports (libSceAgcDriver) on Linux skip ranges that are not mapped read-write, which are copied instead. The NVIDIA driver (595.91.07) refuses
VK_EXT_external_memory_hostimports of read-only or executable mappings (and shared mappings of regular files) withVK_ERROR_OUT_OF_DEVICE_MEMORY, after which everyvkAllocateMemoryon the device fails the same way. Read-only ranges are never imported, even on drivers that accept them. Shared mappings of regular files are not checked for. On Windows, a run of adjacent registered ranges whose shared views are not one contiguous run of views of a section gets no read-write alias, so its ranges are imported one at a time, as before runs were imported whole, and a buffer that crosses two of them is copied. Adjacent registered ranges are joined into one import only where they fill a whole 8 MiB aligned window; ranges of a partly filled window are imported one at a time, and a buffer that crosses two imports is copied. The 8 MiB window is a choice: unbounded runs were re-imported whole on every growth of a heap mapped in small pieces, and the NVIDIA driver (610.57.04, 615.78.08) then refused imports or lost the device. Not measured on RADV. -
Cube texture descriptors with equal
BASE_ARRAYandDEPTHexpose six faces starting atBASE_ARRAY. Measured withimage_load,image_sampleandimage_get_resinfoon RX 6600 (gfx1032), using 64x64 R32_UINT faces and base slices 0, 5 and 6. Other ranges containing fewer than six faces or incomplete cube arrays still throw: hardware load bounds and filtered-sample addressing differ. Out-of-range cube-array sampling remains unimplemented. Samplers withDISABLE_CUBE_WRAPare created withVK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT, the flag RADV maps to that bit (Mesasrc/amd/vulkan/radv_sampler.c,src/amd/common/ac_descriptors.c); withoutVK_EXT_non_seamless_cube_mapa cube texture sampled through such a sampler throws. PS5 equivalence has not been measured on console hardware. -
Multisampled CMASK (libSceAgcDriver) - a multisampled color target's CMASK is decoded under CB_COLOR_INFO FAST_CLEAR (bit 13, as for a single-sample target) or COMPRESSION (bit 14). Which bit a multisampled target sets is inferred: its fast clears were seen on GTA V's multisampled targets through their CMASK fills, not in a register dump. A COMPRESSION-only target's zero CMASK is not read as cleared (inferred: zero means cleared only under FAST_CLEAR), so only a fill after its first use clears it. A slice of a multisampled array is its own image at its own address with its own CB_COLOR0_CMASK (inferred from the register layout). Its CMASK is main's whole-metablock size.
-
Multisampled CMASK state (libSceAgcDriver) - a multisampled target has no guest texels, so its CMASK state comes from fills rather than from a read at each draw as a single-sample target's does. A fill of the whole CMASK with 0 clears the host image at the target's next use, one with 0xffffffff marks it expanded, and any other pattern, or a fill that covers only part of the CMASK, throws at the next use (inferred: main's rule that a mixed CMASK is unmodeled, applied to the one host image). A FAST_CLEAR target starts from its CMASK keys at its first use, and a COMPRESSION-only target starts expanded. Copies by DMA into the CMASK are not seen, and a later use with another CMASK address throws. The clear does not rewrite the CMASK bytes as expanded, so a new target over the same CMASK (a different extent, so a different image) seeds from them again and clears once more.
-
Multisampled targets in CB passes (libSceAgcDriver) - a CB eliminate or DCC pass over a multisampled target throws, since its texels are on the host and only a CB resolve is modeled. A CB resolve into a fast-clear destination throws: the resolve writes the destination's texels but not its CMASK, which would still read as cleared.
-
Multisampled target guest access (libSceAgcDriver) - the memory a multisampled color target throws on (CPU read, DMA copy, texture or storage image read) is taken as
max(CB bytes * samples, width * height * element bytes * samples)from its address, an upper bound on the sample planes of a target laid out in 64 KiB blocks (inferred: the single-sample layout size times the sample count; the exact fragment-aware footprint of addrlib is not computed, so a few bytes past the real footprint can throw too). Targets are kept per device for the device's lifetime, one per surface address, format, extent and sample count, and are not evicted. -
DCC display buffers are presented only when all keys of the console's DCC extent agree on uncompressed or a fast-clear code, padding keys included; other keys, and register-clear keys over a pending image, throw.
-
Storage image write-back (libSceAgcDriver) stores the GPU results over a CPU-stamped range whose guest bytes equal the copy taken when the image's layers got their generation (images up to 1 MiB whose guest bytes were settled at that point, with no unit shadow, pending image results or recorded GPU store over them; other images keep the previous rule: the CPU's bytes win). A CPU store that rewrites the baseline value after the GPU changed it is not told apart from no store, and the GPU result wins there. The 1 MiB limit is a choice, not a console value.
-
16-bit float display buffers (libSceAgcDriver, libSceVideoOut) - pixel formats
0xC001000622000000and0xC001000600000000are taken as R16G16B16A16 and B16G16R16A16 float, eight bytes per texel, as KytyPS5 maps them and SharpProspero names them (Rgba16Float,Bgra16Float); PPSA11386 registers 3840x2160 tiled buffers of the first. The tiled layout is assumed to be the 8-byte SW_64KB_R_X equation ofTextureSwizzleEquations.hppapplied to full coordinates, as addrlib applies it, by analogy with the 32-bit scanout;ColorTargetLayoutapplies the equations to in-block coordinates, which for 8-byte texels differs in every odd 64-row block row (address bit 11 takes y bit 6) and for 16-byte texels also differs, so a float display buffer written throughWriteColorTargetand presented from guest memory would show those rows misplaced. The values are assumed to be linear light and are encoded with the sRGB curve for the 8-bit output. Bits 32-39 of these formats are0x06, as in the 10-bit formats SharpProspero lists without sRGB transfer, while its sRGB formats have0x00, its 10-bit PQ formats0x04(with0x07in bits 40-47) and its float BT.2100 PQ formats0x07: they show only that these formats are not the sRGB ones. NaN and negative values give 0, values of 1 and above give 255, alpha is linear. Neither the layout nor the transfer is verified against console or title frames, and HDR output is not modelled. DCC metadata on a float buffer throws. -
DCC key stores cover the console's DCC extent only for pipe-aligned DCC of single-level, single-layer 4-byte SW_64KB_R_X surfaces; other surfaces, and every texture and color target key read, cover one byte per 256 bytes.
-
DCC key fills over other images (libSceAgcDriver) - a uniform fill at a live image's
dccAddress, at least one key per 256 bytes long, is a key fill of that image even when other live images overlap it, but only while it is no longer than the image's key extent (DccKeyCount, the pipe-aligned count); a longer one is classified by its overlaps as before. The bound is inferred, not measured on a title: a longer fill also writes the bytes past the keys, which the overlapping image may own. Whether the title's bloom-target key fills stay within the extent was not checked (APS5_TRACE_DCC_KEYSprints the length of the fills classified as keys, not of the refused ones). -
Comp-to-single DCC keys (libSceAgcDriver) - key 0x10 (
GFX9_DCC_CLEAR_SINGLEin Mesaac_descriptors.h) is expanded only by a CB DCC decompress pass over uniform keys of a non-linear target: every texel takes the element at the start of its 256-byte block, the top-left texel of the block where radv'sbuild_clear_dcc_comp_to_single_shaderstores the clear color. A fast-clear eliminate over such keys and mixed keys throw; textures and color targets that read them use their stored texels. "Uniform" is judged over the key bytes the driver reads, one per 256 surface bytes (see DCC key stores above), so a pipe-aligned surface whose keys differ past that range is expanded as if all were comp-to-single, as for the other clear codes. Not verified on hardware -
8_SRGB color targets (libSceAgcDriver) on a device that cannot attach and blend R8_SRGB render into an RGBA8_SRGB copy of the target, so the sRGB encode, decode and blend rounding are the device's; the console's are not measured.
-
8_SRGB color targets (libSceAgcDriver) on such a device throw unless they are single-mip 2D surfaces with a resident image; linear targets have none.
-
COPY_DATA from the GPU clock (libSceAgcDriver,
SRC_SEL9) writes the host steady clock in 10 ns ticks when the packet runs, the same counter as theRELEASE_MEMtimestamp, not the console's GPU clock. TheCOPY_DATAcache policy fields are accepted and have no effect. -
16-bit RGBA color targets (libSceAgcDriver) support the standard and the alternate (
COMP_SWAP1) component order. Alternate swaps red and blue in shader exports, write masks and constant-color blend factors, followingac_translate_colorswapin Mesa 26.2.2 ac_formats.c. The reverse orders (COMP_SWAP2 and 3) keep throwing when blending, and simultaneous targets requiring conflicting blend constants throw. Console equivalence has not been measured on hardware. -
UINT16_ABGR color exports (libSceAgcDriver) - export format 7 is accepted only into an unsigned integer target, and each 16-bit value reaches the target unchanged; a value beyond a narrower target's range (
R8_UINT) is undefined in Vulkan, and whether the console clamps or truncates it is not confirmed. SINT16_ABGR (8) throws -
--to-intelguest module trampolines are covered only by a synthetic relinker test; no game title has been verified with them on Linux or Windows. -
--to-rosettalowers what Rosetta lacks on top of--to-intel(matcher). Rosetta runs AVX2, FMA, BMI1/2, F16C and MOVBE but reports none of them through CPUID, so code that checks CPUID takes its baseline path. RDSEED becomes RDRAND and CLWB a NOP. RDPID returns processor 0, because Rosetta's TSC_AUX is the constant 0xAAAAAAAB; the same value reaches RDTSCP's ECX, which is not converted. ADCX/ADOX fault under Rosetta and are not converted: compilers do not emit them, and code that checks CPUID sees no ADX. The conversions are covered by the converter tests; that the converted code runs under Rosetta was checked on an M5 Max only, outside this repository's CI. -
--to-intelreplaces the approximate legacy SSE and VEX.128 register forms of RSQRTPS/RCPPS and VRSQRTPS/VRCPPS with correctly rounded 1/sqrt(x) and 1/x, not with the AMD approximation: its tables are not public. Intel's approximation of 1/sqrt(1.0) is 0x3F7FF000, and two Newton-Raphson steps on it settle on 0.99999994 instead of 1.0; a renormalised identity quaternion then turns into a NaN axis in PPSA21564, which the console does not show. Refined results now reach the exact value; unrefined ones can still differ from the console in the low bits. Each site costs an out-of-line stub (two jumps, a spill below the red zone, SQRTPS/DIVPS). Legacy SSE forms preserve the destination's upper YMM bits; VEX forms clear them. The 256-bit, scalar and memory forms keep the native instruction, as does a site shorter than 5 bytes with no movable instruction after it for the jump (5 sites in PPSA21564, counted before a following RIP-relative instruction could move into the stub; not recounted). -
sceKeyboardGetKey2Char (libSceKeyboard) translates the 101-key (US) arrangement and the alphanumeric layer of the 106-key (Japanese) one, which follows the JIS layout of the HID usages: the Yen (0x89) and Ro (0x87) keys return
\(0x5C) unshifted, as JIS X 0201 places the yen sign there; whether the console returns U+00A5 instead is unverified. With the Kana LED (bit 4, the HID position) set the 106-key arrangement throws, as the kana the console returns are unknown. Ctrl and Alt do not change the character. -
sceAudioOut2Set3DLatency and sceAudioOut2MasteringInit, sceAudioOut2MasteringTerm and sceAudioOut2MasteringSetParam (libSceAudioOut) have no effect: there is no 3D rendering or mastering stage.
-
sceImeKeyboardGetInfo (libSceIme) returns
0x80bc0023(no resource id) for every id while a keyboard is open, since the IME keyboard never reports a connected device. sceImeKeyboardSetMode validates the mode bits but the mode has no effect, as no IME keyboard events are delivered. -
AudioOut2 contexts (libSceAudioOut) with an SDL device read a grain's port buffers at the next push, at least 100 us after the grain was pushed, and play the mix behind a 40 ms cushion that the queue level leaves out. When the hardware reads the buffers is not known. The timing follows a title whose mixer fills a buffer after pushing it, reuses it two pushes later, and may still be writing it when the next push follows within microseconds. The last grain pushed before a title stops pushing is never read or played.
-
sceAudioOutSysGetHdmiMonitorInfo (libSceAudioOut) reports an HDMI sink without a monitor name or audio descriptors: it zeroes the 0x180 bytes and returns 0, since audio reaches the host through SDL as PCM and there is no EDID to describe. The arguments
(type, info, size), the required size 0x180 and the fields titles read (monitor name at +0x0B, 13 bytes; descriptor count as a 32-bit value at +0x94; 8-byte descriptors[coding type, channels, rate mask, 0, extra, 0, 0, 0]from +0x98) come from PS5-Audio-Passthrough-Research (firmware 12.70, one monitor). What a console without an HDMI audio sink returns, an error or no descriptors, is unknown. The other bytes, among them the header at +0x90 (01 09 4f 00on that monitor), have no known meaning and are written as 0. No LPCM descriptor is reported for the host device, as the rate mask and extra byte of one are not known. A null buffer returns0x80260004like the other AudioOut calls; the console's code is not measured. Monitor type 0x10, which the console also accepts, other types and sizes other than 0x180 throw: their results and error codes are unknown. -
libSceAudiodec throws for the 24-bit PCM word size (
iBwPcm0): its sample layout is unknown. ATRAC9 decoding is covered only by configuration and error tests, as no ATRAC9 encoder is available for a fixture. -
sceAjmDecMp3ParseFrame (libSceAjm.native) throws when the original file length is requested (
parse_oflnon-zero) for a layer other than III, for a CRC-protected frame, or for a VBRI header outside MPEG-1 stereo: shadPS4 looks for the tag after the CRC and after the side information, while LAME and FFmpeg place it without the CRC and VBRI always at byte 36. -
ATRAC9 gapless segments (libSceAjm.native) - a run job stops after the gapless total of output samples counted from the start of the segment, leaving the rest of its input unconsumed, and the next run starts the next segment with the decoder as it is and without a second skip. FMOD in PPSA29141 sets a total shorter than a sound's frames and reads the frames after it on later runs; with the output held at the total its stream reader waited for them forever and the last buffer repeated. The console's handling of the frames after the total is not documented; a reset (
SetGaplessDecodewith the reset flag,ClearContext, initialization) starts a new segment. An ATRAC9 run job withoutRUN_MULTIPLE_FRAMESdecodes its whole input as one with it: FMOD in PPSA29141 puts two run jobs in one batch with the second's input right after the whole of the first's. Whether the console stops after one frame there is not verified; MP3 and Opus run jobs still stop after one frame -
Tessellation rings of local, hull and domain programs become Vulkan tessellation interfaces and are never written to guest memory; a title that reads the off-chip or factor ring back sees no data.
-
Inner tessellation factors of fractional-odd triangle patches that are NaN tessellate as 1, as in the D3D11 reference tessellator; the console is not measured.
-
VGT_TF_PARAM (libSceAgcDriver) - DISTRIBUTION_MODE is taken as scheduling only; the host tessellator decides the order of a patch's triangles.
-
Hull programs start from the hull launch registers (user data, ring bases, v0, v1); on the console they start with what the local program leaves, and that it leaves them unchanged is not checked.
-
Local programs (libSceAgcDriver) that the hull header leaves at address 0 are prepared at their first draw, one artifact per tessellation configuration, instead of at registration.
-
The output modifier (
mul:2,mul:4,div:2) follows the shader's float mode as measured on RDNA2 (gfx1035): the hardware applies it only with IEEE mode off and output denormals of the result's precision flushed (bit 1 of theFLOAT_MODEdenormal field clear), and ignores it otherwise. On f32 results it is applied as the hardware does with f32 denormals flushed; a shader without a known float mode is translated with IEEE mode off and f32 denormals flushed, the mode titles use. On f16 and f64 results it is ignored, and it throws in the modes where the hardware applies it. -
The clamp modifier follows
DX10_CLAMP, measured on RDNA2 (gfx1035) for f32, f16, packed f16 and f64 results at IEEE=0 and IEEE=1: withDX10_CLAMP=1 (and in shaders without a known float mode) a NaN result clamps to +0, including the quieted NaN thatv_pk_min_f16andv_pk_max_f16return for a signaling NaN operand with IEEE=1 (measured on RDNA2 gfx1036 at bothIEEE_MODEand bothDX10_CLAMPsettings); withDX10_CLAMP=0 a NaN result is written unchanged and every other value clamps to [0, 1] as before. f64 results follow the same rule on hardware, but a clamped f64 result withDX10_CLAMP=0 throws until it has an execution test. WithDX10_CLAMP=0 the NaN's bits are those the translation already produces for the instruction without clamp, so where those are left to the driver (f32 and scalar f16 arithmetic) the payload is the driver's, not the hardware's input propagation.v_dot2_f32_f16and the integer clamps are unchanged. -
FP16_OVFL follows the shader's float mode as measured on RDNA2 (gfx1036) at IEEE=0 and IEEE=1 with f16 denormals kept and flushed: with
FP16_OVFL=1 an f16 result that rounds to ±infinity is written as ±0x7bff unless a source operand is infinite, sov_rcp_f16,v_rsq_f16andv_log_f16of ±0 andv_exp_f16of 16 or more are clamped while an infinite input passes through, andv_div_fixup_f16keeps the infinity it writes for a zero denominator or an infinite numerator and clamps any other infinite quotient, a NaN one included.v_cvt_pkrtz_f16_f32rounds toward zero and never overflows. The sources are checked as the f32 values the translation computes with; the rule is applied tov_fma_mix*_f16with f32 sources and tov_interp_p2_f16without a measurement of infinite f32 sources or parameters. Round modes other than nearest even are not modelled, so the overflow threshold is the nearest-even one (65520). -
Directed f16 rounding for
v_cvt_f16_f32,v_cvt_f16_i16,v_cvt_f16_u16andv_ldexp_f16followsFLOAT_MODEbits 3:2 only when f16 denormals are preserved (bits 7:6 = 3), measured on RDNA2 (gfx1036). With f16 denormals flushed (bits 7:6 = 0), or flushed on one side (modes 1 and 2, not measured), the hardware also flushes the f16 result and the directed path does not model that, so those shaders keep round-to-nearest-even. Theclampmodifier with directed rounding is not measured. -
Comparison sampling of a color texture (
image_sample_c/image_sample_c_lzon a texture that is not R32 float or R16 unorm) is emulated in the shader, since Vulkan compares only depth formats: the red channel is fetched, compared and, for bilinear filtering, blended (compare, then filter). Only 2D, 2D array and cube views, float/unorm/snorm formats, wrap, clamp-to-edge and clamp-to-border addressing (border red 0 for the black borders, 1 for opaque white) and point or bilinear filtering at one level are implemented, with texel offsets added to the texel indices; LOD biases and clamps are accepted, as they cannot select another level of a single-level sample. Half-border addressing, the border color table, gradients, gathers, other dimensions, anisotropy and mip filtering throw. Under bilinear filtering, taps past a clamp-to-border edge compare the border value and blend with the texel taps, so results near the edge depend on the filter weights. AMD documentation does not say how a color format's reference is handled: it is clamped to [0, 1] for unorm and [-1, 1] for snorm, as Vulkan does for unorm depth, and not clamped for float. 8-bit sRGB (Format8Srgb,Format8_8Srgb,Format8_8_8_8Srgb) returns 0 for every compare function, measured withimage_sample_c_lzon gfx1035 over references -0.5..1.5 and texel codes 0..255; that measurement also returns 0 for 8-bit UNORM, which this path still compares. A bilinear cube of those 8-bit sRGB formats withoutDISABLE_CUBE_WRAPreturns 0 for the same reason; float, unorm and snorm bilinear cubes without that bit still throw. Bilinear weights are full float, not the hardware's fixed-point subtexel weights -
Negative color-texture comparison wrap indices (libSceAgcDriver) use explicit
OpSRemnormalization to implement modulo; the negative-offset point-wrap regression fails with directOpSModand passes with normalization on Mesa 22.3.6 llvmpipe (LLVM 15.0.6), but negative-index wrap has not been measured on PS5 hardware. -
libScePlayerInvitationDialog simulates dialog completion without displaying UI or sending invitations, so
scePlayerInvitationDialogGetResultreportsUSER_CANCELED; its parameter ABI remains unverified. The 40-byte result layout (error code, result, 32 reserved bytes) is taken from SharpProspero and the error codes from the other common dialogs, not confirmed on a title. -
Converted unorm images (10_11_11_UNORM, read and written through an R32_UINT view): samples, gathers, LOD queries, 16-bit data and a DST_SEL of the missing W channel throw.
-
Packed 16-bit textures (libSceAgcDriver) -
5_6_5,1_5_5_5and4_4_4_4are viewed as R5G6B5, A1R5G5B5 and B4G4R4A4 (the 4-bit format every Vulkan device can sample; R4G4B4A4 is optional and lavapipe lacks it) with a swizzle that reads X from the low bits, and a DST_SEL of the missing W of5_6_5reads X. Measured on RDNA2 (gfx1035), not on the console: throughimage_loadandimage_sample_lz, X, Y, Z (and W of1_5_5_5and4_4_4_4) come from the low, middle and high fields, and W of5_6_5returns X (the low 5 bits), not 1. -
Converted unorm image loads divide by 2^n - 1 with the buffer format path's
OpFDiv, which Vulkan allows to be up to 2.5 ULP off, so some drivers are not bit-exact. -
64-bit LDS atomics (
ds_*_u64,ds_*_b64,ds_*_f64) read and write the two dwords under a workgroup lock stored after the guest LDS, as LDS is a 32-bit array without 64-bit atomics. On RDNA2 (gfx1036) the LDS serialises a 32-bit atomic on a slot's high dword and a 64-bit atomic on that slot: 128 lanes ofds_add_u32and 128 lanes ofds_add_u64on one slot sum exactly. Only that pair was measured. Every 32-bit LDS atomic of a program that contains a 64-bit LDS atomic therefore takes the same lock, including a 32-bitflat_atomic_*whose address lands in the LDS aperture (a 64-bit one takes it already); the flat forms were not measured against a 64-bit atomic either (the other 32-bit LDS atomics,ds_min/max,ds_cmpst, the float forms,ds_inc/dec,ds_mskorandds_wrxchg, are extrapolated fromds_add_u32and were not measured against a 64-bit atomic); a program without a 64-bit LDS atomic keeps its native 32-bit atomics.ds_condxchg32_rtn_b64is twods_mskorhalves, each under the lock but not atomic as a pair, so a 64-bit atomic between the two halves is not excluded. Sub-dword writes (ds_write_b8,ds_write_b16and their_d16_hiforms) and plainds_read_*,ds_write_*,ds_append_u32andds_consume_u32are not taken under the lock, so a plain access racing a 64-bit atomic on the same dwords can see or overwrite one half of it; whether the hardware orders them was not measured. The lock serialises the workgroup's LDS atomics of such a program; the throughput cost was not measured.VK_KHR_workgroup_memory_explicit_layoutwithshaderSharedInt64Atomicswould make both widths native and is not used. A 64-bit atomic at an address that is 4-byte but not 8-byte aligned faults the wave on gfx1036, as on gfx1035. -
LDS float atomics (
ds_min/max/cmpst_f32,ds_min/max/cmpst_f64and their_rtnforms) follow the hardware measured on RDNA2 (gfx1036) over 14 x 14 operand sets (zeros, ones, infinities, denormals, quiet and signalling NaNs of both signs and with payloads) in IEEE 0 and 1 with every value 0-3 of the type's denormal field: both operands are flushed to a signed zero when bit 0 of the field is clear (0 and 2; 1 and 3 keep them; the f32 field for the f32 forms, the f16/f64 field for the f64 forms; a shader without a known float mode flushes f32 and keeps f64), then a signalling-NaN data operand is stored quieted, else a signalling-NaN old value is stored quieted, else a quiet-NaN old value is replaced by the data, else a quiet-NaN data operand loses, else the ordered compare with -0 below +0 decides, and the flushed value is what is written, also when the old value wins.cmpstcompares the flushed bits (both zeros equal, NaN never equal) and leaves memory unchanged when they differ. The returned value is always the old value as it was in memory.IEEE_MODEhas no effect. The same bit rule serves the buffer float atomics (AtomicFloatBits). Not measured: a denormal or signalling-NaNdata1ofcmpst(stored as given), andds_add_f32, which keeps the host'sOpFAdd. -
V# bases off a DWORD boundary (shader recompiler) - raw accesses use the exact bytes and
s_buffer_loadreads(base & ~3) + (offset & ~3), as measured on gfx1035 (Linux, alignment mode UNALIGNED; the console's mode is unknown). Formatted accesses off their element's alignment and atomics throw. -
32-bit bitfield masks (
S_BFM_B32,V_BFM_B32) use the truncating 32-bit shift specified by the RDNA 1.0 ISA, sections 12.1 (opcode 36) and 12.12 (opcode 867). Width and offset use their low five bits. This matches gfx1035 (Linux) for every width/offset pair, with and without upper operand bits set, and both leave SCC unchanged; not measured on the console. -
Vector buffer offsets that are not a multiple of 4 (shader recompiler) - dword accesses count whole dwords from the V# base, where the hardware reads the exact bytes at base + offset.
-
Min/max S# reduction (libSceAgcDriver) -
FILTER_MODE1 and 2 use Vulkan's min and max reduction (the sameSQ_IMG_FILTER_MODEvalues RADV programs). Measured on RDNA2 (gfx1035), not on the console: only texels of non-zero weight are reduced, and the weight is taken after rounding to the 8-bit subtexel grid (a sample within 1/512 texel of a centre reduces that texel alone); a driver with othersubTexelPrecisionBitsreduces a different set there. Gathers ignore the mode. -
Min/max S# (libSceAgcDriver, shader recompiler) - throws with anisotropy, a linear mip filter, depth or color-texture compare, or bilinear filtering of an image the recompiler point-samples (sint, converted, depth-bits).
-
FORCE_DEGAMMA (libSceAgcDriver) - an S# that forces sRGB decoding adds nothing to an sRGB texture, as in shadPS4 (PS4). Measured on RDNA2 (gfx1035), not on the console:
8,8_8and8_8_8_8sRGB textures sample bit for bit the same with and without the bit (point and bilinear; BC formats not measured). Other textures throw; on the same hardware their UNORM8,8_8and8_8_8_8forms sample bit for bit as the sRGB format (decoded before filtering). -
Tessellation factor ring (libSceAgcDriver) -
sceAgcDriverSetTFRingrecords the ring andsceAgcDriverGetTFRingreports it. Before a title sets one, it reports the console's default, 0xFF0000000 and 128 KiB, as measured in PS5_Vulkan's hardware findings. Nothing is written to the recorded ring: tessellated draws run as Vulkan tessellation stages, which keep their factors on the host, so a title that reads tessellation factors from the ring finds none. A null base or a zero size throws; ps5-opengl's AGC runtime callssceAgcDriverSetTFRing(0, 0)in its cleanup, and what that does on the console is unknown. -
Raw
buffer_load_dwordx2is one 64-bit access on the hardware (with or without glc), so it never sees half of abuffer_atomic_swap_x2. Only a glc load that is 8-byte aligned and in bounds, in a program that has the 64-bit storage view (it uses 64-bit buffer atomics), is read with one 64-bit atomic load; every other dwordx2 load is two dword loads and can tear against a concurrent 64-bit write: loads without glc, and loads in a program without 64-bit buffer atomics while another shader writes the pair withswap_x2. -
Buffer loads without GLC or DLC (shader recompiler) are not coherent in a program that has GLC or DLC buffer accesses and no
buffer_gl0_inv,buffer_gl1_inv,s_gl1_invors_dcache_inv: only its GLC and DLC loads, stores and atomics use theCoherentbuffer view, so a plain load can return a value cached before another work-group's write. This follows the LLVM AMDGPU memory model for GFX10, in which a load-acquire is a GLC DLC load followed bybuffer_gl1_invandbuffer_gl0_inv; it is not measured on the console or on RDNA hardware. -
DS src2 operations (
ds_*_src2_*, GFX10.1 only) readDS[B], withB = A + 4 * sext(offset1[6:0]:offset0), and then updateDS[A]with the matching 32-bit atomic, so the read ofBis not atomic with the update ofA. The form that takes the offset from the address (offset1[7]set), the 64-bit forms and GDS throw: whether the LDS address keepsA[31:17]in that form, and whether the 64-bit forms scale the offset by 4 or 8, is not documented.ds_min_src2_f32,ds_max_src2_f32andds_add_src2_f32throw: on RDNA2 (gfx1035, the oracle's hardware, which has no src2 opcodes)ds_min_f32,ds_max_f32andds_add_f32ignoreIEEE_MODEbut depend on whether f32 denormals are flushed (28, 28 and 12 of 196 special rows differ), and that is not modelled for LDS float atomics yet (#981). -
wcsrtombs_s (libc) follows the console's
libc.prx, but a runtime-constraint violation only returns its error: the default handler there writes the message and a newline tostderrbefore returning, which is not done here. Conversion uses the C locale ofwcrtomb(MB_CUR_MAX1), so the path where a multibyte character does not fit the remaining space is not reached -
The narrow printf family (libc) converts 16-bit guest wide arguments to UTF-8 on both platforms, independently of the host locale. It does not use the guest's single-byte
wcrtomb; the console's treatment of invalid UTF-16 and locale-specific encoding remains unverified. Linux retains host formatting for formats without wide arguments, so a narrow%pthere still follows the host (glibc prints a null pointer as(nil), where FreeBSD prints0x0);%mand argument positions above 99 (FreeBSD'sNL_ARGMAX) throw when a format requires the guest formatter -
collate::_Getcat (libc) builds the facet for the C locale only and throws for any other locale name. The console's
libc.prxstores pointers to its collation state tables at offsets 0x10 and 0x18 of the facet; ours leaves them null, as only the facet's own functions read them.do_transformthrows for input with embedded null characters, which the console drops depending on the output buffer size, and for results of 4095 characters or more, whose string storage uses the guest's over-aligned large allocation. -
The scanf family (libc) hands
%ito glibc on Linux, which since 2.38 reads the C230b/0Bbinary prefix when the library is built as GNU C++:sscanf("0b101", "%i", &value)stores 5 where C17 stores 0 and stops at theb. The strtol family stops at the prefix as C17 does -
The scanf family (libc) on Windows returns 0, as C17 and FreeBSD do, when input fails after only suppressed conversions have completed (
sscanf("12", "%*d%d", &value)). Linux hands the format to glibc, which returnsEOFthere. On Windows the host stops a%x,%X,%ior%pafter thexof a0xthat no hex digit follows (or that the width cuts off), and a float conversion (%e,%f,%g,%a) after theeof an exponent with no digits (1e), where C17 and FreeBSD stop before thexor thee -
socketpair (libkernel) - the pair is the host's
AF_UNIXpair on Linux and, on Windows, a loopback TCP connection forSOCK_STREAMor two connected UDP sockets forSOCK_DGRAM;SOCK_SEQPACKETthrows on Windows. A datagram sent to a full receiver getsENOBUFSon the console, waits or getsEAGAINon Linux and is dropped on Windows, and on Windows a datagramrecvafter the peer closed reportsECONNRESETinstead of the console'sENOTCONN, and a streamsendafter the peer closed reportsECONNABORTEDinstead of the console'sEPIPE.readandwriteon a pair end go to the host like on every guest socket.getpeernameon a pair end succeeds after the peer closed, where the console returnsENOTCONN, andconnect,bindandsendtowith an address on a pair end report an address-family error instead of the console'sEISCONN. On Windowspollon a stream end reportsPOLLHUPwithoutPOLLINafter the peer'sshutdown(SHUT_WR)orclose, where the console reportsPOLLIN, withPOLLHUPonly afterclose -
UDP recv/recvfrom and sceNetRecv/sceNetRecvfrom translate Windows WSAEMSGSIZE into the copied byte count for datagram sockets, including MSG_PEEK, and retain the sender address. This follows FreeBSD 11.4 recv(2) and Winsock's documented truncated-datagram behavior; console behavior and existing title impact are unverified.
-
read, write and vector I/O (libkernel) on a guest socket use
recvandsendwithout flags;sceKernelReadvandsceKernelWritevgather or scatter through one socket operation, preserving stream short reads and datagram boundaries. The positionedpread,pwrite,preadvandpwritevforms, and theirsceKernelforms, returnESPIPEfor an open guest socket andEBADFfor a closed one. Guest socket descriptors start at0x10000000and are allocated upward, so the descriptor range selects the guest socket table or the host descriptor table.EPIPEfrom a write raises the host'sSIGPIPEon Linux, which the guest can neither ignore nor suppress:signal(SIGPIPE, SIG_IGN)andsigactionrecord the disposition, as they do for every number from 1 to 128, but only the six signals with host equivalents (2, 4, 6, 8, 11 and 15) take effect on the host or are delivered, so the hostSIGPIPEis not stopped;SO_NOSIGPIPEis not an option here, and raises nothing on Windows; awritelonger thanINT_MAXbytes isEMSGSIZEwhere the console sends it. AIO on a guest socket still goes to the host, which has no such descriptor -
poll (libkernel) waits only on guest sockets, through
WSAPollon Windows andpollon Linux; thepollfdlayout and flag values are FreeBSD's. A descriptor below the socket range (files, pipes, stdio) throws, as do event bits other thanPOLLIN,POLLPRI,POLLOUT,POLLRDNORM,POLLRDBANDandPOLLWRBAND(thePOLLERR,POLLHUPandPOLLNVALbits are ignored inevents),POLLPRIon Windows, whichWSAPollrejects, and an infinite timeout with no socket to wait on. A closed socket descriptor reportsPOLLNVAL; the console's limit on the descriptor count is unknown and not checked -
Socket error numbers (libkernel) - a host socket error becomes the FreeBSD 11
errno.hnumber of the same name; the numbers are not checked on the console. WinsockWSAESHUTDOWNbecomesEPIPE, as a send aftershutdowndoes on FreeBSD, and a host error with no FreeBSD socket counterpart becomesEIO. A nonblockingconnectin progress reportsEINPROGRESSon Linux butEAGAINon Windows (WSAEWOULDBLOCK), where FreeBSD reportsEINPROGRESS. On Windows a refused nonblockingconnectis never reported (SO_ERRORis unsupported), so a repeated one keeps reportingEALREADYwhere FreeBSD reportsECONNREFUSED. A receive aftershutdown(SHUT_RD)reportsEPIPEon Windows where FreeBSD returns 0 -
msync (libkernel) follows FreeBSD 11's
kern_msyncandvm_map_sync, not measured on the console: the address is rounded down to the page, a range that wraps isEINVAL, as isMS_ASYNCwithMS_INVALIDATE, and a range whose start or any page is not mapped (assceKernelVirtualQueryreports it, reservations included) isENOMEM; a page unmapped from inside a larger mapping still counts as mapped there, sincesceKernelVirtualQuerykeeps reporting the whole mapping. The guest has no file mappings, so a successful call writes nothing back.MS_INVALIDATEon a mapped range throws: FreeBSD returnsEBUSYwhen the range holdsmlocked pages, and locked pages are not tracked -
Thread exit destructors (libSceLibcInternal) run when a libkernel thread finishes; on the main or a host thread only
_sceLibcInternalThreadDtorsruns them, asexitdoes, else they are dropped -
sceFontOpenFontSet (libSceFont) opens only the primary file of a system font set. Characters the console takes from the set's other files (Hangul, Thai and Arabic in Japanese and Chinese sets, Arabic in European sets) are reported as unsupported glyphs. The console file names are those of the PS4 firmware; the names of the PS5-only JG2 sets (
0x1A......) are unknown, so they use the SSTJpPro files. When a console file is missing, an openly licensed substitute (Noto Sans, Noto Sans Mono, Noto Sans Thai, Noto Sans CJK) is loaded instead. It is not the system font: its metrics differ, so text width, line height and wrapping differ from the console. System font faces are loaded by FreeType in host memory, not in the font memory the title passes to the library: FreeType needs about 1 MiB per CJK face, which the title's font memory is not sized for. -
sceFontGetCharGlyphMetrics, sceFontGetRenderCharGlyphMetrics (libSceFont) report the vertical metrics the way the FreeType driver reports them for a rendered glyph, not confirmed on a title: FreeType's vertical advance, and for a face without vertical metrics a bearing of half the horizontal advance left of the horizontal bearing and of half the advance left over by the glyph height.
-
Font writing lines (libSceFont) -
sceFontWritingLineWritesOrder,sceFontWritingLineRefersRenderStep,sceFontWritingLineGetRenderMetrics,sceFontWritingLineGetOrderingSpaceandsceFontWritingLineClearfollow the PS4 11.00libSceFont.sprx(firmware module, read from its disassembly and compared call for call on random sequences): runs are linked in visual order by embedding level, the space at each spaced join is summed for the line, steps walk the visual order from the left (form0x12) or from the right (form0x11) and the render metrics grow as steps are consumed. The PS5 library was not measured. Not from that module: form0x10is accepted and treated as left to right and a detail with id0x0FD5is accepted (the PS4 library rejects both); the memory argument ofsceFontCreateWritingLineand the rest of the detail are not read (the PS4 library validates its library object there); an unknown writing form, another detail id, a null line pointer on creation, unknown and null handles (except insceFontWritingLineRefersRenderStep, which returns null for a null line) and a null output ofsceFontWritingLineGetRenderMetricsthrow instead of returning the PS4 error codes, which are not confirmed for the PS5;sceFontDestroyWritingLinewas not compared. Lines are allocated on the host, not in the font memory the title passes to the library: FreeType needs about 1 MiB per CJK face, which the title's font memory is not sized for. -
s_swappc_b64 writes the link pair with the same model as
s_getpc_b64: the guest return addresspc + 4as a byte offset overGetShaderBase. Any other use of the link pair (arithmetic, compare, hash, store) throws, apart from the overwrites and shared links that static scalar calls allow; constant-offset folding over the link is not modeled. The special encodings_swappc_b64with SDST 125 still decodes ass_setpc_b64, which matches the hardware: measured on RDNA2 (gfx1036) in wave32 and wave64, it branches to the source pair and leaves a marker SGPR pair untouched, and with an SGPR destination the link isPC + 4. -
The s_swappc_b64 fetch-shader call at vertex/local/tessellation/mesh entry assumes the called fetch-shader blob ends in
s_setpc_b64to the link pair (the GNM fetch-shader shape shadPS4'sEmitFetchcopies); the blob is not part of the shader program, so its return closes the pairing by assumption and any in-program reader of the link pair throws. Attribute fetches are inlined from the request's parsed fetch-shader plan through the sameGetAttributepath as the embedded fetch analyzer, honoring the buffer resourcedst_sel; an attribute writing more than four registers, or an entry call without a parsed plan, throws. The vertex/instance offset accumulator inside the fetch blob is not replayed for external blobs. -
The scalar aperture sources src_shared_base, src_shared_limit, src_private_base, src_private_limit (core/shader/recompiler) decode to their own operand kinds (scalar source codes 235 to 238, named as in LLVM's
SIRegisterInfo.td), but their value is not modelled: reading one refuses with the source it refused named, because the wave's shared and private aperture bases and limits are unknown. Both the scalar-code read and the raw-operand read refuse; a shader that only carries the value into an address still prepares, one that reads it does not -
VertexBufferReadSize and the vertex staging copy (libSceAgcDriver) - a vertex fetch whose index is at or past the descriptor's
num_recordsno longer throws forOOB_SELECT0 and 1. The copy still spans the whole fetch, but the bytes fromnum_records * strideonward read as zeros, so the out-of-range vertex is(0, 0, 0, 0). Measured withbuffer_load_format_xyzw(idxen) through the hardware oracle on RDNA2 gfx1036 for PPSA01325's word 30x0004dfac(OOB_SELECT0) in #2241: indices 3, 4 and 5 over 3 records each return00000000 00000000 00000000 00000000, W included, unlike VulkanrobustBufferAccess, which returns(0, 0, 0, 1). The zeros come from the record check, not from memory: stored values placed past the records are ignored, and anum_records6 control returns them.RESOURCE_LEVEL1,OOB_SELECT1 and FORMAT 7432_32_32_FLOATgive the same zeros, in wave32 and wave64; gfx1013 (the console) is not measured.OOB_SELECT2 returns the stored values past the records andOOB_SELECT3 comparesnum_recordsagainst the byte offset, both measured on the same setup in #2241; the two keep throwing pastnum_recordshere, since each needs its own rule. Zero-stride descriptors (stride0) keep their separate byte-count check and are not covered here. Each out-of-range fetch is copied alone and outside the draw-snapshot cache, which is neither read nor written for it: a reused snapshot would carry another draw's bytes into the zero region, and a stored zero-padded copy would hand zeros to a later in-range draw at the same address. The valid prefix is still flushed for GPU writes before it is read. -
sceImeKeyboardGetResourceId (libSceIme) reports that no USB keyboard is connected (
0x80bc0004, as shadPS4 does) because IME keyboard events are not delivered to the handler, although libSceKeyboard exposes the host keyboard -
Player review dialog (libSceCdlgPlayerReview) shows nothing:
scePlayerReviewDialogOpenfinishes at once and the result reports that the user canceled, assceWebBrowserDialogOpendoes -
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.
-
Running application ID (libSceSystemService) -
sceSystemServiceGetAppIdOfRunningBigAppreports 1 as the running title's app ID. The value is AnyPS5's own: the console's shell assigns app IDs and their values are not known here, so other calls that take an app ID must use the same one.sceSystemServiceKillAppwith that ID and the arguments -1, 0 and 0, which SwanStationPS5 passes to close itself and ps5-payload-dev's hbldr passes to close the running game, ends the title as its ownexit(0)would: the guest's shutdown andatexithandlers run and the process exits with status 0. On the console the call returns and the shell then ends the title, and whether those handlers run there is unknown; here there is no shell, so the call does not return. Another app ID or other arguments throw. -
sceNpCheckNpAvailability (libSceNpManager) - the
(req_id, online_id)signature and the errors follow shadPS4 with no user signed in to PSN: a null online id isSCE_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 -
Temporary app-content storage tracks one
/temp0mount, preserves its files on unmount, and rejects new path resolutions until remount. Mount, format, space-query and unmount errors follow fpPS4; the pointer ABI is also declared by SharpProspero. Existing open host descriptors remain usable after unmount; console behaviour with open files is unverified. Host filesystem failures still throw. -
Guest path resolution falls back to ASCII case-insensitive component lookup, following shadPS4's host filesystem. PPSA03747 requests
Skyrim.INI,Data/Videoand lowercase archive/plugin names that differ from the dump's filenames. Exact host names take precedence; multiple fallback matches throw instead of selecting an arbitrary file. Existing parent names are resolved when creating a new file, and guest mount aliases use the same ASCII comparison. Results are not cached, so renames and newly created files remain visible. Unicode case folding and PS5 behaviour for case-colliding host entries are unverified; host roots are used as supplied. Explicit native Windows drive and UNC paths bypass guest parent-component validation. -
localtime, mktime (libc) on Windows convert through the CRT's
localtime_sandmktime, which accept about 1970 to January 3001 UTC and apply the CRT's daylight-saving rule; outside that rangelocaltimereturns null andmktimereturns -1, where the console converts.gmtimeconverts every time whose year fits aninton both hosts. -
strftime (libc) expands FreeBSD's
%k,%l,%s,%vand%+itself, ignoring a leadingEorOas FreeBSD does, and passes every other conversion to the host'sstrftime. On Windows the conversions the CRT lacks (%Pand the%-,%_and%0padding flags) still produce nothing, and the padding flags are not supported on the five new conversions at all (%-k,%_kand%0kgo to the host), an unknown conversion, a doubledEorOmodifier (%EE) or a trailing lone%returns 0 where FreeBSD prints%and the character, and a standalone%zor%Zuses the host's zone instead of the broken-down time'stm_zone.%sfollows FreeBSD 9 and 11 and is the local-timemktimeof the broken-down time (current FreeBSD usestm_gmtoff), which is -1 on Windows outside the range above.%+is the C locale's%a %b %e %H:%M:%S %Z %Ywith%Ztaken fromtm_zone, or fromtzname[tm_isdst != 0]when it is null. -
LINE_STIPPLE_TEX (recompiler) reads as 0: line stipple is not emulated. RADV enables the input only as the required pixel input of a shader that reads no interpolants, because it initializes the fewest VGPRs (Mesa
radv_compute_spi_ps_input), and never reads it -
Draw snapshot buffer descriptors rewrite each affected array from element zero, preserving unchanged descriptors. MoltenVK 1.4.2 writes auxiliary buffer lengths at index
iinstead ofstart + ifor partial array updates (MVKDescriptorSet.mm, BufferAuxSize). Per-element writes therefore let one buffer length replace another even when Vulkan buffer handles and ranges are correct. -
Static scalar calls (
s_call_b64ands_swappc_b64) require an ordinary even-aligned SGPR link pair (s0:s1 through s104:s105) and a laters_setpc_b64return reading that exact pair. A pair serves one call, or several calls whose regions are disjoint, each closed by the first return reading the pair after its target. Outside every region of its calls the pair may only be overwritten whole, bys_mov_b32,s_mov_b64, an SOP2 result or a scalar load, as the caller of a user-data callee does before each call. Regions must nest or be disjoint; recursion, other shared links, escaping link values (including overlapping tuples and resource descriptors), invalid targets, interleaved regions, cross-region branches or fall-through, relative SGPR reads and dynamics_setpc_b64in a program with calls throw. The analysis checks all decoded instructions, including unreachable code. Arbitrary indirect calls and general call frames are not implemented. -
Relative vector addressing (
v_movrels_b32,v_movreld_b32,v_movrelsd_b32,v_movrelsd_2_b32,v_swaprel_b32) keeps every vector register from the lowest base register the program addresses relatively up to the last register the program names in a zero-initialised function-scope array per invocation (LoadVectorWindow/StoreVectorWindow, one element per register), so an indexed access is one load or store instead of a compare-and-select chain over the window; the host compiler decides whether that array stays in registers or spills to scratch, which is not measured. A register in the window the program never wrote reads 0, as an unwritten SSA register does; the console's value is undefined. M0 is unsigned: an index at or past the window readsv0and drops its write, andv_swaprel_b32writes neither side when either is out of range, as measured on RDNA2 (gfx1035,agc_driver_relative_indexing). The window ends at the last register the program names rather than at the shader's VGPR allocation, which the recompiler does not receive, so a relative write past the named registers but inside the allocation is dropped where the hardware keeps it for a later relative read. Killzone: Liberation's PSP vertex program (PPSA11142, 3176 ISA words, 104 relative accesses over 154 registers) went from 649,515 to 392,333 SPIR-V words with this. -
User-data callees (libSceAgcDriver) - a compute shader's
s_swappc_b64whose source pair is a user-data pair, or a copy of one made withs_mov_b32ors_mov_b64in the same block, calls the code at the address that user data holds. At dispatch the callee is read from guest memory up to itss_setpc_b64on the link pair, one copy of it is appended per call after the caller's last instruction, and the call is rewritten tos_call_b64to that copy. The words after the caller's last instruction are dropped; in the shaders seen they are metadata, and a caller that reads its program counter, which could address them, throws. A copy runs at another program counter than the callee, so a callee that reads its program counter, makes a call, ends the program, jumps through another pair, returns before code it branches to, spans more than 64 KiB or is not readable throws. Callees are read again whenever a dispatch misses the dispatch cache; a dispatch that hits it reuses the linked program, so a title that rewrote a callee in place at the same address would keep running the old code. -
DB_RENDER_CONTROL resummarize draws (libSceAgcDriver) - HTILE is not modeled, so a RESUMMARIZE_ENABLE draw without depth or stencil tests and without color writes changes no modeled state and draws nothing; any other resummarize, copy or decompress draw throws
-
s_call_b64 saves
PC + 4overGetShaderBaseand branches toPC + 4 + signext(SIMM16) * 4, following AMD RDNA2 ISA sections 3.6.3, 12.2 and 12.3. Forward callees afters_endpgmare decoded. Measured on RDNA2 (gfx1036) in wave32 and wave64 with SIMM16 = 3: the link pair receivesPC + 4, the branch goes toPC + 4 + signext(SIMM16) * 4, ands_setpc_b64of the link returns to the instruction after the call. Execution on the PS5 (gfx1013) and title compatibility for these bounded scalar calls remain unverified;s_rfe_b64still throws in translation. -
sceVideodec2CreateDecoder (libSceVideodec2) decodes HEVC (codec type 974921) and VP9 (2382845) through FFmpeg, besides H.264. The tags come from SharpProspero's
Videodec2CodecTypeand EVO-PLAYER-PS5'ssce_videodec2.h, which records them from hardware runs. HEVC input is converted from length-prefixed NAL units to Annex B as for H.264, and VP9 frames are passed through. Output is the same 8-bit NV12 for every codec; a decoder for HEVC Main10 or VP9 Profile 2 is created, but a frame deeper than 8 bits throws, since the console's 10-bit output layout is unknown, andQueryDecoderMemoryInforeports the 8-bit frame size for it.sceVideodec2GetPictureInfoandsceVideodec2GetAvcPictureInfothrow for HEVC and VP9 pictures, which use other layouts (SceVideodec2HevcPictureInfo,SceVideodec2Vp9PictureInfo), andsceVideodec2GetHevcPictureInfoandsceVideodec2GetVp9PictureInfoare not exported -
syslog (libc) writes each message to
stderras[syslog:<priority>] <message>, with a newline added when missing, instead of sending it to the console's system log. Priority and facility handling follow FreeBSD'svsyslog:%mexpands to the guest errno's message, unknown bits are reported (as priority 0x23, since FreeBSD passesLOG_ERR|LOG_CONS|LOG_PERROR|LOG_PIDas the priority) and masked, a missing facility becomesLOG_USER, and errno is preserved.setlogmaskfollows FreeBSD 11: the process-wide mask defaults to 0xff, zero queries it, and nonzero values replace it; masked messages are skipped before formatting, including the unknown-priority diagnostic. The console's mask behaviour is unverified.openlogandcloselogare not implemented, so their identity and options are not applied -
daemon (libc) throws: forking into the background is not supported. PPSA85300 imports it and fails to load without it. VLC 3.0 calls it only when its
daemonoption is set (libvlc.c), and the title starts libVLC with--ignore-configand without--daemon(player.cc) -
sigtimedwait (libkernel) throws: guest signals are delivered when raised and never left pending, so there is nothing to wait for or take. PPSA85300 imports it and fails to load without it. Its only call site is VLC's
vlc_writev(filesystem.c), which polls with a zero timeout to drain aSIGPIPEonly afterwritevfails withEPIPE -
pause, sigwait, sigwaitinfo (libkernel) throw, as
sigtimedwaitdoes: guest signals are never left pending, sosigwaitandsigwaitinfohave nothing to take, andpausewould wait for a handler thatraise,killandpthread_killonly run on the calling thread. PPSA68091, PPSA99169, PPSA99420 and PPSA97358 import them and fail to load without them. PPSA68091 callspauseat one site (0x8F7266), in a loop that waits while a global holds another thread'serrnoaddress. PPSA99169 only stores the address ofpausein a table of symbol addresses (0x30DB1). PPSA99420 callspauseat 0x3BD80F6 and 0x3C9E220,sigwaitat 0x3C9E4C7 andsigwaitinfoat 0x3C9E588. PPSA97358 callssigwaitfrom QEMU'ssigwait_compatthread (compatfd.c), whichqemu_signal_init(main-loop.c) starts forSIGIO,SIGALRMandSIGBUSwhen the main loop is created, so it reaches the throw at start-up, and from the vCPU thread of the dummy accelerator (dummy-cpus.c) -
getsid (libkernel) throws: process sessions are not modelled. PPSA74126 imports it and fails to load without it; the title made no call to it in a 60 s run
-
sigaction (libkernel) records the handler, flags and mask of every signal from 1 to 128 and reports them back, following FreeBSD's
sigaction(EINVALfor other signals, and for a handler onSIGKILLorSIGSTOP);signalrecords its handler withSA_RESTART, as FreeBSD's libc does. Only handlers withoutSA_SIGINFOon the signalssignalalready delivers (SIGINT,SIGILL,SIGABRT,SIGFPE,SIGSEGV,SIGTERM) run, the same waysignalhandlers do; their mask and flags are not applied.SA_SIGINFOhandlers are recorded but never called, since that needs FreeBSD'ssiginfo_tanducontext_t, and neither are the handlers of other signals (SIGBUS,SIGHUP, ...), whether they are set bysigactionor bysignal, which records them too (every number from 1 to 128, withSA_RESTARTand an empty mask replacing whatsigactionstored;SIGKILLandSIGSTOPaccept only the default handler in both calls, as in FreeBSD'skern_sigaction).raiseof anSA_SIGINFOhandler on a signalsignaldelivers throws instead of terminating, andraiseandkillof the other signals still fail withEINVAL, recorded handler or not -
kill (libkernel) follows FreeBSD's
kern_killandkillpg1for the only guest process:EINVALfor signals outside 0 to 128, signal 0 only checks that the target exists, and its own pid, 0 and minus its own pid (the guest is taken to lead its own process group) signal it throughraise, so they shareraise's limits above. Any other pid, and -1, which skips the caller, reportESRCH, soEPERMis never reported -
sceKernelFcntl (libkernel) handles socket descriptors through the POSIX
fcntlexport (F_GETFL,F_SETFLwithO_NONBLOCK) and returns its guest errno asSCE_KERNEL_ERROR_*, the form the othersceKernelfile exports use; the command semantics follow FreeBSD's fcntl, and a closed descriptor returnsSCE_KERNEL_ERROR_EBADF. File descriptors throw: their open flags are not tracked, andF_DUPFD,F_GETFDandF_SETFDare unsupported on all descriptors. The return values and error codes are unverified on a console -
ioctl, _ioctl (libkernel) handle only
FIONBIOandFIONREADon a socket. Any other request on a socket fails withENOTTY, and any request on a file or pipe descriptor fails withEBADF, where FreeBSD answersFIONBIOandFIONREADthere too and fails other requests, termios ones included, withENOTTY. Stremio Plus (PPSA74126) imports_ioctlfor its statically linkedtc*functions, which sendTIOCGETA,TIOCSETA,TIOCSPGRPand the other termios requests -
sendfile (libkernel) follows FreeBSD 11's
sendfilefor a connected stream socket: headers, the file fromoffset(to its end whennbytesis 0) and trailers, the file offset left unchanged,EAGAINwith*sbytesset after a partial send on a non-blocking socket. It reads the file throughsceKernelPreadin 64 KiB blocks and sends each withsend. A socket as the file fails withEINVAL, as on FreeBSD, but any other descriptorsceKernelPreadreads, such as/dev/urandom, is sent where FreeBSD requires a regular file or shared memory, and a file descriptor as the socket fails withEBADF, as forsend, where FreeBSD answersENOTSOCK.flagsare ignored: reads complete before sending, soSF_NODISKIOnever fails withEBUSY, andSF_SYNCreturns once the data is queued on the socket rather than sent. PS5MC (PPSA99420) imports it -
pthread_kill (libkernel) returns the error number like FreeBSD's
pthread_kill:EINVALfor signals outside 0 to 128 andESRCHfor a null thread. Signal 0 reports any other thread handle as existing, without checking that the thread is still alive. A signal to the calling thread goes throughraise, so it sharesraise's limits; a signal to another thread throws, since guest signals are not delivered to a chosen thread -
select (libkernel) validates
tv_usecbut saturates a valid timeout beyond the remainingsteady_clockrange attime_point::max(), so the wait can continue effectively indefinitely. The console's behavior for a valid timeout outside the host clock's range is unknown. -
AJM, APR and NGS2 state is allocated with
newand never freed on purpose: title threads still call into these libraries whilestd::exitruns static destructors, so ordinary statics would be destroyed under them. Keep them leaked;guest_ajm_teardowncovers the AJM case on Unix. -
PPSA07411 imports declared without parameters, signatures unknown, added without an implementation because the title fails to load without them: sceSslCreateConnection, sceSslDeleteConnection, sceSslEnableVerifyOption, sceSslConnect, sceSslRead, sceSslWrite (libSceSsl), four sce::Json::Value members (setElementAccessFailureHandler, setSpecialFloatHandler, setTypeMismatchHandler, operator bool) (libSceJson2), sceConvertKeycodeGetCharacter (libSceConvertKeycode) and sceNpSessionSignalingGetGroupFromSessionId (libSceNpSessionSignaling)
-
Comparison-sampled R32 float and R16 unorm textures (libSceAgcDriver) whose surface a storage image holds are sampled from a D32_SFLOAT or D16_UNORM image that the GPU refills from the storage image whenever its version moves, because Vulkan compares only depth formats. Only surfaces of at least 1 MiB (
APS5_DEPTH_COPY_MIN_KIB) that are not 3D take the copy; smaller ones stay CPU snapshots compared against guest memory. With copies of small surfaces, one title hit an intermittent boot-time crash that was not explained. -
Null vertex buffer V# (libSceAgcDriver) - a V# whose four dwords are all zero is bound to a zeroed vertex buffer of the attribute's size with stride 0, so every component of its attribute reads 0. This follows the V# fields in the AMD RDNA2 ISA (
NUM_RECORDS0,DST_SEL0 selects 0), not measured on hardware. -
Descriptor pool recycling avoids individually freed sets: RADV 26.2.2 initializes its free-set heap with 32 bytes beyond the backing allocation. An allocation-only RX 6600 test reproduces acceptance of a 4,128-byte set in a 4,096-byte pool; the path without individual frees rejects it. Pools reset after their last set is released. A cached set can retain unused slots in an exhausted pool until eviction; peak gameplay pool memory remains unmeasured.
-
sce::Json::InitParameter2 base-object constructor (libSceJson2) - forwards to the complete-object constructor and uses its inferred layout and default field values; constructor equivalence and initialization bytes remain unverified on the console
-
_fstatfs (libkernel) fills the FreeBSD 11
struct statfsof the PS5 payload SDK with the host volume that holds the file: block size, transfer size, total, free and available blocks, maximum name length and the read-only,nosuidandnoexecflags (on Windows only read-only, andf_filesandf_ffreeare 0, as NTFS has no fixed number of files). The filesystem type number and name, mount paths, owner, filesystem id and I/O counters are left 0 or empty, since they would describe a host mount, not a console one. Sockets and pipes returnEINVAL, as FreeBSD'sgetvnodedoes; a Windows descriptor that is neither a file nor a pipe throws. Stremio Plus (PPSA74126) reads the free space before a download and only logs the other fields -
fstatvfs (libSceLibcInternal) converts
_fstatfsto the 88-bytestruct statvfsas FreeBSD 9.2'ssfs2svfsdoes (f_bsizefrom the transfer size,f_frsizefrom the block size,f_favailequal tof_ffree,f_fsid0,ST_RDONLYandST_NOSUIDonly). Differences:f_namemaxis thestatfsvalue, notfpathconf(_PC_NAME_MAX); negativef_bavailandf_ffreewrap to unsigned withoutEOVERFLOW, as the same-width copy in FreeBSD does; inode counts are 0 on Windows, inherited from_fstatfs; a null output returnsEFAULTafter the descriptor is validated, where FreeBSD would fault. Layout and conversion are unverified against the PS5 library (PS5MC importsfstatvfsbut was not run) -
sceVoiceQoSEnd (libSceVoiceQoS) -
0x804E0901(not initialized) before any initialization was measured on a PS5 (firmware 13.60, #1407); ending an initialized library was not, because a validsceVoiceQoSInitnever returns inside a homebrew payload. PPSA14632 calls it at shutdown and PPSA26344 after a nonzerosceVoiceQoSInit. After an initialization it returns 0 and clears the init flag, so the library can be initialized again. Whether the console also ends the libSceVoice instance that itssceVoiceQoSInitstarts (prosper's reading of the module), and what it answers while endpoints exist, is unknown; no endpoint is implemented -
_WStoul, _Iswctype and swscanf_s (libc) -
_WStouliswcstouland throws for a base other than 0 or 2 to 36._Iswctypetakes the class numbers of Dinkumware's xwcc.h (1alnumto 11xdigit, 12blank) and throws for any other value, including the FreeBSD maskswctypereturns; the numbering is not confirmed on the console'slibc.prx.swscanf_sfollows C11 7.29.2.2 and K.3.9.1.5, but reads the size argument asunsigned intlikesscanf_swhere K.3.9.1.5 specifiesrsize_t; the console's width is unverified. A runtime-constraint violation (null buffer, format or receiving pointer) only returnsEOF, and a too small array gets a null first element as insscanf_s. A literal mismatch is a matching failure and a field that is only a prefix, such as0xor1e, does not convert, as C11 requires; FreeBSD'svfwscanfreports an input failure for the first and converts the second. Integers out of range are truncated fromstrtoll/strtoull. It throws for%p,%S,%C, unknown length modifiers, scanset ranges,%nwith suppression or width, and narrow%s,%cor%[input that the C-localewcrtombcannot convert -
sceSharePlayGetCurrentConnectionInfoA (libSceSharePlay) - reports no Share Play session, as the library keeps none: status 0 (DORMANT), mode 0, empty online IDs, account IDs 0 and both user IDs -1 (
SCE_USER_SERVICE_USER_ID_INVALID). A null pointer returnsSCE_SHARE_PLAY_ERROR_INVALID_ARGS(0x810E0001). The 72-byteSceSharePlayConnectionInfoAlayout and the error code follow KytyPS5 and fpPS4, which agree on both; KytyPS5 sets the user IDs to -1 and fpPS4 leaves them 0, and which one the console returns is not verified. KytyPS5 also returnsSCE_SHARE_PLAY_ERROR_NOT_INITIALIZEDbeforesceSharePlayInitialize; this library keeps no initialization state and does not. -
sceAgcCreatePrimState (libSceAgc) - the
ge_user_vgpr_enspecial is passed to the user configuration registers at whatever offset the shader header stores, as the SPRX does according to OpenAGC, which copies all four specials verbatim (KytyPS5 stops on any other offset). PPSA99039, PPSA99505, PPSA99515 and PPSA99997 build their headers by hand with it at 0x25c (GE_USER_VGPR1) instead of 0x262 (GE_USER_VGPR_EN), value 0, and run on the console; it is not moved to 0x262, and the driver reads neither register.ge_cntl,vgt_shader_stages_enand a usedvgt_gs_out_prim_typemust still be at their own offsets, since the driver reads those registers there, so a header that stores one elsewhere throws naming the offset, although by OpenAGC the SPRX would copy it as well -
pthread_spin_init, pthread_spin_destroy, pthread_spin_lock, pthread_spin_trylock, pthread_spin_unlock (libkernel) follow FreeBSD 11.4 libthr
thr_pspinlock.cand the owner checks of itsthr_umtx.h, unverified on the console:EINVALfor a null or destroyed lock and apsharedother than 0 or 1,EBUSYfromtrylockwhile any thread holds it,EPERMfromunlockby a thread that does not hold it.PTHREAD_PROCESS_SHAREDallocates a private lock, as guest code runs in one process. libthr spins forever when the holder locks again; here that call throws -
pthread_cond_reltimedwait_np (libkernel) takes
(cond, mutex, usec), a relative timeout in microseconds, and isscePthreadCondTimedwaitwith POSIX error numbers. FreeBSD 11.4 has no such function; the signature comes only from shadPS4, which registers one function for this NID and forscePthreadCondTimedwait(condvar.cpp). shadPS4 reads a 64-bit count; here it is the 32-bitSceKernelUsecondsof the SCE twin, as forsem_reltimedwait_np. Unverified on the console