Commit Graph
12196 Commits
Author SHA1 Message Date
fogydes 477f8a9cb8 fix(relinker): guard PLT compactor against displacement underflow and offset overflow 2026-10-19 12:15:52 +05:30
fogydes f36bdeba2b fix(relinker): guard base relocations against page boundary overflow and deduplicate entries 2026-10-19 12:15:00 +05:30
Yuri Olive 4d6942f1e6 feat(libSceNet): export missing firmware network interfaces 2026-10-19 08:42:01 +02:00
ShinMalphur cdd476fdfc test(libc): cover oversized secure string destinations 2026-10-19 13:11:17 +06:30
ShinMalphur 016f743c64 fix(libc): reject oversized secure string destinations 2026-10-19 13:11:00 +06:30
Adrià 7f596df48d Merge pull request #6550 from orishamir/fix/savedata-memory-journal
fix(libSceSaveData.native): write only the changed bytes of save-data memory
2026-10-19 08:39:54 +02:00
Werner ea58c903b0 fix(relinker): keep the PT_TLS zero fill out of memory when converting to Windows
WindowsTlsBuilder allocated the whole TLS block and thread control block
for .gtls, so a large p_memsz cost that much memory even though only the
p_filesz template is written. Store the template and reserve the rest as
the section's virtual size; the TLS directory still covers the whole
block, which the loader copies from the zeroed image.
2026-10-19 06:39:49 +00:00
Adrià 05b5d192fb Merge pull request #6309 from fogydes/feat/voicechat-firmware-exports
feat(libSceVoiceChat): export missing firmware voice chat interfaces
2026-10-19 08:38:57 +02:00
Adrià fcde2cf95c Merge pull request #6529 from al3w0f205/feat/agcdriver-quadlist-primitive
feat(libSceAgcDriver): support quad-list primitive type
2026-10-19 08:38:11 +02:00
Adrià dc54701e49 Merge pull request #6541 from wachi35676/fix/libc-fopen-random-device
fix(libc): read /dev/random and /dev/urandom through fopen
2026-10-19 08:38:06 +02:00
Adrià 22e59888ce Merge pull request #6467 from fogydes/feat/agc-driver-command-buffer-submit
feat(libSceAgcDriver): implement command buffer submission
2026-10-19 08:37:37 +02:00
Adrià 8b54728061 Merge pull request #6360 from hypermoist/fix/agc-gpu-indirect-dispatch-limit
fix(agc): check GPU-side indirect dispatch group counts against the device limit
2026-10-19 08:37:32 +02:00
Adrià 22410061d5 Merge pull request #6542 from wachi35676/fix/libkernel-windows-shared-file-mmap
feat(libkernel): map regular files with mmap on Windows
2026-10-19 08:37:27 +02:00
Adrià feb74b65c2 Merge pull request #6551 from yash27git/patch/Tessellation-Lowering
feat(shader): read hull inputs at a control point chosen by a select or phi
2026-10-19 08:31:08 +02:00
notaxeltvandCursor 07d9f409a4 fix(libSceNgs2): keep CalcListener basis when front and up are parallel
PPSA15552 passes matching front/up after a listener move; pick a perpendicular up hint instead of throwing so Dead Cells can keep running.

Co-authored-by: Cursor <[email protected]>
2026-10-19 08:29:47 +02:00
MarcZX10 55a3eeb074 fix(agc): retain shader memory region vectors 2026-10-19 06:27:51 +00:00
Luis Gerardo Aguilar 8cf212a9d8 feat(np-tus): add libSceNpTus with offline title user storage
Titles that import libSceNpTus failed to load because the library did
not exist. Title contexts and requests are tracked, arguments are
validated, and every storage operation completes as signed out, matching
how libSceNpManager reports PSN.
2026-10-19 08:26:59 +02:00
MontyMcK b378541e79 fix(libSceHmd2): report the PS VR2 runtime as unavailable again
Since #7323 sceHmd2Initialize succeeds and sceHmd2Open returns a handle,
so PPSA01317 runs its PS VR2 set-up and aborts on
sceHmd2ReprojectionQueryBufferSizeAlign, which is not implemented
(reported in #6350). AnyPS5 has no PS VR2 or PC VR support, so
initialization returns libSceHmd's UNSUPPORTED_FEATURE (0x81110016)
again, as before #7323, and titles skip their VR set-up. sceHmd2Open
then returns NotInitialized. The reprojection size queries stay
unimplemented.

Refs #6350
2026-10-19 19:25:30 +13:00
Adrià b44d0127d8 Merge pull request #6545 from Get-fix/ps4/relinker-init-array-without-size
fix(relinker): treat DT_INIT_ARRAY without DT_INIT_ARRAYSZ as empty
2026-10-19 08:22:06 +02:00
Karan Vora 2907ca6cac fix(agc): take RADV's fill-memory kernel as a buffer fill
RADV initializes and fast-clears DCC keys with its fill_memory compute
kernel, which stores through a global address. Run as an ordinary
dispatch, its stores name no range. The DCC key tracking therefore saw
a key fill only once it had landed in guest memory, which could be
after later writes to the surface had already been recorded.

vkQuake (PPSA99010) hits this on every item pickup:
- the scene renders into a second color buffer;
- RADV's UNDEFINED -> GENERAL barrier fills color buffer 0's keys with
  DCC_CLEAR_0000;
- a screen-effects compute pass writes color buffer 0;
- the UI pass draws on color buffer 0.
The keys landed while the UI pass was being recorded. The refresh took
them for a clear made after the compute pass, dropped its results and
cleared the image to black. For the length of the pickup flash the
scene was black, with only the HUD drawn.

The fill HLE now matches the 16-byte variant of the kernel as a fill of
min(threads * 16, user[4] + 16) bytes. The kernel takes its address in
user[2..3], its largest store offset in user[4] and its value in
user[5]. A key fill through it is handled where it is in the command
stream.
2026-10-19 08:21:36 +02:00
ionut27001andClaude Opus 5.5 ae662c873d fix(libc): parse NaN payloads in strtod as measured on a PS5
In a payload process on a PS5 (firmware 12.70), the strtod and wcstod
of libSceLibcInternal.sprx keep the payload of a NAN(...) sequence,
read as FreeBSD 11's gdtoa hexnan reads it, under the quiet bit and
with the sign. strtof, wcstof, strtold and wcstold return the positive
default quiet NaN whatever the sign and the sequence, and consume a
sequence of letters, digits and underscores up to its closing
parenthesis. Here every NaN lost its payload, and strtof and strtold
kept the sign.

The model reproduces the 64 NaN inputs that p11, p14, p27 and p33
measured, including blanks and other characters inside the parentheses
and unterminated sequences, and the test now pins them. It also pins
two p71 cases measured through strtod: nan(1 2), and "nan( " followed
by NUL and ")". In hexnan, a blank after a payload digit, while a
32-bit word of the payload is still free, starts a blank skip that has
no NUL check, so when only blanks follow up to the terminating NUL the
console reads past it (p71); that case throws here. A blank right after
"nan(" is skipped with a NUL check, and the console stopped at the NUL
there.

AI-assisted: yes

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 09:20:41 +03:00
Adrià 06a750df70 Merge pull request #6293 from fogydes/feat/video-recording-firmware-320-exports
feat(libSceVideoRecordingP): export missing firmware 3.20 video recording interfaces
2026-10-19 08:19:41 +02:00
Jota 5937ef03ef fix(agc): wait for an image another thread is storing before a host read
FlushPending moves the overlapping images from the pending list to the
flushing list and stores them under the GPU mutex. A FlushPending or a
flush hook on another thread for the same range found nothing pending and
returned while the store was still running, so the host read saw guest
memory before the store; the queue-idle store hits this with any host read.

When an overlapping image is being stored and this thread does not hold
the GPU mutex, take it and check again until no overlapping image is left
being stored, and report the range as stored so the hook syncs the
recorded store.

Fixes #7744
2026-10-19 06:18:44 +00:00
Adam Franke 2798e6a6fd fix(libSceSsl): follow the codes and defaults measured on a PS5 (13.40)
Every unverified point of the libSceSsl debt entry was measured on a PS5 on
system software 13.40 with a ps5-payload-dev payload against a TLS 1.2 test
server presenting leaves issued by the test fixture root. The code follows the
console where it differed: initial verify options 0x25 with the date checks
off, bits outside 0x3F rejected, the verify callback called with the context
id and the bitmask of failed checks and re-run from every later call after a
negative return, sceSslRead flags 0 reading until the requested length,
streams that end without close_notify reading as 0, resets reported with the
libSceNet codes, receive timeouts as SSL_ERROR_WANT_POLLIN, a fatal alert
ending the transport, sceSslClose as a repeatable no-op before the handshake,
read and write before connect running the handshake, SSL_ERROR_INVALID_ID for
unknown or deleted handles and terminated contexts, sceSslSetMinSslVersion
accepting 2 to 5, an empty ALPN list rejected, long attribute names from
sceSslGetNameEntryInfo and sceSslGetSerialNumber leaving the caller's length.
The debt entries record the measured values and what stays unmeasured.
2026-10-19 02:12:30 -04:00
Adrià 63e4a63804 Merge pull request #6538 from TheAggie/perf/agc-dma-prefetch-keeps-pipeline
perf(agc): a DMA_DATA prefetch keeps the draw pipeline
2026-10-19 08:11:46 +02:00
fogydes 0f38f0fe58 feat(libSceVoiceChat): export missing firmware voice chat interfaces 2026-10-19 11:39:06 +05:30
Adrià 9817d53cc9 Merge pull request #6345 from hypermoist/feat/libc-exact-math
feat(libc): add exact long double and BSD math exports
2026-10-19 08:06:40 +02:00
JJenkx f085363ef2 fix(agc): reject late profiling output after shutdown 2026-10-19 02:05:16 -04:00
Josip Parlov 278ea58337 test(agc): name the device limitation when the clear-key hand-over test skips 2026-10-19 08:03:03 +02:00
Josip Parlov 15466d7c53 test(agc): skip the clear-key hand-over test when its watched case cannot run 2026-10-19 08:03:03 +02:00
Josip Parlov b176274da1 perf(agc): keep a CPU store over a handed-over unit ahead of the receiving image's write 2026-10-19 08:03:03 +02:00
Josip Parlov 26fecae5b4 test(agc): state the clear-key hand-over fixture's layout 2026-10-19 08:03:03 +02:00
Josip Parlov 92063916d2 perf(agc): hand pending results over to an image whose DCC keys are a clear code
A storage image refreshed over memory where other images still had results
pending stored those results first, then uploaded. When the image's DCC keys
are a clear code its upload is a GPU clear that reads none of that memory, so
those stores were dead for it. Unreal's render graph does this whenever it
hands transient memory to a new texture it fast-clears.

In write-watched memory the results now stay pending. Anything that reads the
memory before the image is written stores them as before. Once the image's own
results cover their 64 KiB units they are dropped, as its write-back stores
every byte of those units; an image written again since keeps its newer
results, and a unit stored after the hand-over no longer counts as a CPU store
against the image's write. The path is chosen from the keys read before any
flush, and only when no flush is needed. APS5_NO_CLEAR_HAND_OVER=1 stores the
results first as before.
2026-10-19 08:03:03 +02:00
Josip Parlov 1208bb5a54 test(agc): expect an unmap inside a host import to keep its larger side 2026-10-19 08:02:13 +02:00
Josip Parlov 2d90ce58a8 test(agc): check a trimmed import whose kept side is unmapped and mapped again
While a trimmed import waits for the next refresh it pins no registered
range, so the guest can unmap its kept side and map new pages at the
same address without waiting for it. The new pages must be imported
again: the GPU has to read their bytes, not the old pages the trimmed
memory still pins.
2026-10-19 08:02:13 +02:00
Josip Parlov 9af0914ff4 test(agc): check trimmed host imports after protects and unmaps inside them
agc_trimmed_import imports 32 MiB of singly mapped direct memory whole
and then cuts it: a 16 KiB page made inaccessible nearer its start or
nearer its end, an unmap of a 2 MiB resident run inside it, an unmap of
its first 2 MiB run, and an unmap of the first 1440 KiB of that run. It
checks that the larger side keeps the import's memory, or, when the
unmap replaced pages of the kept side's run, that it is imported again;
that the smaller side is imported apart from it; and that the GPU reads
the guest's bytes through each import while the write watch collects CPU
stores and reports none nobody made. Each unmapped span is then mapped
again at the same address, and the whole range must be served by a new
import that matches the new pages and the kept side.
2026-10-19 08:02:13 +02:00
Josip Parlov 7357c85999 test(agc): time host re-imports after cuts at the tail and inside the range
The re-import bench only moved the start of the range. It now runs three
patterns, each on a fresh 1126 MiB range: the head or the tail loses GPU
access 1440 KiB at a time, or a 16 KiB page inside the kept side loses
all access (256 MiB in, then 1440 KiB above the one before). For every
cut it prints whether the kept side was trimmed or imported again, the
cut and import times and, for a cut inside, the import of the smaller
side. After each pattern it checks that the kept side still matches the
guest's bytes and write watch. The bench is registered on Windows only,
the one platform it runs on.
2026-10-19 08:02:13 +02:00
Josip Parlov b2a12bac84 fix(agc): hold a released trimmed import through the recorder
releaseTrimmed freed the trimmed import's memory at once when the
calling thread did not hold GpuMutex. It now hands the memory to the
active recorder whenever there is one, as retireImport does for the
imports importRunAt and refreshImports retire, so the memory outlives
the open batch and every batch submitted before it.
2026-10-19 08:02:13 +02:00
Josip Parlov 16473dbbe1 perf(agc): keep the larger side of a host import cut inside its range
A protect or unmap strictly inside a plain host import still retired the
whole import, and the next access imported both sides of the cut again.
The larger side is now kept as a trimmed import, as a cut at the head or
the tail already is, and only the smaller side is imported again. Equal
sides keep the tail.
2026-10-19 08:02:13 +02:00
Josip Parlov 6970fb0b09 test(agc): check that a trimmed host import keeps its write watch and guest bytes 2026-10-19 08:02:13 +02:00
Josip Parlov f9caa09745 perf(agc): keep a host import across a split of its guest range 2026-10-19 08:02:12 +02:00
Josip Parlov 18d2ce913c test(agc): time host re-imports of a range whose start moves 2026-10-19 08:01:59 +02:00
eth-j17andClaude Opus 5.5 ca4303a155 feat(trace): record host, title and per-frame benchmark data
The summary line names the CPU, its thread count, physical memory and,
with param.json, the title ID, name and content version.

APS5_TRACE_BENCH=1 with APS5_TRACE_SUMMARY_EVERY rewrites
aps5-bench-<commit>-<pid>.json.gz at each interval with the time between
every two presents, so reports can be recomputed and checked from raw
frame times. param.json's contentVersion is read when present.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 01:01:13 -05:00
fogydes c3775ea000 feat(libSceAgcDriver): implement command buffer submission 2026-10-19 11:28:13 +05:30
hypermistandClaude Opus 5.5 6b176d98e3 test(agc): exceed the device's own indirect dispatch limit
The over-limit row was a fixed 0xffffffff in X, which is a valid count
on devices that report that X limit (RX 9070 XT). Take the first axis
whose limit is below 0xffffffff and use limit + 1 there; skip when no
count can exceed the limits.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 18:57:39 +13:00
hypermistandClaude Opus 5.5 6a33a080bf Merge upstream main into fix/agc-gpu-indirect-dispatch-limit
recordDispatch now reads its indirect offset through HostImportOffset,
which adds the import's lead. The unchecked path passes that offset to
vkCmdDispatchIndirect; the clamp kernel reads from import.address plus
the guest offset, since import.address already includes the lead.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 18:57:30 +13:00
xdCloudy 753b03811c feat(prx): declare charset and VDECSW exports 2026-10-19 06:57:18 +01:00
xdCloudy 8f21bcbc98 feat(prx): declare notification exports 2026-10-19 06:57:16 +01:00
xdCloudy afc389c1bc feat(prx): declare NetCtlAp exports 2026-10-19 06:57:13 +01:00
Werner 9babdd83fb fix(relinker): merge zero-filled Mach-O segments past the dyld segment limit
Backing only the pages a pointer touches splits a zero-filled run into
one section per backed block. Each becomes a Mach-O segment, and dyld's
bind and rebase opcodes address at most 16 segments, so a module with
pointer slots on many separate zero-filled pages converted on main but
failed with --macos. When the segments would pass that limit, adjacent
sections with the same protection are merged again, smallest gap first.

Reported by jotitadev in the review.
2026-10-19 05:55:26 +00:00