sceUltGetUlthreadRuntimeInfo returned success when workerThreads was null and workerCapacity was nonzero, while rejecting the same null/nonzero-capacity combination on ulthreads with ULT_ERROR_NULL. Reject null workerThreads with nonzero capacity before touching info, and add test coverage checking the error result and that info is left untouched.
sceUltGetQueueInfo reported every blocked queue thread as a waiting popper because both directions incremented one counter. Track the two wait classes in separate fields and fill both query outputs, copy one waiter record per blocked thread, and cover full-queue and empty-queue waits with a new queue-waiters test. sceUltGetUlthreadRuntimeInfo now throws when a caller asks for worker thread handles, since this runtime starts no worker threads, and the debt entry records the remaining limitations.
SSLeay() returns 0x20000000, the value measured on a PS5 with firmware
13.40 and the SSLEAY_VERSION_NUMBER of LibreSSL 2.5.4, which the module
is. The guest_libressl_version test checks it.
CONTRIBUTING.md permits silent stubs only when unblocking a title UI path and when backed by title evidence. Since no title ID evidence demonstrates that a constant no-disc return unblocks a UI path, throw NotImplemented_nid_no_patch from sceDiscIdGet and sceDiscIdGet2 without touching caller memory. Tests assert both calls throw on null and non-null outputs and across flags values while leaving caller buffers untouched, and the debt entry records the unresolved hardware contract.
The previous revision rejected a null output with 0x80D50001 and any nonzero flag with 0x80D50002, but no SDK or console evidence establishes those validation rules, the error codes or their precedence, and the flag argument may be a bitfield. Report SCE_DISC_ID_ERROR_NO_DISC for every pointer and flag value without touching the output, and record the unverified contract in the debt entry. Normalize the new test and CMake file to LF line endings.
The previous revision rejected a null output with 0x80D50001 and any nonzero flag with 0x80D50002, but no SDK or console evidence establishes those validation rules, the error codes or their precedence, and the flag argument may be a bitfield. Report SCE_DISC_ID_ERROR_NO_DISC for every pointer and flag value without touching the output, and record the unverified contract in the debt entry.
DccComparedImportTests' mode 5 forces the write watch on the planes' host imports as a control. On a device whose import probe reports watched pages written at the import or after a GPU read, as RADV on a Radeon 860M does, the watched planes see those writes and the reuse check refuses with the resident-DCC message, so the three compared-import tests failed there in mode 5 alone. Mode 5 now runs only where the probe reports neither, the condition #10138 uses for the forced-watch shadow tests; lavapipe still runs it.
be write-watched at the initial import ("native FMASK contents require
watched guest memory") and at each reuse ("native FMASK sampling requires
watched guest memory"). In Linux comparison mode a host import over the
FMASK unwatches it, so the target is refused one check after the color,
DCC and CMASK ranges that the previous commit accepts.
Treat an FMASK range that a compared host import covers
(ComparedHostImportCovers) as the color and metadata ranges are treated:
keep a copy and its NewestStamp at the initial import, skip it in the
import's UnchangedSinceAll, and at reuse require the stamp and the bytes
to be unchanged, comparing them at most once per collect epoch. An
explicitly unwatched FMASK range is still refused.
Four-sample targets take no FMASK range, so this changes nothing for them.
Refs https://github.com/boykopovar/AnyPS5/issues/9724
Rush 2 Recompiled (PPSA69423) and Wave Race 64 Recompiled (PPSA69424)
stop with "AGC graphics: initial multisampled DCC contents require
watched guest memory"
(https://github.com/boykopovar/AnyPS5/issues/9724). On Linux with
lavapipe, the write-watch probe finds that device accesses to a host
import trip the write watch, so every imported range is compared rather
than watched. A multisampled DCC target whose color, DCC or CMASK range
lies in such an import was then refused at its first draw: importing the
target takes a write generation for each range, and a compared range has
none.
A range that is not watched but lies in a live host import the probe
compares is now copied when the target is imported, and its metadata
again when a whole fill is taken as its fast clear. Each later use
compares the range with that copy, at most once per collect epoch, and
counts any driver or GPU store over its 64 KiB blocks since the copy as
a write, so a guest store of new bytes or any store by the driver
refuses the resident target as a watched range does. A range left
unwatched outside such an import is refused as before.
This covers the Linux comparison mode, not the Windows deferred settle
(BF-150): compared imports on Windows still refuse.
With an NP title id in place, a PS4 Pro (firmware 10.71) answers 0x80551607
from sceNpTrophyRegisterContext through an aborted handle, ahead of the
missing trophy package (0x80551626 through a live handle). The earlier
measurement stopped at the NP title id lookup on both handles.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
On a PS4 Pro (firmware 10.71) sceNpTrophyGetTrophyUnlockState and
sceNpTrophyGetGameIcon answer 0x80551607 through an aborted handle, ahead of
the not-registered check, and aborting the handle again answers 0.
sceNpTrophyAbortHandle now records the abort, the calls that use the handle
answer NP_TROPHY_ERROR_ABORT, and destroying the handle clears it.
sceNpTrophyRegisterContext keeps its answer, as measured without a trophy
package.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Both measured PS4 titles (CUSA04865, CUSA12435) import it. On a PS4 Pro
with firmware 10.71 a live handle answers 0 and an unknown handle
0x80551608 (INVALID_HANDLE); the library has no asynchronous request to
abort, so the call only validates the handle.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Hold() queues a pipeline job that spins on a Gate until it is released,
and captured the Gate by reference. Each Gate lives in a block of
main(), and its destructor only sets the flag. When the block ends
before the job's next poll, the job reads the Gate's stack slot after
the scope is gone. An ANYPS5_ENABLE_ASAN build reports a
stack-use-after-scope in the job (PipelinedDma.cpp:52, the Gate of the
block at line 111), and the test fails.
The Gate now owns its flag through a shared_ptr that the job captures by
value, as the pipelined indirect draw test's blocker does since #9647.
The job can then poll it after the block ends, and releasing the Gate
works as before.
Co-Authored-By: Claude Opus 5.5 <[email protected]>