Commit Graph
7981 Commits
Author SHA1 Message Date
Karim Ibrahim ceec3da0a0 fix(libc): share the constraint handler across libc source files
SonyCrt.hpp kept the constraint handler slot in an unnamed namespace,
so every source file that included it had its own slot. A handler
installed with set_constraint_handler_s in WideConversion.cpp was not
the one qsort_s in FileAndHeap.cpp called, and its violations aborted.
The slot and its mutex now have one instance per module, and the
handler type uses the guest calling convention, as the handlers a title
installs and the default handler it gets back are guest functions.
2026-10-16 02:46:25 -04:00
Yunus Shaikh 4ee79e522e perf(agc): remember an evicting import request's budget refusal
At a full host import budget with nothing evictable, a request that may
evict tried again on every use, and each try walked every live import to
add up what could be evicted. In a title's first scene at its 6400 MiB
budget that was 37,627 refusals per present, each one a walk over about
4,400 imports, while the address-based builds kept every import held.

Such a request now remembers its final refusal, the one with no smaller
block left to try. Later requests for the same run, from the same range,
are answered from that memory, still counted as refused and remembered,
until an import is made or retired, the budget or the import window
changes, the run's ranges change, or an import could have become
evictable. An import becomes evictable only once the use count passes
its last use by the 256-use protection, and a held one also needs a
higher build floor, so the walk records the first such use among the
imports it could not evict, held ones apart: the memory survives a new
build while no held import can age out yet. Requests that may not evict
keep their behaviour.
2026-10-16 06:45:27 +00:00
Yunus Shaikh 815b8add6f test(agc): check that a settle read ends the driver's marking of an import
A Windows import under 1 MiB returns to the write watch once its settle
read has completed, though main-queue work submitted before the read may
have used the import first, and an earlier import of the same pages may
not have run its first use yet. On the NVIDIA driver (617.42) neither
marks the pages once the read has completed, so the rewatch needs no wait
for the main queue. The docs said the marking lasts until the import's
first GPU use completes; they now say that a completed GPU use ends it,
the settle read included.

agc_import_settle_first_use submits 4096 copies of a 64 KiB import on
the main queue before its settle read is queued. The import must return
to the write watch while the copies still run, and the driver must mark
none of its pages afterwards.

agc_import_settle_earlier_import records 4096 copies of a 64 KiB window
import, replaces it with the import of its whole 128 KiB range, and
submits the copies only once the range is back in the write watch. The
driver must mark none of the range's pages while they run. A driver that
keeps marking fails either test.
2026-10-15 23:43:07 -07:00
Yunus Shaikh ee406d6179 docs(agc): give the 3070's per-count sample location grids and say why a moved sample mask throws
The device setup logs each sample count's largest grid. On the RTX 3070
Laptop GPU (617.42) it is 2x4 at 2 samples, 2x2 at 4 and 1x2 at 8,
while maxSampleLocationGridSize is 1x1 for every count; the AMD Radeon
iGPU reports 2x2 both ways. So the 3070's 2x patterns take the native
grid, and the stand-in plus the exact path serve its 8-sample patterns
and devices without a grid.

The throw for a uniform partial sample mask that the order moves stays.
The order is fixed at decode, before compilation shows whether the pixel
program writes memory, and falling back would lose exactness on draws
the exact path gets right. The entry now says when the draw throws, what
#6451's stand-in did with it, and what a fix would take.
2026-10-16 06:23:50 +00:00
Yunus Shaikh 7476390517 perf(agc): free an import retired during its settle read after the read
Retiring a Windows import whose settle read was still running waited for
the read's batch under the imports mutex, so lookups on every thread
waited with it. The retired import is now kept with that batch and freed
once the batch has completed. Only a guest unmap of its memory still
waits for the batch, in the pin waiter, which waits for the main queue
there anyway.

The [buffers] profile line counts these retirements and the unmaps that
waited, apart from the imports of 1 MiB or more settled inside their
window, which the old wait counter mixed with the retirement waits.

agc_import_settle_retire replaces a 64 KiB window import with the import
of its whole range, 64 times, right after its settle read was submitted.
No replacement may wait, at least one must find the read running, and
the last import must return to the write watch.
2026-10-15 23:20:30 -07:00
Yunus Shaikh c3f947ef47 docs(agc): say the 3070 draws 2x patterns on its grid and name the depth transitions and the sample mask throw
The debt entry said the RTX 3070 Laptop GPU reports a 1x1 grid for
every count. That is VkPhysicalDeviceSampleLocationsPropertiesEXT; the
device setup reads each count's VkMultisamplePropertiesEXT, which gives
an even grid at 2 samples, so the 3070 draws 2x patterns on its grid.

The entry also gains the transition that ends a pass drawing depth at
custom sample locations, and the throw for a draw with early depth or
stencil tests whose pixel program writes memory when the order moves a
partial sample mask into the pixel shader.
2026-10-16 06:16:00 +00:00
Karim Ibrahim edf4efe360 feat(libc): implement qsort_s
The Quake homebrew's libOSMesa.so.8 imports qsort_s, the only strong
import left unresolved once its symbol names resolve through NIDs.

qsort_s sorts as qsort does, with the context passed as the
comparator's third argument, and returns EINVAL after calling the
constraint handler for the runtime constraint violations of FreeBSD
13's qsort_s. The sort helpers take any comparator so both functions
share the FreeBSD 11 algorithm.
2026-10-16 01:31:40 -04:00
TamaleroandClaude Opus 5.5 ae5046eeb2 feat(libkernel): add sceCoredumpConfigDumpMode as a throwing stub
PPSA16833 imports it from libkernel, and its executable does not load
while no library exports the NID. The signature is unknown, so it throws
if called, like sceCoredumpWriteUserString.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 21:57:24 -07:00
David 0e6ad36fe4 docs(debt): say how mktime converts a time before 1900 on macOS 2026-10-16 08:45:29 +04:00
David 80a9ef9e3b docs(debt): say where NetCtl finds the default route and why GetIfStat throws on macOS 2026-10-16 08:42:35 +04:00
SandstromPLandClaude Opus 5.5 051dac94ee fix(relinker): find the PLT before the code in PS4 modules
FindSceCodeEnd looked for the PLT only after the last function of the
unwind table and failed with "PLT not found after the last unwind
function" otherwise. The libSceFios2.prx and libc.prx that Until Dawn
(CUSA02636) bundles have their PLT at 0xc8, at the start of the text
segment, before the code. In both, the last unwind function is
followed by the module's DT_FINI routine, which has no unwind entry,
and then by read-only data.

When no PLT follows the last unwind function, the search now also looks
before it. A PLT found there must not overlap an unwind function, and
the code extent then ends at the last unwind function, so what follows
it stays out of the scans and the code analysis, including code
without an unwind entry such as the DT_FINI routine of both modules
(recorded in the debt file). A missing PLT now fails with "PLT not
found before or after the unwind functions".

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 09:43:51 +05:30
xXPBSXxandClaude Sonnet 5.5 cfbf714d87 docs(debt): list the unprepared AGC shader types
ShaderRegistry.cpp prepares the registered shader types 0, 1, 2, 4, 6 and 7, skips 5, and logs and leaves every other type unprepared at registration; Hello Neighbor 2, Ad Infinitum and Ghostrunner register type 8.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-16 05:55:24 +02:00
Yunus Shaikh aa2b7ce7ef fix(agc): keep a refused heap's mirror once its range has left the write watch
A heap mirror whose range had left the write watch was dropped and its
range planned again. When the host import budget refused the range, that
plan was a per-build copy, and past APS5_ADDRESS_COPY_MAX_MIB (64 MiB) the
copy stopped the process ("an address-based build copies ... past ..."),
where refreshing the mirror in full would have carried on.

Plan such a range again only when the import path takes it now. A cached
address space whose heap or sparse mirror has left the watch is rebuilt
only if importing the mirror's range succeeds, and the rebuild then finds
that import; otherwise the space is kept and the mirror refreshed in full,
every block counted as written. A build that plans its ranges tries the
import first, so acquireMirror keeps the existing mirror of a range that
reaches it, and a sparse mirror whose pieces are unwatched is refreshed in
full instead of planned again.

SetAddressCopyLimit sets the copy cap in-process, as SetHostImportBudget
sets the budget. The heap and sparse unwatch tests set it below the heap
the old plan would copy: the refused heap's mirror is kept and refreshed in
full (its unwatched block and a watched block the CPU wrote both reach it),
and once the budget holds the heap the next build imports it and releases
the mirror.
2026-10-16 03:55:11 +00:00
xXPBSXxandClaude Sonnet 5.5 905a0dffb2 docs(debt): list the NGS2 custom module id 0x20 of PPSA35169
Trails in the Sky 2nd Chapter creates a custom rack with module id 0x20, which Custom.cpp rejects; the module and its structure are unknown (#4246).

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-16 05:45:49 +02:00
xXPBSXxandClaude Sonnet 5.5 4dc23f9c14 docs(debt): list the unimplemented AJM codec 23 of PPSA21480
Broken Sword - Shadow of the Templars: Reforged stops at AJM decoding codec 23, which is not one of the codec ids known in Ajm.cpp (MP3 0, ATRAC9 1, M4AAC 2, Opus 24).

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-16 05:45:41 +02:00
Kovalev Vladislav caae92c12c fix(agc): read uncompressed FMASK images from guest memory 2026-10-16 09:40:41 +06:00
David e44e828f61 docs(debt): say where fchdir checks search permission
The fchdir entry still said FreeBSD's search-permission check was not
modelled, although it has run on Linux since 0e4d94ce3 and now runs on
every host but Windows.
2026-10-16 07:20:14 +04:00
Dellz36 5338ff0631 docs(build): document Windows Python and Git Bash setup 2026-10-15 23:16:33 -04:00
Nithishvelan M e92484a251 feat(libSceUserService): implement sceUserServiceGetAccessibilityKeyremapEnable and sceUserServiceGetAccessibilityZoom 2026-10-16 08:42:16 +05:30
hypermistandClaude Opus 5.5 20edd079e4 fix(libc): store the sign of gamma in an exported signgam from lgamma
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 16:11:02 +13:00
Nicolas AboschandClaude Opus 5.5 6ce90a7286 perf(libkernel): keep the sleep wake include and debt entry off lines other PRs change
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 23:42:41 -03:00
Yunus Shaikh bc27ba7d07 docs(agc): describe the settle of Windows imports under 1 MiB
ARCHITECTURE.md and the debt entry describe how imports under 1 MiB are
settled without waiting and return to the write watch, which the debt
entry listed as not implemented.
2026-10-15 19:42:17 -07:00
Yunus Shaikh 356d2a9dfa fix(agc): plan a sparse heap again when its mirror's range has left the write watch
A sparse heap mirror, made for a heap with uncommitted pages, is
refreshed from the write watch through its committed pieces. The check
that a reused heap mirror's range is still watched covered the heap
mirrors acquireMirror reuses and the cached space's heap runs, not
sparse ones: once a committed piece left the watch, refreshSparseMirror
threw "a sparse heap mirror's range is no longer write-watched" from
acquireMirror's reuse and from a cache hit's sparse refresh.

refreshSparseMirror now returns false when a piece is no longer
watched. Both callers already take false as not reusable: acquireMirror
makes the mirror again, finds the range unwatched, drops the stale
mirror and leaves the range to a copy, and a cache hit gives up the
cached space.

agc_sparse_heap_mirror_unwatch mirrors a 1 MiB reservation with 256 KiB
committed, takes one committed block off the write watch and stores new
bytes there from the CPU; the next build must not reuse the mirror and
must serve the new bytes. agc_sparse_heap_mirror_unwatch_no_space_cache
runs the same without the address-space cache. Without the fix both
throw. They are registered on Linux; the Windows path uses the guest
arena as the existing sparse heap test does and has not run on Windows.
2026-10-16 01:52:33 +00:00
Nicolas AboschandClaude Opus 5.5 82dd286192 perf(libkernel): end short sleeps when the GPU or a flip completes
A sleep of 1 ms or less returns once the AGC driver sees a GPU batch
complete (a thread waits on the recorder's timeline semaphore), runs a
batch's completion actions, or VideoOut completes a flip. A thread
returns early at most 8 times in a run of back-to-back sleeps; the run
restarts when the thread submits AGC work or did not sleep for the
requested time. APS5_NO_SLEEP_WAKE=1 keeps every sleep in full.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 22:50:57 -03:00
Yuri Olive 630ab4c20b feat(libSceHttp): implement sceHttpUriCopy 2026-10-15 22:46:40 -03:00
JJenkx 522696d1ce fix(agc): retain front-half offchip LDS enable during shader fusion 2026-10-15 21:42:43 -04:00
Yuri Olive b27e4c9710 feat(libScePad): export missing firmware pad interfaces 2026-10-15 19:24:39 -03:00
Adrià 7b20318e89 Merge pull request #5882 from billythemenace2/fix/agc-msaa-target-without-msaa-enable
fix(agc): rasterize a multisampled target without MSAA_ENABLE at the pixel center
2026-10-15 23:58:24 +02:00
Yuri Olive 783da344a7 docs(libSceRtc): list sceRtcInit and sceRtcEnd as silent stubs 2026-10-15 18:56:38 -03:00
Felipe Arce 46d49131e7 feat(libkernel): support EVFILT_READ on the read end of a pipe
kevent threw for any descriptor that is not a guest socket. The read end
of a pipe now gets the descriptor knote, following FreeBSD 11's
filt_piperead: data is the number of buffered bytes and EV_EOF is set
once the write end is closed. GuestSockets::Ready falls back to the new
PipeReadState for a descriptor that is not a socket, and WaitAny waits on
the pipe with ppoll on Linux or in 1 ms WSAPoll slices on Windows, only
when the queue holds a pipe. On Windows the equeue waker now starts
Winsock itself, since a queue can wait on a pipe before any socket exists.
2026-10-15 21:56:19 +00:00
Yuri Olive 51e9e5e825 feat(libSceRtc): implement the remaining firmware exports 2026-10-15 18:54:39 -03:00
Karim Ibrahim 411dc0748f feat(libkernel): set and read IPV6_V6ONLY on a guest socket 2026-10-15 17:48:41 -04:00
MarcZX100 881facc4fa fix(agc): refuse native MSAA index buffer reads 2026-10-15 21:35:59 +00:00
Adrià f35c13fc95 Merge pull request #5833 from Ondra97/codex/fix-windows-vector-io-lock
fix(libkernel): serialize Windows vectored file transfers
2026-10-15 23:15:38 +02:00
Adrià 65262da1e0 Merge pull request #5856 from ErenYeager1836/fix/ime-keyboard-duplicate-open-error
fix(libSceIme): return error codes instead of throwing on duplicate open or close
2026-10-15 23:15:29 +02:00
Yunus Shaikh ac9ccfb89c fix(agc): keep the host import budget off the device report until an import fails
The host heap's VK_EXT_memory_budget report lowered a set
APS5_HOST_IMPORT_MIB of 6400 MiB to 4480 MiB on Resident Evil Village
(PPSA01556), where 6400 MiB runs without a vkAllocateMemory failure, and
85,047 imports were refused. A set APS5_HOST_IMPORT_MIB is now never
lowered by the report, and the default is held to the report only once
an import's vkAllocateMemory has failed. The failure ceiling is
unchanged. The first time the report would lower the budget, a [gpu]
host import budget line prints the heap's reported budget and usage and
the live imports, and the refusal line names where its budget came from.
2026-10-15 21:04:31 +00:00
Adrià f27697f083 Merge pull request #5847 from akkadbakkad89/feat/kevent-ev-flags
feat(libkernel): implement kevent EV_DISABLE, EV_DISPATCH and EV_FORCEONESHOT
2026-10-15 23:01:10 +02:00
Adrià 006388ea7c Merge pull request #5846 from SeifKaroui/fix/avplayer-loop-warning
fix(avplayer): defer loop warnings until frame delivery
2026-10-15 23:01:04 +02:00
Adrià ab88420409 Merge pull request #5845 from pushkarreddyy/feat/libSceAgc-default-cx-state-flat
feat(libSceAgc): implement sceAgcGetDefaultCxStateFlat
2026-10-15 23:00:59 +02:00
Adrià 90dea83b59 Merge pull request #5718 from ErenYeager1836/fix/savedata-dialog-native-state-checks
fix(libSceSaveDataDialog.native): validate dialog state in close, get result and terminate
2026-10-15 23:00:55 +02:00
Adrià 7758abac13 Merge pull request #5841 from simonbronk/feat/line-reads-through-2d-array
fix(shader): read explicit-LOD and level-zero 2D-array samples through 1D T#s as measured
2026-10-15 23:00:50 +02:00
Adrià 8b99f0177c Merge pull request #5848 from wachi35676/refactor/libSceAgc-name-interpolant-mapping-10000
refactor(agc): name dbOlWdppb4o and vieBRwlh1Lw the _10000 interpolant mappings
2026-10-15 23:00:46 +02:00
Adrià 7663bc63bb Merge pull request #5092 from MrMha/fix/scripting-heap-694
feat(libc): provide the runtime scripting allocator hooks
2026-10-15 22:58:23 +02:00
Adrià c10aa036d2 Merge pull request #5821 from SandstromPL/fix/agc-sampler-aniso-minmax-reduction
fix(agc): accept a min or max reduction sampler with anisotropic filtering
2026-10-15 22:58:19 +02:00
Yunus Shaikh e9ff3b1768 fix(agc): plan a heap again when its mirror's range has left the write watch
A heap mirror is refreshed from the write watch. acquireMirror checked
the watch only when it made a mirror and reused an existing one as it
was. Once part of the range left the watch, the next address-based build
threw "a heap mirror's range is no longer write-watched" from the
refresh, and a build served from the address-space cache threw the same
from its heap runs. A range leaves the watch for good when a host import
that does not keep the watch covers it: on Windows a direct import of
private memory that is not settled (below the 1 MiB settle floor, or any
when imports cannot be settled), elsewhere any import while imports are
compared.

A heap mirror now records the unwatch serial at which its range was last
seen fully watched. Its reuse, and a cache hit over it, compare that
serial with GuestMemory::UnwatchSerial and look at the watch again only
when a range has left it since. A mirror whose range is no longer
watched is not reused, the cache is not taken (before its imports are
stamped), and the pass plans the range again: an import if the budget
allows, else a copy. A refused heap mirror also drops the registry's
stale one, whose buffer would stay allocated otherwise.
2026-10-15 20:40:32 +00:00
mattogepetoandClaude Sonnet 5.5 3f8337e730 fix(libSceSysmodule): test and document unknown module ids
sceSysmoduleIsLoaded, sceSysmoduleLoadModule and sceSysmoduleUnloadModule
return success for an id missing from the module table, because titles that
load or unload such an id aborted otherwise (b4db9fdd6, a2520aa07). Nothing
tested or recorded it, and two commented-out throws were left in the code.

Remove the commented-out throws, list the three functions under Silent stubs
in the library's technical debt file, and test that unknown ids succeed
without changing state while the internal variants still throw.

Written with AI assistance (Claude).

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-15 22:33:13 +02:00
Yunus Shaikh 210a585b67 Merge upstream main into perf/shader-image-table-reuse-v3-pr 2026-10-15 13:17:18 -07:00
Gabrieljr42 a2392c0246 feat(tools): add a module filter and JSON output to progress.py 2026-10-15 17:04:10 -03:00
HILAL El MehdiandClaude Opus 5.5 2a9390aa11 docs(debt): correct Windows GUI logging description
Since ab3e92605 the entry stub gives each missing standard handle
anyps5.log beside the executable, and the crash report writes to the
standard error handle, so it reaches the log too. The entry now records
only what is still lost: the stub's errors about the executable path or
about waiting for the previous LoadExec process, written before the log
is opened, and output to the missing handles when the log cannot be
created.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0154rPujpieMaCnZ6WMobg7M
2026-10-15 21:39:42 +02:00
billybobpicklioandClaude Opus 5.5 a0347cfed5 feat(agc): draw line-strip output of NGG geometry programs as mesh lines
A geometry program with VGT_GS_OUT_PRIM_TYPE 1 was refused as an
unsupported output assembly. Each primitive export of an NGG line-strip
program is one line whose indices are packed like a triangle's, so the
mesh module now declares OutputLinesEXT with PrimitiveLineIndicesEXT for
it. A subgroup gets VGT_GS_MAX_VERT_OUT - 1 lines per input primitive and
at least GE_MAX_OUTPUT_PER_SUBGROUP line slots; fast launch keeps using
PRIM_AMP_FACTOR. The output size is part of the cache, draw, validation
and pipeline keys, and the request serialization version becomes 31.
Triangle-strip geometry is unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 15:39:35 -04:00