Commit Graph
14017 Commits
Author SHA1 Message Date
Gjon Gojcevic 35e3b69a2b feat(libSceShare): report no running share feature in sceShareGetRunningStatus
The host never records or broadcasts, so the first status word is cleared and the call succeeds; a null status is rejected.
2026-10-07 20:21:26 -04:00
Gjon Gojcevic 9e4e3a8976 fix(libSceAgcDriver): do not raise an interrupt for RELEASE_MEM send-data-after-write-confirm
INT_SEL 3 waits for write confirmation before the data write and sends no interrupt; only the other non-zero values raise an end-of-pipe event.
2026-10-07 20:18:20 -04:00
Gjon Gojcevic a988b8b1d0 feat(libSceHmd2): add PS VR2 modules that report the runtime as unavailable
sceHmd2Initialize fails, so titles skip their VR set-up; the other libSceHmd2 and libSceVrTracker2 exports throw.
2026-10-07 19:58:01 -04:00
Gjon Gojcevic e6f4d2c178 fix(libSceVideoOut): ignore the reserved buffer pointers
Titles may leave the reserved pointers of a VideoOutBuffers entry uninitialized, so sceVideoOutRegisterBuffers2 no longer rejects them.
2026-10-07 19:50:12 -04:00
Dextroid17 4930202db6 fix(agc): keep dma-buf import off the NVIDIA proprietary driver
The dma-buf import probe corrupts the device on the NVIDIA proprietary Linux
driver: the import itself succeeds, the allocation right after it fails
(vkAllocateMemory, VK_ERROR_OUT_OF_DEVICE_MEMORY), and every later allocation on
that device fails with it. The probe runs while each device is set up, so every
GPU execution test on that driver fails.

Measured on an RTX 3080 Ti, driver 615.71.09, main at df16c4c2, ctest -j 16:

- without this change: 84 of 408 tests fail, all 84 of them agc_driver
  execution tests (84 of 166);
- APS5_WRITE_WATCH_IMPORTS=watch, which skips both probes but leaves
  context.dmaBufImport set: 408 of 408 pass, which places the probe, not the
  shared-backing imports, at the failure.

dma-buf import is now off on VK_DRIVER_ID_NVIDIA_PROPRIETARY, which stops the
probe and 815d2747's imports together. No test provides shared backing, so those
imports are not exercised here; they are left off rather than assumed to work on
this driver. The Recorder test device takes the same decision, so a developer
build behaves like the shipped one.

Tested: Linux (CachyOS, GCC, Release, BUILD_TESTING=ON), full suite 408 of 408
with the change, 324 of 408 without it. CI runs on lavapipe, whose driver id is
not NVIDIA, so the new condition does not fire there.
2026-10-07 19:40:56 -04:00
Gjon Gojcevic c95721f701 fix(libkernel): report AMPR completion events with the AMPR filter
AMPR events were registered and raised as EVFILT_USER. Titles that
dispatch their AMPR queue by filter ignore those events, so reads that
complete through WriteKernelEventQueue never finish. Add, delete and
trigger them with EVFILT_AMPR (-25).
2026-10-07 19:37:40 -04:00
TibixDev 1bcc744f80 fix(libc): unlock allocation registry while waiting without a callback
Release the registry mutex while yielding for an outstanding lease even before a GPU pin waiter is registered. This lets the lease holder finish a nested allocation lookup and release its lease instead of deadlocking against an unmap.

Validation: the deterministic concurrent unmap/lookup regression fails at the lease deadline before the fix and passes after it. Graphics and guest-memory CTests pass. Live Skyrim stacks captured this cycle in a compute upload flushing a storage texture.

AI-assisted implementation.
2026-10-08 02:31:14 +03:00
Dextroid17 9fce570e95 fix(relinker): name the second SELF container magic as a SELF input
ElfReader::ReadHeader names 0x1D3D154F as a SELF container, but dumps also
carry a second container magic, 0xEEF51454 (bytes 54 14 f5 ee), which fell
through to "Invalid ELF magic number: 54 14 f5 ee". That message reads as a
corrupt input rather than an encrypted one, so a user cannot tell that
decryption is what stands between them and a relink.

Both magics now report the SELF message. Measured on two retail dumps:
PPSA03671's eboot.bin and libcohtml.Prospero.prx are 54 14 f5 ee; PPSA28997's
eboot and modules are 4f 15 3d 1d.

Tested: Linux (CachyOS, GCC, Release, BUILD_TESTING=ON), relinker rebuilt. The
new case fails on the revert of the reader change with the exact message above
and passes with it; elf_header, elf_offsets, dynamic_segment,
string_table_bounds, guest_needed_modules, guest_module_directories and
linux_load_alignment still pass.
2026-10-07 19:28:04 -04:00
MerijnandClaude Opus 5.5 7f4f887a66 test(kernel): define the unwind fixture's .ehmeta without compiler extensions
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 00:54:43 +02:00
MerijnandClaude Opus 5.5 b86370285b fix(kernel): throw on unsupported unwind tables in sceKernelGetModuleInfoForUnwind
Once an image has .ehmeta, an eh_frame_hdr version other than 1, an
eh_frame_ptr encoding other than absptr or pcrel, a 64-bit record length,
an eh_frame_ptr outside the image or a missing terminator now throw
instead of returning the empty answer. The test queries a fixture DLL
whose .ehmeta it can break, since the unwinder reads the same section.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 00:54:43 +02:00
MerijnandClaude Opus 5.5 e975d9a926 fix(libkernel): report guest unwind tables in sceKernelGetModuleInfoForUnwind
On Windows the call returned no eh_frame_hdr for every address, so a
title's own libc (its libunwind) found no frame information and
terminated on the first C++ exception thrown in guest code. PPSA12544
died that way after its intro cinematic: IL2CPP raised an
AmbiguousMatchException that Unity catches and logs, and the runtime
called terminate instead. For an address in a relinked guest image the
call now returns the PT_GNU_EH_FRAME segment named by .ehmeta, the
eh_frame it points to and its size, and the image as seg0; host images
keep the empty answer.

AI-assisted: yes

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 00:52:14 +02:00
overlordxrz-source f4ef1cd6ec fix(relinker): do not add the F6/F7 TEST immediate to EVEX instructions
The decoder adds the TEST immediate of opcodes F6 and F7 when ModRM.reg
is 0 or 1. The check excluded VEX and two-byte opcodes but not EVEX, so
an EVEX.0F F6 (VPSADBW) whose ModRM.reg is 0 or 1 was given an extra
imm8 and decoded one byte too long. VPSADBW has no immediate (Intel SDM
Vol. 2B, VPSADBW).
2026-10-07 18:51:05 -04:00
TibixDev efe59e0249 test(libc): resolve the library address in the TLS destructor test
Use dlsym to avoid identifying the executable PLT entry as the shared-library function in non-PIE builds. Fedora 44 Release guest_force_tls_destructor passes. Written with AI assistance.
2026-10-08 01:39:37 +03:00
TibixDev 97f16be342 fix(savedata): keep progress dialogs running until closed
Opening a save progress dialog immediately reported FINISHED. Skyrim
waited for RUNNING before writing SAVEDATA.DAT and never resumed. Keep
progress-bar mode running through polling and progress updates until
Close, retaining the existing automatic responses for other dialog modes.

Add lifecycle regression coverage for repeated polling, completion,
reopening, result metadata and ordinary selection dialogs. The test
failed on the previous implementation and passes with the fix on Fedora
44 Release. Correcting the live dialog state recovered a blocked Skyrim
save without restarting its session.

Written with AI assistance.
2026-10-08 01:37:34 +03:00
TibixDev 2085f4560d fix(savedata): use 32-byte directory records
The 36-byte SceSaveDataDirName declaration placed every search result
after the first at the wrong address and could overrun guest arrays.
Skyrim read an empty directory name for its second save and aborted
when mounting it. Use the 32-byte layout also used by the native dialog,
KytyPS5 src/libs/libSaveData.cpp and fpPS4 ps4_libscesavedata.pas.

Add a regression using two maximum-length names, a guest buffer guard,
and mounts of both returned records. It detects the previous overrun.
Fedora 44 Release search, dialog, delete and PS4-save tests pass. Skyrim
now mounts and reads the second save instead of rejecting its name.

Written with AI assistance.
2026-10-08 01:34:20 +03:00
JAB-devandClaude Opus 5.5 7f4ed6cedc style(audioout): remove the comment in queueAudio
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 00:32:05 +02:00
Ethan Barr e41050f71c fix(savedata): reject deleting mounted native saves 2026-10-07 15:13:43 -07:00
hugodearaujoandClaude Opus 5.5 a156104cba fix(rtc): parse RFC 2822, RFC 850 and asctime text like the console
Measured on a PS5 (firmware 13.60) through dlopen of libSceRtc.sprx.
The weekday is required in any case or length, month names may be
full, RFC 2822 and RFC 850 share one lenient grammar with 2-digit years
split at 50, and the asctime zone is ignored. Zones come from a name
table, a military letter, or +HHMM without a range check. Text the
console rejects returns a parse error with the tick untouched, and an
invalid calendar date returns 0 with only the offset applied to the
tick, as the console does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 19:08:10 -03:00
hugodearaujoandClaude Opus 5.5 32dd014efe fix(rtc): parse ISO text in sceRtcParseDateTime by the RFC 3339 rules
On a PS5 (firmware 13.60) every input that starts with a digit gets the
same result and tick from sceRtcParseDateTime as from
sceRtcParseRFC3339, except that leading spaces and tabs are skipped
first. A string without a zone, or with a space instead of T, is a
parse error rather than UTC.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 19:04:17 -03:00
hugodearaujoandClaude Opus 5.5 fcfe9b56a3 fix(rtc): match sceRtcParseRFC3339 to the console
Measured on a PS5 (firmware 13.60) through dlopen of libSceRtc.sprx:
an empty fraction is accepted, any digits past the sixth are dropped,
text after the zone is ignored, the offset is applied without a range
check, and a 60th second returns 0 with the tick only shifted by the
offset.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 19:04:17 -03:00
Adrià df16c4c256 Merge pull request #940 from CnRJay/feat/image-gather-1d-array
feat(shader): implement 1D array gathers
2026-10-08 00:02:35 +02:00
Adrià c73ee448d5 Merge pull request #903 from Celegans12/fix/agc-dcc-keys-on-first-write
fix(agc): store uncompressed DCC keys at the first write of a fast-cleared image
2026-10-07 23:42:16 +02:00
clem-gbandClaude Opus 5.5 7a33ba272a test(agc): import the released block again from a second device
Without the host import release, a device created after another was
destroyed freed the leftover imports through the destroyed device and
the process crashed (SIGILL on NVIDIA). The teardown test now runs a
second device over the same guest block once the first is gone.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018RNrNcixatky8U4LfC7Ew5
2026-10-07 23:41:49 +02:00
clem-gbandClaude Opus 5.5 c411489c9b fix(agc): release host imports before the device is destroyed
The host import registry is a function-local static that device
teardown never emptied, so every import still registered kept its
VkBuffer and VkDeviceMemory past vkDestroyDevice
(VUID-vkDestroyDevice-device-05137 in 23 execution tests).
ClearHostImports destroys the device's imports and resets the
registry; ~State calls it next to ClearImageMirrors.

Closes #1236

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018RNrNcixatky8U4LfC7Ew5
2026-10-07 23:41:49 +02:00
Adrià 539cbd881d Merge pull request #943 from alfalfa-star/feat/linux-direct-memory-dmabuf-import
feat(agc): import shared direct memory through udmabuf on Linux
2026-10-07 23:38:09 +02:00
Adrià 4c16e5a0d0 Merge pull request #935 from CnRJay/feat/agc-swizzle-modes-d-t-4kb-x
feat(agc): detile the display, T and 4 KiB XOR swizzle modes
2026-10-07 23:27:45 +02:00
Adrià FranchandClaude cfaa336dad test(agc): pin newest-fill order and unfilled keys in pending key reads
Co-Authored-By: Claude <[email protected]>
2026-10-07 23:24:14 +02:00
Celegans12 b8d3060351 fix(agc): store uncompressed DCC keys at the first write of a fast-cleared image
A storage image uploaded under fast-clear DCC keys left the clear code
in guest memory until its write-back, so a title kernel that read the
keys after a draw or dispatch into the image saw the clear code.
PPSA26344's DCC retile kernel copies such keys into its display
buffer's metadata every frame, and the flip presented the clear color.

MarkDirty now stores uncompressed keys the first time an image uploaded
under a clear code is written, unless the title filled the keys with a
clear code since, and the image's uploaded keys become uncompressed.
While they are, Refresh and the fast revalidation read the keys as the
recorded work writing them leaves them: from the bytes pending uniform
fills and driver key stores note (NotePendingFill) when those already
make the keys read uncompressed (bytes that differ, 0xff, or a byte the
format can't use as a clear code), otherwise after waiting for that work.
2026-10-07 23:24:14 +02:00
Karan Shrivastava 954d6f19b1 fix(libSceRtc): answer out-of-range years in sceRtcGetDosTime
A year before 1980 or after 2107 cannot be packed into the DOS time, so
GetDosTime threw. Following the disassembly-derived fpPS4
reimplementation of the PS4 library, it now returns INVALID_YEAR after
writing 0 for an earlier year and 0xff9fbf7d, the largest encodable
time, for a later one. The TechnicalDebt entry now records fpPS4 as the
source for the SetDosTime year decode as well.
2026-10-07 17:18:42 -04:00
Adrià FranchandClaude c572650575 test(libkernel): cover a sub-page shared backing offset and a gap after a direct mapping
Co-Authored-By: Claude <[email protected]>
2026-10-07 23:16:22 +02:00
Adrià FranchandClaude 0ed9059ff8 test(agc): enable dma-buf imports in the recorder test device
Co-Authored-By: Claude <[email protected]>
2026-10-07 23:14:53 +02:00
ChadandClaude Opus 5.5 b950ecd7e4 docs(agc): keep the swizzle equation table header as on main
The conventions check rejects changed code comments without a
TechnicalDebt change; the header line only listed the new modes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 16:11:05 -05:00
Claude ace10fdba3 feat(agc): detile the display, T and 4 KiB XOR swizzle modes
Textures in SW_256B_D, SW_4KB_D, SW_64KB_D, SW_64KB_S_T, SW_64KB_D_T,
SW_4KB_S_X and SW_4KB_D_X (tile modes 2, 6, 10, 17, 18, 21 and 22)
threw while their T# was decoded. They are detiled with address
equations generated from AMD addrlib's GFX10 swizzle patterns for the
same 16-pipe non-RB+ configuration as the 64 KiB XOR table, and share
the block shape and mip tail placement of the standard mode of their
block size. The pipe/bank XOR base check of the XOR and T modes now
uses the block size.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 16:11:05 -05:00
alfalfa-starandClaude Opus 5.5 00e6d078cb fix(agc): keep dma-buf imports write-watched when they leave write protection intact
The import write-watch probe imports private anonymous scratch pages
through VK_EXT_external_memory_host. On amdgpu that path resolves the
pages' write protection (the userptr is revalidated at every submission),
so the probe decides that imported ranges are compared instead of
watched, and every import is unwatched. Shared direct memory is never
imported that way: its imports go through udmabuf, which takes the
memfd's pages without touching the process page tables. Unwatching them
anyway left every surface in direct memory without write stamps: each
storage image refresh re-uploaded the whole surface ("untracked"), and
draw snapshots of imported ranges could never be reused. On PPSA14632
that was over 800 GiB of uploads in 90 s.

- HostImport records whether it is a dma-buf import, and the import
  decides watch or unwatch after the import by its kind (ImportWatched
  already absorbs the pages the import itself touches).
- A second probe, ProbeDmaBufImportWriteProtection, imports a sealed
  shared memfd scratch range through udmabuf: dma-buf imports stay
  watched when a GPU read of it marks no page written and a CPU store
  after that is still collected. Otherwise, or when the probe fails,
  they are compared like host-pointer imports.
- Both probes also report whether a CPU store after the GPU read was
  collected (ImportProbe::writtenByCpu).
- APS5_WRITE_WATCH_IMPORTS=watch or unwatch overrides both kinds.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 23:09:26 +02:00
alfalfa-starandClaude Opus 5.5 815d274736 feat(agc): import shared direct memory through udmabuf on Linux
On Linux, direct memory is a memfd mapped MAP_SHARED. amdgpu accepts only
private anonymous memory for a host pointer import (libdrm sets
AMDGPU_GEM_USERPTR_ANONONLY), so every import of direct memory failed with
VK_ERROR_INVALID_EXTERNAL_HANDLE and its ranges were copied.

When a host pointer import fails, the range's memfd slice is turned into a
dma-buf through /dev/udmabuf and imported with VK_EXT_external_memory_dma_buf.
The direct memory backing is sealed against shrinking and growing, as
udmabuf requires. libkernel reports the backing of a guest range through
GuestArenaSharedBacking. Without /dev/udmabuf, or past its size limit, the
range is copied as before. APS5_TRACE_HOST_IMPORT now prints the mappings
behind a failed import on Linux too.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 23:09:16 +02:00
ChadandClaude Opus 5.5 f4edc9ae92 fix(recompiler): split image reads whose descriptor is a web of SRT Phis
SplitDescriptorPhi (#414) handles a T# or S# that is a Phi of SRT reads in
one block. A descriptor picked inside a loop through a jump table reaches
the read as a chain of Phis rooted at the loop header, so the plan threw
"GetImageResource dword 0 is not a valid runtime value".

When the one-block split does not apply, walk the descriptor dwords
together through the Phi web, give each distinct SRT descriptor an arm,
build a U32 selector Phi web carrying the arm index, and select between one
copy of the read per arm. Paths whose dwords hold a program-counter, EXEC
or ballot value fold onto the first arm (listed in TechnicalDebt); any
other descriptor that cannot be recomputed still throws.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 16:07:43 -05:00
Scott SchusterandClaude Opus 5.5 1dca7b4f40 perf(recompiler): load the written-page slot before the CAS
note_bda_write ran a device-scope compare-exchange on every probe, also
when the slot already held the page. The table lives in host-visible
memory, so each BDA store paid an atomic across PCIe, and nearly every
store hits a page an earlier store noted. Load the slot first and only
compare-exchange when it does not hold the page. The slots probed, the
pages recorded and the overflow report are unchanged.

DOOM (PPSA99666) presents through a compute kernel that stores about two
million pixels through raw pointers per frame: 248 ms per dispatch
before, 8.1 ms after, on an RTX 5070 Ti.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 16:07:13 -05:00
Claude 495aa94ec4 feat(shader): implement 1D array gathers
image_gather4_lz(_o) on a 1D array view threw. The 1D gather emulation
now takes the width from the array view's size, keeps the layer
coordinate and samples both texel centres of that layer, so 1D array
gathers return the same footprint as 1D ones.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 23:01:09 +02:00
Adrià 6c48acecb3 Merge pull request #285 from SP4C3B4R-8/feat/gds-guest-memory
feat(libSceAgcDriver): back the global data share with driver-owned guest memory
2026-10-07 23:00:32 +02:00
Adrià 2b9cd26dbe Merge pull request #933 from CnRJay/feat/agc-3d-xor-swizzle
feat(agc): detile 3D textures in SW_64KB_Z_X and SW_64KB_S_X
2026-10-07 22:53:31 +02:00
popcoder565 2e60f5585e refactor(recompiler): keep the BDA byte write helper beside the store path
The declaration, the state field and the definition of write_bda_bytes now sit next to EmitBdaStore and the other BDA write functions instead of next to the dword read functions, which #1267 extends at the same lines. No change to the emitted code.
2026-10-07 16:49:06 -04:00
Adrià 400ba7f5ec Merge pull request #924 from Adin-bima/feat/np-get-np-id
feat(libSceNpManager): implement sceNpGetNpId
2026-10-07 22:48:19 +02:00
Adrià 629724f103 Merge pull request #931 from CnRJay/feat/agc-1d-array-textures
feat(agc): implement 1D array textures
2026-10-07 22:43:42 +02:00
Celegans12 9af8e9e9f6 fix(agc): bound the upload buffers that recorder batches keep alive
A sampled texture upload keeps its staging, tiled and linear buffers
until the batch that recorded it completes. A draw whose image table
uploads thousands of textures records them all into one open batch,
so in PPSA26344 6.6 GiB of device buffers were live when the next
texture allocation failed with VK_ERROR_OUT_OF_DEVICE_MEMORY.

Recorder::Keep now takes the bytes an object holds, and the sampled
upload and the storage upload and write-back scratch paths pass theirs.
Before each sampled or storage texture lookup, BoundKeptBytes submits
the open batch once it keeps 512 MiB. While the batches in flight and
those a sync or reap of this hold already finished keep more than twice
that, it destroys the finished ones' objects, then waits for the oldest
in flight and releases its objects at once instead of at the unlock.
agc_recorder_kept_bytes checks these bounds on a mock device.
2026-10-07 22:37:12 +02:00
Celegans12 14b4edda8d fix(agc): allocate oversized descriptor sets from a dedicated pool
DescriptorCache::Allocate returned no set when a set needed more
descriptors of one type than a chain pool holds (4,096 storage
buffers, 1,024 sampled or storage images, 512 samplers). A build's
own set then fell back to a pool of its own, but PrepareDrawBindings
has no fallback and threw "draw snapshot descriptor allocation
failed", so a recorded draw with such a set and a snapshotted input
was skipped.

Such a set now gets a pool sized to it (maxSets 1, no
FREE_DESCRIPTOR_SET_BIT), which Free destroys. Every set's count of
each type is first checked against the device's maxDescriptorSet*
limit; other descriptor types throw. The [descriptors] profile line
counts the dedicated pools.
2026-10-07 22:37:10 +02:00
Adrià 2cc5735d30 Merge pull request #913 from adriadam10/feat/agc-submit-multi-acbs
feat(libSceAgcDriver): implement sceAgcDriverSubmitMultiAcbs
2026-10-07 22:29:47 +02:00
Adrià fb0d627ff6 Merge pull request #839 from merwie/fix/audioout2-read-grain-at-playback
fix(audioout2): read grains at the next push and play them behind a cushion
2026-10-07 22:29:12 +02:00
Adrià e674a6384d Merge pull request #760 from merwie/feat/kernel-raise-exception-windows
feat(libkernel): deliver sceKernelRaiseException on Windows
2026-10-07 22:27:39 +02:00
Adrià 832247b0a0 Merge pull request #283 from SP4C3B4R-8/fix/fiber-windows-stack
fix(libSceFiber): pin fiber contexts writable under write tracking on Windows
2026-10-07 22:25:25 +02:00
Dean 43b01023e6 Merge pull request #1084 from MathiasDevelopes/claude/mingw-link-flags
build(libs): strip the MinGW static runtime flags once for all libraries
2026-10-08 09:24:20 +13:00