Commit Graph

4862 Commits

Author SHA1 Message Date
Pouare514 f1a3d60b15 fix(libkernel): boot Dreaming Sarah past unwind and debug raise 2026-10-02 13:34:35 +02:00
julienlgy 2755aff9b1 feat(libSceAudio3d): add missing sceAudio3dPortClose stub
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-02 12:46:50 +02:00
DotDebian dab1110556 feat(libkernel): implement sceKernelCancelSema
sceKernelCancelSema was a throwing stub. It now releases every thread
blocked in sceKernelWaitSema with SCE_KERNEL_ERROR_ECANCELED without
consuming tokens, sets the count to setCount (the initial count when
setCount is negative) and reports how many threads were waiting. A
setCount above the maximum returns SCE_KERNEL_ERROR_EINVAL and changes
nothing.

Waiters are counted separately from waiterCount, which is only
decremented when a waiter leaves, so two cancels in a row do not report
the same thread twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 11:57:00 +02:00
DotDebian d6cca762f4 feat(libkernel): support the CPU-time clocks in clock_gettime and clock_getres on Windows
CLOCK_THREAD_CPUTIME_ID (14) and CLOCK_PROCESS_CPUTIME_ID (15) threw
"unsupported clock_id" on Windows while the Linux branch already maps
them to the native clocks. clock_gettime now returns the user + kernel
time from GetThreadTimes / GetProcessTimes, and clock_getres reports the
clock interrupt period from GetSystemTimeAdjustment, which is the step
those counters actually advance by.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 11:40:22 +02:00
DotDebian 7fd0890320 feat(libkernel): implement __elf_phdr_match_addr
Returns 1 when the address lies in an executable PT_LOAD segment of the
given dl_phdr_info, following FreeBSD lib/libc/gen/elf_utils.c (9.x and
11.x branches). The stub parameters become (dl_phdr_info*, void*) to
match the FreeBSD declaration; a null dl_phdr_info throws.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 11:18:06 +02:00
DotDebian 40d63b1b4c feat(libkernel): implement the sceKernelGetEvent* field accessors
sceKernelGetEventId, sceKernelGetEventFilter, sceKernelGetEventFflags,
sceKernelGetEventData and sceKernelGetEventUserData return the matching
field of the KernelEvent filled by sceKernelWaitEqueue and throw on a
null event. sceKernelGetEventError still throws NotImplemented.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 10:46:15 +02:00
boykopovar e1654a97e5
Merge pull request #259 from adriadam10/feat/vopc-compare-gaps
feat(shader): implement the missing non-f64 VOPC compares
2026-10-02 11:14:37 +03:00
boykopovar 8ed9e7ab5e
Merge pull request #257 from adriadam10/feat/vop3-integer-gaps
feat(shader): VOP3 v_add/sub_nc_i32 (clamp), v_mul_lo_u16, 16-bit mads, v_ashrrev_i64
2026-10-02 11:13:30 +03:00
boykopovar 623c0d8dc6
Merge pull request #254 from adriadam10/fix/shader-writelane
fix(shader): select the written lane in v_writelane_b32
2026-10-02 11:13:02 +03:00
Dean Galvin 7ed138d13f fix(recompiler): start pixel waves without their helper invocations in EXEC
A pixel wave starts with EXEC holding its covered pixels. The other lanes of
a partly covered quad run as helpers outside EXEC until the shader asks for
whole quads with s_wqm. Pixel shaders started with every invocation in EXEC,
Vulkan's helper invocations included. Those take part in subgroup
operations, so they counted in ballots (v_mbcnt, s_bcnt1 of EXEC,
v_readfirstlane), and a wave's single ds_append or atomic could be performed
by one of them: an atomic in a helper invocation does nothing and returns an
undefined value.

The entry prologue now starts a pixel shader's EXEC as !gl_HelperInvocation,
through a new StageInputKind::HelperInvocation builtin input. s_wqm still
adds the helpers of every quad with a covered pixel, so derivative code keeps
them.

The agc_driver_pixel_helper_lanes execution test draws triangles that leave
partly covered quads across the target with a pixel shader that stores each
covered pixel's v_mbcnt rank in EXEC, the s_bcnt1 count of EXEC and the
v_readfirstlane of a pixel id. Every wave's covered pixels must be lanes
0..n-1 of an n-lane EXEC whose first lane is one of them, in wave64 and
wave32. It skips on a subgroup narrower than 32, such as lavapipe's.
2026-10-02 21:08:32 +13:00
Dean Galvin 151fec7fd6 fix(videoout): read the open param as the service thread's priority and affinity
and throws for any non-zero word after it. Its layout matches shadPS4's
ServiceThreadParams instead: an unknown first word (16), a set-priority flag
and a priority (256..767), a set-affinity flag and a 64-bit CPU mask at
offset 16. PPSA21564 passes 16, 1, 0x100, 1 and 0x1FFF, so it stops at
startup on main.

sceVideoOutOpen now validates each field and reads the mask only when its
flag is set, so a 16-byte param with both flags clear still works. The
priority and affinity are not applied, since the present and vblank threads
are host threads; this and the unknown first word are listed in the
technical debt.
2026-10-02 21:05:25 +13:00
Adrià Franch 58f90eea9d feat(libScePngEnc): implement PNG encoding
scePngEncQueryMemorySize, scePngEncCreate, scePngEncEncode and
scePngEncDelete encode R8G8B8A8 and B8G8R8A8 images with a pitch into
RGB or RGBA PNGs using the shared encoder in core/Decoder/Png.
Decoder::Png::Encode takes optional compression level and filter
options so the encode parameters are honoured.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 10:00:32 +02:00
Adrià Franch 3033e5e554 feat(shader): implement s_movrels/s_movreld (b32, b64) and s_movrelsd_2_b32
s_movrels reads SGPR[src + M0] and s_movreld writes SGPR[dst + M0].
The 64-bit forms align the offset down to even (M0 & ~1), and
s_movrelsd_2_b32 takes the source offset from M0[9:0] and the
destination offset from M0[25:16], as measured on hardware. They use
the same select-over-registers lowering as the vector forms, over the
106 SGPRs. The embedded vertex-fetch scan forgets every tracked SGPR on
a relative write.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 09:59:59 +02:00
Adrià Franch f3f9b4fff7 feat(shader): implement s_bcnt0_i32_b64, s_ff0_i32_b64, s_flbit_i32(_i64), s_quadmask_b32
The decoder threw for these SOP1 opcodes. The 64-bit find-first-zero and
signed leading-bit counts reuse the existing 64-bit helpers with a flag;
s_quadmask_b32 is the 32-bit half of s_quadmask_b64. s_bcnt0 and s_quadmask
set SCC to result != 0; the find and leading-bit forms leave it.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 09:59:47 +02:00
Adrià Franch 24f959b48c fix(shader): select the written lane in v_writelane_b32
The WriteLane IR takes {value, lane, previous}, as the translation and the
read-lane eliminator use it, but the SPIR-V emitter compared the lane id with
the previous value and selected between the lane index and the value. Every
v_writelane therefore wrote its value to all lanes (or the lane index to the
lane whose old value happened to equal its id).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 09:59:37 +02:00
boykopovar 01eaae0bf9
Merge pull request #253 from adriadam10/feat/shader-cache-hint-noops
feat(shader): decode cache invalidations and performance hints as no-ops
2026-10-02 10:50:20 +03:00
boykopovar 9b3927b4ea
Merge pull request #252 from adriadam10/feat/vop3-f16-ubyte-aliases
feat(shader): VOP3 v_max/min_f16, v_cvt_f32_f16/ubyte and abs/neg on f16 binaries
2026-10-02 10:49:58 +03:00
boykopovar 29364c33d8
Merge pull request #248 from adriadam10/feat/ngs2-atrac9
feat(libSceNgs2.native): decode ATRAC9 sampler voices, parse and size ATRAC9 waveforms
2026-10-02 10:47:15 +03:00
boykopovar 4eab28c1fa
Merge pull request #241 from adriadam10/feat/audio-legacy
refactor(audio): drop duplicated stub exports from libSceAudio
2026-10-02 10:35:29 +03:00
boykopovar 194ea62ff9
Merge pull request #228 from adriadam10/feat/ajm-from-native
refactor(ajm): drop duplicated stub exports from libSceAjm and libSceAjmi
2026-10-02 10:35:05 +03:00
boykopovar a0eb90559e
Merge pull request #237 from adriadam10/fix/ajm-mp3-s16p
fix(ajm): convert planar 16-bit MP3 output from FFmpeg
2026-10-02 10:34:44 +03:00
boykopovar 409c41cc6a
Merge pull request #236 from adriadam10/feat/audiodec
feat(libSceAudiodec): decode MP3, M4AAC and ATRAC9
2026-10-02 10:34:11 +03:00
boykopovar 8cad51d19e
Merge pull request #247 from adriadam10/feat/ngs2-core
feat(libSceNgs2.native): implement system, racks, voices and PCM rendering
2026-10-02 10:33:53 +03:00
boykopovar 2d0e706fc7
Merge pull request #246 from oneandonlydean/fix/agc-keys-fill-clear-hold
fix(agc): end a key fill's hold when the fill clears the image at once
2026-10-02 10:33:28 +03:00
boykopovar 08e6a57662
Merge pull request #251 from adriadam10/ci/gpu-tests-lavapipe
ci: run the shader execution tests on lavapipe
2026-10-02 10:32:21 +03:00
boykopovar fbfe6bb13b
Merge pull request #249 from MichonGoddijn231849/fix/fast-texture-filled-keys
fix(agc): the stage-A fast path leaves a view of a pending image whose keys were filled to the full lookup
2026-10-02 10:30:29 +03:00
Adrià Franch 69bd750c46 feat(libSceNgs2.native): decode ATRAC9 sampler voices, parse and size ATRAC9 waveforms
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 09:24:46 +02:00
Adrià Franch 90295d3733 feat(libSceNgs2.native): implement system, racks, voices and PCM rendering
libSceNgs2 keeps its stubs; its types now come from the .native header.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 09:24:46 +02:00
Adrià Franch 569c2ec56c feat(libSceAudiodec): decode MP3, M4AAC and ATRAC9
All six exports are implemented: MP3 and AAC (ADTS or raw blocks) are
decoded with the bundled FFmpeg and ATRAC9 with LibAtrac9, one unit per
call, into interleaved S16 or float PCM, with the libSceAudiodec
validation and error codes. libSceAudiodec.native is built from the same
sources.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 09:22:59 +02:00
Adrià Franch 2036697758 fix(ajm): convert planar 16-bit MP3 output from FFmpeg
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 09:20:45 +02:00
Adrià Franch e3fa37f60a refactor(audio): drop duplicated stub exports from libSceAudio
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 09:16:34 +02:00
Adrià Franch 14e13219ee refactor(ajm): drop duplicated stub exports from libSceAjm and libSceAjmi
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 09:16:34 +02:00
boykopovar 56aa800ef0
Merge pull request #220 from asimplestray/feat/shader-sop1-saveexec
feat(shader): implement SOP1 saveexec/wrexec family
2026-10-02 09:46:06 +03:00
Alberto Ruiz 1b2af06c92 fix(json2): reject documents nested deeper than 512 levels
The parser descends recursively into every array and object without a
limit, so deeply nested input exhausts the stack and crashes the
process: 50000 levels on an 8 MB main thread and 5000 levels (10 KB of
brackets) on a 256 KB thread. sce::Json::Parser::parse now returns
JsonErrorParse when a document opens more than 512 nested arrays or
objects, which bounds the recursion for any input.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5WJS4ZdQynAJesCZKH5hb
2026-10-02 08:08:37 +02:00
Adrià Franch 7d90b1dcec feat(shader): implement s_memtime and s_memrealtime
Both SMEM opcodes read a 64-bit counter into an SGPR pair. They now
lower to OpReadClockKHR: s_memtime with subgroup scope (the shader
clock) and s_memrealtime with device scope (the constant real-time
clock). The device enables VK_KHR_shader_clock when it has both clocks
and the backend refuses the opcodes with a clear reason otherwise.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 07:58:41 +02:00
Dean Galvin dc8a716930 fix(shader): wrap the v_readlane_b32 lane select at the wave size
The hardware reads the lane select modulo the wave size (S1[4:0] in wave32,
S1[5:0] in wave64), as ReadLaneEliminator already assumes with
selector % waveSize. On the single-subgroup path EmitReadLane passed the raw
select to OpGroupNonUniformShuffle, which is undefined for an id at or above
the subgroup size. It is now masked with WaveSize() - 1, like v_writelane_b32.
The two-lane wave64 path already wrapped.
2026-10-02 18:23:56 +13:00
Adrià Franch c8af88921a feat(shader): implement the missing 32-bit LDS atomics and fix ds_min/max_f32
ds_rsub(_rtn)_u32, ds_inc_u32, ds_dec_u32, ds_mskor(_rtn)_b32,
ds_cmpst(_rtn)_b32/f32, ds_add(_rtn)_f32, ds_min/max_rtn_f32,
ds_wrap_rtn_b32 and ds_nop threw in the decoder. The new ones run as a
compare-exchange loop over the old value, with the semantics measured on an
RDNA2 GPU.

ds_min_f32 and ds_max_f32 take one data operand on gfx10, but compared the
memory with a second register (the unused data1 field, usually v0) and
stored data0 when that compare held. They now keep the minimum/maximum of
memory and data like the hardware: a NaN loses to a number, -0 < +0. Both
IR ops return the old value, so the _rtn forms share them.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 07:11:48 +02:00
Adrià Franch 8fd19cda0e feat(shader): implement f16 ldexp/frexp/norm/class, v_sat_pk_u8_i16 and v_mul/mac_legacy_f32
v_ldexp_f16, v_frexp_mant_f16, v_frexp_exp_i16_f16, v_cvt_norm_i16/u16_f16,
v_cvt_pknorm_i16/u16_f16, v_cmp_class_f16, v_cmpx_class_f16,
v_sat_pk_u8_i16 and v_mul/mac_legacy_f32 threw in the decoder. The
behaviour was measured on an RDNA2 GPU: ldexp takes the exponent as an i16,
the norm conversions round to nearest even (done in integers, as x * 32767
does not fit f32 exactly), and a legacy multiply with a zero operand gives
+0 even for an infinite or NaN other operand. v_mac_legacy_f32 adds the
rounded product, like v_mac_f32.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 06:46:26 +02:00
Adrià Franch 9e0060cb37 fix(shader): keep fused multiply-adds fused and v_mad/v_mac_f32 rounded twice
SPIR-V float ops without NoContraction let the driver fuse or split them:
RADV contracted a guest v_mul_f32 + v_add_f32 into one fma, which made the
f32 division macro one ulp off. f32 add, sub, mul and fma now carry
NoContraction.

v_mad_f32, v_mac_f32, v_madmk_f32 and v_madak_f32 round the product before
the add, unlike their v_fma*/v_fmac* counterparts, but all of them were
translated to FPFma32. They now use a new FPMad32, emitted as a separate
NoContraction multiply and add.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 06:41:03 +02:00
Adrià Franch 7c753c336e fix(shader): round f32 to f16 to nearest even on every driver
f32 to f16 conversions (every f16 VALU result, v_cvt_f16_f32, f16 image
stores) used GLSL packHalf2x16, whose rounding is implementation-defined.
RADV truncates, so f16 results were off by one ulp and overflowed to
65504 instead of infinity. The conversion is now done with integer
operations: round to nearest even, subnormals, overflow to infinity and
quiet NaNs, as RDNA does. v_cvt_pkrtz keeps its own truncating op.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 06:40:10 +02:00
Adrià Franch ecda77d51d fix(agc): run wave32 compute programs on 32-wide subgroups
On devices whose default subgroup is 64 lanes (RADV, AMD on Windows) a
wave32 compute program was compiled for a 64-wide host subgroup, so the two
guest waves of a 64-thread workgroup shared one subgroup: ballots, EXEC,
v_mbcnt and lane reads of the second wave saw the first one's lanes.

With VK_EXT_subgroup_size_control, when compute can require 32 lanes, the
dispatch recompiles wave32 programs for a 32-wide host subgroup
(VulkanDevice::ComputeTarget) and the pipeline requires that size. The
result records the width it was compiled for (hostSubgroupSize, also in the
disk cache).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 06:28:08 +02:00
RomainROCH 74586bab57 fix(libkernel): avoid semaphore count overflow 2026-10-02 06:19:39 +02:00
Adrià Franch d06883aeff fix(shader): select the written lane in v_writelane_b32
The WriteLane IR takes {value, lane, previous}, as the translation and the
read-lane eliminator use it, but the SPIR-V emitter compared the lane id with
the previous value and selected between the lane index and the value. Every
v_writelane therefore wrote its value to all lanes (or the lane index to the
lane whose old value happened to equal its id).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 06:18:55 +02:00
RomainROCH 99fbcf0377 fix(libc): propagate file position errors 2026-10-02 06:15:14 +02:00
RomainROCH 193ec6e268 fix(savedata): report memory metadata write failures 2026-10-02 06:05:54 +02:00
asimplestray f2bfdd26f9 feat(shader): implement SOP1 saveexec/wrexec family 2026-10-02 00:22:41 +00:00
Dean Galvin 301f3b161e fix(recompiler): sample with texel offsets the guest computes, through maintenance8's Offset
image_sample_*_o takes its texel offset from an address VGPR. The emitter
accepted only an immediate there and failed with "requires a constant texel
offset for image sampling" for any other, including an offset the program
moves into the VGPR under EXEC.

An offset that resolves to a constant at its packed address position stays a
ConstOffset. Any other becomes the Offset image operand, which Vulkan allows
on sampling instructions only with VK_KHR_maintenance8's maintenance8 feature
and the ImageGatherExtended capability. The device enables maintenance8 when
available and reports it through SpirvTarget::nonConstantImageOffsets, which
the cache key, the request serialization (version 6) and the SPIRV-Tools
validator options follow. Without it the sample still fails.

agc_shader_replay --maintenance8 recompiles a request for such a device.
2026-10-02 12:26:31 +13:00
SP4C3B4R-8 53aac1137a fix(libSceAgcDriver): destroy host imports of a replaced Vulkan device
Replacing the headless device with the windowed one dropped the import
registry without freeing its buffers and memory, and the replaced device
is kept alive, so the imported pinned host memory stayed allocated and
the new device ran out of memory importing the same ranges again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 23:54:43 +02:00
SP4C3B4R-8 c4be3f78f6 feat(libScePad): implement scePadSetTiltCorrectionState
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bn7CrhG7pTPR6DT13tN6Me
2026-10-01 23:44:31 +02:00
SP4C3B4R-8 4099ffb7d3 feat(libkernel): accept MAP_NO_OVERWRITE fixed mappings on Windows
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bn7CrhG7pTPR6DT13tN6Me
2026-10-01 23:44:31 +02:00
SP4C3B4R-8 f2deb00fa4 feat(libs): declare missing AudioPropagation, AudioIn, NpSessionSignaling and dialog exports
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bn7CrhG7pTPR6DT13tN6Me
2026-10-01 23:44:31 +02:00
SP4C3B4R-8 3fc3b993da feat(libkernel): honour non-fixed mapping address hints on Windows
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bn7CrhG7pTPR6DT13tN6Me
2026-10-01 23:44:30 +02:00
SP4C3B4R-8 ef172bb5d1 fix(libSceAgcDriver): prefer a discrete GPU over the first suitable device
Physical device selection took the first Vulkan device with graphics,
compute and presentation support, so on systems with an integrated GPU
(e.g. Ryzen 7000 desktop CPUs) the enumeration order decided whether the
integrated or the discrete GPU was used. Rank candidates by device type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bn7CrhG7pTPR6DT13tN6Me
2026-10-01 23:44:29 +02:00
Dean Galvin e69de0df66 perf(agc): reuse a draw's index and vertex copies while the guest bytes are unchanged
Every draw copied its index and vertex ranges from guest memory into
fresh buffers and scanned the indices, although the draws of a frame read
the same meshes again: about 10 GiB of vertex copies per 10 s at
PPSA21564's title.

CopyDrawInput now keeps the copy in the recorder's draw snapshot cache
and binds it again while the write tracker proves the range unchanged
since the copy was taken, with the same rules as the storage-buffer
snapshots: UnchangedSince on the collect made right before the copy and
an unchanged allocation registry. As GuestMemory::Read does, the flush
hook runs first, so pending GPU results over the range are stored and
stamped before the check. Unwatched memory is copied every time. An index
copy keeps its highest index; the device limit is still checked for every
draw.

The cache key includes the snapshot's use (storage, vertex, 16-bit or
32-bit index), so each use keeps its own buffer with its own usage. A
vertex copy runs from the buffer's start to its highest fetched element,
so draws over one shared vertex pool ask for many sizes: a vertex
snapshot also serves a shorter read at the same address while that
read's bytes are unchanged, and a new one replaces the shorter ones.
Vertex and index snapshots have their own least recently used pool
(1 GiB, 16384 entries), so storage copies, most of which change every
frame, do not push them out before their next use.

Tests: agc_driver_recorder_tests copies index and vertex ranges of
write-watched memory and requires a reuse (with the stored highest index)
while the bytes are unchanged, a new copy with the current bytes after a
CPU store, a MarkWritten store and a registry mutation, separate copies
per use, no reuse without a recorder, prefix reuse for vertex reads only,
and storage snapshots not evicting vertex snapshots.
2026-10-02 10:30:36 +13:00
Dean Galvin 69a94208b7 perf(agc): reuse unchanged draw input snapshots across draws
A recorded draw binds a CPU copy of each read-only guest buffer it reads
in place, made for every draw. PPSA21564's title-stage draws bind the
same large light-list buffers written by compute passes (up to 16 MiB
each) hundreds of times per frame, so about 4 ms of every draw went into
copying about 30 MiB into freshly allocated host buffers.

The recorder now keeps the snapshots, least recently used first, under a
256 MiB budget and 1024 entries. A later draw of the same range binds the
kept, immutable copy while GuestMemory::UnchangedSince holds for the
write generation collected right before the copy and the guest allocation
registry generation is unchanged. A CPU store (stamped by a collect), a
driver or GPU store (MarkWritten) or a registry mutation makes the next
draw copy again. Unwatched memory has no generation and is copied for
every draw, as before.

A recency list (each entry holding its own position) gives the eviction
victim and moves a used entry to the back in O(1).

Tests: agc_driver_recorder_tests binds a write-watched, host-imported
range twice and requires the same snapshot, then a new copy with the new
bytes after a CPU store, a MarkWritten store and a registry mutation; and
checks the least recently used eviction order at the entry cap, the byte
budget and a CPU store dropping a kept snapshot.
2026-10-02 10:27:00 +13:00
RomainROCH 021eb65b51 fix(libkernel): report undersized Windows directory buffers 2026-10-01 23:24:41 +02:00
Dean Galvin 66ddf59c22 fix(recompiler): give a loop's exit-tail branch a selection merge
A conditional inside a loop with one target in the loop body and the
other outside it was taken for a break and emitted without a merge. When
the outside target is not the loop's merge but a tail of blocks that
reaches it, SPIR-V has no construct for that branch: spirv-val rejects
the module ("Selection must be structured") and the driver is free to
compile it into anything.

Such a branch now merges at its in-body target when the tail is private
to it (every tail block is dominated by the tail's first block, stays in
the loop construct and leaves only for the loop's merge), so the tail is
an "if (c) { tail; break; }" the loop already allows. Merges are given
to these after every other construct's, and one already taken leaves the
branch as before.

All 13 PPSA21564 programs whose V#s are read from GPU memory (the
deferred lighting and ray-traced passes) had two such branches in their
traversal loops. With this change none of the 74 dumped title programs
has one, and the 209 modules of a title-to-cinematic run validate apart
from three unrelated image-offset and entry-point errors.

Tests: agc_structurizer_tests structures a loop that exits through one
tail block and a loop with two exit tails, and requires every merge-less
conditional to target its loop's merge or continue.
2026-10-02 10:23:02 +13:00
Michon f9162abb84 fix(agc): color targets with gaps between written MRT slots, depth array slices
An MRT slot below the highest written one that the draw does not write is a VK_ATTACHMENT_UNUSED
reference with a disabled blend; color targets keep their slot for export mappings, pipeline and
pass keys. DB_DEPTH_VIEW SLICE_START moves the depth and stencil planes by whole slices, so each
slice of a depth array is its own depth surface.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 23:21:58 +02:00
Michon 04691c0797 feat(libs): offline services GTA V reaches in Story Mode
Sign-in, web browser and player dialogs finish cancelled; the message dialog finishes at once;
NpAuth, entitlement consumption, reachability, account age and the NpUtility bandwidth test
report signed out; sceKernelMtypeprotect changes the protection (the memory type has no host
equivalent); the APR ForEach resolvers resolve every path and report each failure in its own
result entry. vswprintf's stub is dropped in favor of the existing wide-formatter
implementation, which already covers it on every platform.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-01 23:21:54 +02:00
RomainROCH c58f3f0a14 fix(savedata): preserve memory saves when growth reads fail 2026-10-01 23:20:39 +02:00
Alberto Ruiz fc68a04b0b fix(shader): reject SDWA and DPP instructions without their modifier word
The VOP1, VOP2 and VOPC SDWA and DPP decoders read the modifier word at
wordIndex + 1 before SetRdnaRawWords checked that it exists, so a code
span ending at such an instruction was read one word past its end.
AddressSanitizer reports a heap-buffer-overflow in decodeVop2Sdwa on a
synthetic program. The six decoders now throw "truncated <encoding>
instruction" first, as DecodeRdnaVop3 and DecodeRdnaVop3p already do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5WJS4ZdQynAJesCZKH5hb
2026-10-01 22:49:38 +02:00
Adrià Franch 703afd5b10 fix(shader): accept neg on VOP3-encoded float compares
VOP3 compares have a scalar destination, so checkNativeVop3Modifiers sent
them through the carry/scalar-destination branch, which rejects neg. abs
already passed and both are applied to the sources by the VOPC path, so
v_cmp_lt_f32_e64 vcc_lo, -v1, v2 threw "VOP3 source modifiers are not
implemented". Float compares now accept neg there; integer ones still don't.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 22:45:25 +02:00
Adrià Franch b6376737bb feat(shader): implement the missing non-f64 VOPC compares
Fifty VOPC opcodes threw in the decoder: cmpx f/o/u/tru for f32, cmpx f/t
for i32/u32, the 64-bit integer compares except the seven already present,
and the f16 f/o/u/nge/nlg/ngt/nle/nlt/tru compares and their cmpx forms.
64-bit gt/le/ge are built from SLessThan64/ULessThan64 by swapping and
negating, as the IR has no other 64-bit orderings. emitFloatOrderedCompare
gains the f16 and cmpx forms.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 22:45:25 +02:00
Adrià Franch e144f43f05 feat(shader): implement VOP3 v_add/sub_nc_i32 with clamp, v_mul_lo_u16, v_mad_u16/i16/u32_u16/i32_i16, v_ashrrev_i64
These VOP3 opcodes threw in the decoder. v_add_nc_i32 and v_sub_nc_i32 are
what compilers emit for signed saturating add/sub, so their clamp saturates
to the int32 range. The 16-bit mads honour op_sel on their 16-bit sources;
the u32_u16/i32_i16 forms take a 32-bit addend and write all 32 bits, so
they do not get the 16-bit destination select.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 22:45:25 +02:00
Adrià Franch e56511f2b4 feat(shader): decode cache invalidations and performance hints as no-ops
s_icache_inv, s_incperflevel, s_decperflevel, s_ttracedata_imm, s_wait_idle,
s_gl1_inv, s_dcache_inv, s_dcache_wb, buffer_gl0_inv and buffer_gl1_inv threw
in the decoder. SPIR-V has no cache control, so they translate like s_clause
and s_waitcnt, which already emit nothing. The SMEM and MUBUF forms carry no
operands, so no pass sees a phantom base or destination register.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 22:45:25 +02:00
Adrià Franch d97c6aee63 feat(shader): decode VOP3 v_max/min_f16 and v_cvt_f32_f16/ubyte, accept abs/neg on f16 binaries
The VOP2/VOP1 forms already translate; the VOP3 encodings were rejected by the
decoder. VOP3 f16 add/sub/subrev/mul/min/max now take abs and neg, which
readF16AsF32 already applies. Clamp and omod stay rejected for them because
writeF16 does not apply result modifiers.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 22:45:25 +02:00
Adrià Franch 8ed454d2fa ci: run the shader execution tests on lavapipe
MixPrecision and SdwaDestination dispatch hand-assembled RDNA through the
recompiler and compare every lane with a CPU model, but were never in ctest.
Move them to tests/execution/, which is globbed into one test per file with
the same target names, so new execution tests add a file and no CMake lines.
They exit 77 (skipped) when the host has no Vulkan device; the Linux runner
installs lavapipe and sets ANYPS5_REQUIRE_VULKAN=1 so they cannot skip there.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 22:45:25 +02:00
RomainROCH 8f76c0a57f fix(libc): release aligned allocations through the application heap 2026-10-01 22:43:44 +02:00
Michon f5ae0b8106 fix(shader): rect lists take explicitly interpolated fragment parameters and refuse only custom ones
Explicit v_interp_p1/p2 interpolation (fragment-shader barycentrics) reads every interpolated
parameter per vertex, and the rect-list shaders refused every per-vertex parameter. Their
tessellation stage emits each corner's parameter value, which is what a per-vertex read of the
generated triangles needs. Only custom parameters (custom interpolation or passthrough), whose
fourth vertex has no value of its own, stay refused; FragmentParameter carries that flag.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 22:13:36 +02:00
boykopovar 7c5f8b6e12 Revert "Merge pull request #143 from SamG-Coder/codex/shader-geometry-validation"
This reverts commit de49f81697, reversing
changes made to cfb1d76e60.
2026-10-01 22:55:27 +03:00
Michon ecf73da860 fix(agc): the stage-A fast path leaves a view of a pending image whose keys were filled to the full lookup
A sampled read through a surface's keys after a uniform key fill with a clear code reads the
fill's clear value, not the image's pending results (cachedTexture's clear-through-keys). The
stage-A fast path returned the record's view of the pending image without that check, so a
read between the fill and the image's next refresh saw the previous results.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 21:12:26 +02:00
boykopovar 75434ee4ad
Merge pull request #240 from adriadam10/feat/pad-small
feat(libScePad): implement scePadGetHandle and the embedded mic vibration option
2026-10-01 22:00:55 +03:00
boykopovar 643c8cfc99
Merge pull request #239 from adriadam10/fix/error-codes
fix(libs): correct VideoOut and Pad error codes
2026-10-01 21:59:04 +03:00
boykopovar 54c3f39680
Merge pull request #238 from adriadam10/feat/playgo-language-todo
feat(libScePlayGo): fix error codes, implement the language mask and to-do list
2026-10-01 21:58:12 +03:00
boykopovar ce6bd0c750
Merge pull request #233 from adriadam10/feat/fiber-context-size-check
feat(libSceFiber): implement context size checking and the thread frame pointer
2026-10-01 21:57:29 +03:00
boykopovar 171c9a97b2
Merge pull request #230 from asimplestray/feat/rt-miss-mode
feat(shader): add ray tracing miss fallback mode
2026-10-01 21:56:27 +03:00
boykopovar a360f162c6
Merge pull request #224 from adriadam10/feat/ces-cp1252
feat(libSceCesCs): convert single characters between CP1252 and UTF-8
2026-10-01 21:53:01 +03:00
boykopovar e0f7866205
Merge pull request #223 from adriadam10/feat/http2-ssl-stubs
feat(libSceSsl): implement CA certificate queries and sceHttp2AbortRequest
2026-10-01 21:52:19 +03:00
boykopovar 0567aca352
Merge pull request #225 from adriadam10/feat/keyboard-key2char
feat(libSceKeyboard): implement the keyboard library
2026-10-01 21:50:25 +03:00
boykopovar 938b632784
Merge pull request #221 from adriadam10/feat/http-uri
feat(libSceHttp): implement URI parse, build and escape
2026-10-01 21:48:06 +03:00
boykopovar 01e1074efc
Merge pull request #219 from asimplestray/feat/shader-vop3-minmax16
feat(shader): implement VOP3 I16/U16 min/max/med3
2026-10-01 21:42:12 +03:00
Dean Galvin ea0f13027e fix(agc): end a key fill's hold when the fill clears the image at once
An image's filledKeys stands for "the pending results predate the title's
key fill": sampled reads through those keys bind the clear value, and
(with APS5_KEYS_FILL_WRITEBACK_KEEP=1) a write-back leaves the keys at the
fill's code. A refresh that clears the image under the new keys ends that
hold (upload resets it), but the immediate clear of APS5_KEYS_FILL_CLEAR=1
did not. Results drawn after such a fill were then treated as dead: reads
through the keys saw the clear and a write-back kept the keys clear over
them. The immediate clear now ends the hold as the refresh does.
2026-10-02 07:41:50 +13:00
RomainROCH 9c07fc0a98 style(savedata): remove namespace comment 2026-10-01 20:35:18 +02:00
boykopovar 1ffaa66173
Merge pull request #215 from julienlgy/feat/lib-sce-hmd-stub
feat(libSceHmd): add a disconnected-headset HLE stub
2026-10-01 21:28:09 +03:00
boykopovar c19448f834
Merge pull request #214 from oneandonlydean/fix/recompiler-sdwa-dword-dst
fix(recompiler): zero the high half of 16-bit SDWA results written as a whole dword
2026-10-01 21:27:50 +03:00
boykopovar de49f81697
Merge pull request #143 from SamG-Coder/codex/shader-geometry-validation
fix(shader): preserve NGG passthrough and wave32 launch inputs
2026-10-01 21:17:52 +03:00
boykopovar cfb1d76e60
Merge pull request #142 from SamG-Coder/codex/shader-interpolation-operands
fix(shader): preserve interpolation instruction operands
2026-10-01 21:17:16 +03:00
Adrià Franch eb85dc7362 fix(nid): share string suffixes when rebuilding .dynstr
The linker stores a dynamic string that is the suffix of another once
(for example "cos" inside "acos"). The patcher wrote every string
separately, so a library whose renamed exports do not shrink the table
enough failed with "rebuilt .dynstr exceeds original section size".
Strings are now sorted by their reversed text and a string that ends
another one points into it.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 20:09:41 +02:00
Adrià Franch 621c8bea23 feat(libScePad): implement scePadGetHandle and the embedded mic vibration option
scePadOpen now records that the pad is open and scePadClose clears it;
scePadGetHandle returns the handle for a port scePadOpen accepts while
the pad is open, and DEVICE_NO_HANDLE otherwise. No embedded microphone
is emulated, so the option that weakens trigger vibration while it is
in use is accepted with no effect.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 19:57:32 +02:00
Adrià Franch 76be6796dc fix(libs): correct VideoOut and Pad error codes
Ten libSceVideoOut and two libScePad error constants had values that
belong to other errors of the same library (for example INVALID_HANDLE
was 0x80290003 and RESOURCE_BUSY / SLOT_OCCUPIED were swapped). They now
match KytyPS5, shadPS4 and fpPS4, which agree on all of them.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 19:53:49 +02:00
Adrià Franch 2b36dc2408 feat(libScePlayGo): implement the language mask and to-do list
The title is fully installed, so scePlayGoGetLanguageMask reports every
language. scePlayGoSetToDoList validates the handle, entries, chunk IDs
and loci; nothing is pending, so the list is not kept.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 19:50:33 +02:00
Adrià Franch 97958bdd07 fix(libScePlayGo): use the library's error codes for bad pointer, handle and size
BAD_POINTER, BAD_HANDLE and BAD_SIZE were 0x80B20004, 0x80B20005 and
0x80B2000D, which are INVALID_ARGUMENT, NOT_INITIALIZED and BAD_SPEED.
They are 0x80B2000A, 0x80B20009 and 0x80B2000B.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 19:49:12 +02:00
Adrià Franch 62530c9d5c feat(libSceFiber): implement context size checking and the thread frame pointer
sceFiberStartContextSizeCheck and sceFiberStopContextSizeCheck toggle a
mode in which new fibers get their context filled with a pattern, so
sceFiberGetInfo can report the unused stack margin.
sceFiberGetThreadFramePointerAddress returns the frame pointer of the
thread that called sceFiberRun.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 19:27:24 +02:00
asimplestray c3a740b3e6 feat(shader): add ray tracing miss fallback mode 2026-10-01 17:24:09 +00:00
Adrià Franch 63501b6d73 feat(libSceKeyboard): implement the keyboard library
Keyboard input follows libSceMouse: the video out event loop forwards SDL
key and focus events, whose scancodes are USB HID usages, and the library
keeps the pressed keys, modifiers and lock LEDs in a 16-entry history for
sceKeyboardRead and a snapshot for sceKeyboardReadState.
sceKeyboardGetKey2Char translates the 101-key arrangement; the 106-key
one throws and is listed as technical debt.

KeyboardData holds 16 key codes (96 bytes), not 6.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 19:00:23 +02:00
Michon 676bbea348 fix(libkernel): read, pread, AIO and APR write into guest memory as host writes
A file read into guest memory is a host write: before the I/O it pins the shared pages it
covers, which reopens any page armed for write tracking and keeps write tracking from arming
it again until the read ends, when the pages count as written. A destination the guest cannot
write fails with EFAULT before any I/O; read and pread throw as for any failed read, AIO
reports SCE_KERNEL_ERROR_EFAULT, and APR throws. APR also throws when a read ends before the
requested size.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 18:56:36 +02:00
Michon 17eefbbbd9 fix(libc): reserve the guest arena at its fixed range around what Windows already placed in it
The arena is always [0x200000000, 0x7200000000). Every free, allocation-granularity-aligned
piece of the range is reserved as a placeholder; what lies between the pieces (thread stacks
and other reservations Windows made before libc starts, unaligned slivers) and the
system-reserved range are holes, used ranges a release never frees. A failed query or
reservation of the range throws.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 18:50:15 +02:00
Adrià Franch fb6580ae36 feat(libSceCesCs): convert single characters between CP1252 and UTF-8
sceCesRefersUcsProfileCp1252 returns the CP1252 profile, and
sceCesSbcToUtf8 / sceCesUtf8ToSbc convert one character in each
direction. The five bytes CP1252 leaves undefined map to the matching
C1 controls, so every byte round-trips. Malformed UTF-8 and code points
outside CP1252 return the library's error codes.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 18:41:25 +02:00
Adrià Franch c548cd25b7 feat(libSceSsl): implement CA certificate queries and sceHttp2AbortRequest
sceSslGetCaCerts reports that no CA certificates are available and
sceSslFreeCaCerts clears the structure, in line with the library's
no-network behaviour. sceHttp2AbortRequest succeeds like
sceHttpAbortRequest. sceSslClose and sceSslGetSerialNumber keep throwing
and are listed as unknown signatures.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 18:35:02 +02:00
Adrià Franch 0a8cc7f543 feat(libSceHttp): implement URI parse, build and escape
sceHttpUriParse, sceHttpUriBuild and sceHttpUriEscape work on strings
only and are implemented. sceHttpCreateRequestWithURL, sceHttpReadData,
sceHttpSetChunkedTransferEnabled and sceHttpCreateEpoll follow the
existing no-network behaviour.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-01 18:15:50 +02:00
asimplestray b15f6800dd feat(shader): implement VOP3 I16/U16 min/max/med3 2026-10-01 16:11:33 +00:00
RomainROCH 91dd508c85 fix(libkernel): clear directory metadata on close 2026-10-01 16:48:10 +02:00
RomainROCH d7f89a6654 fix(savedata): preserve existing saves on replace failure 2026-10-01 16:40:38 +02:00
julienlgy 0c4dace39e feat(libSceHmd): add a disconnected-headset HLE stub 2026-10-01 14:18:10 +02:00
Dean Galvin b37365d2dd fix(recompiler): zero the high half of 16-bit SDWA results written as a whole dword
A 16-bit VOP1/VOP2 result in SDWA form with dst_sel:DWORD writes the whole register, so with
dst_unused:UNUSED_PAD the high half is zero. write16Bits treated dst_sel:DWORD as the plain
encoding and kept the old high half, which is right only for the non-SDWA form (GFX10 16-bit
instructions preserve the high bits). The decoder already marks SDWA destinations with
explicitSdwaDst; write16Bits now sends those through writeRawU32 like the other selectors.

GFX10 compilers rely on this to zero-extend f16 results before packing two of them with an
integer add, e.g. v_cvt_f16_f32_sdwa ... dst_sel:DWORD dst_unused:UNUSED_PAD followed by
v_lshl_add_u32 v2, hi, 16, lo. PPSA21564's FidelityFX depth-of-field combine pass packs its
near/far colours into LDS this way 60 times: whatever the low register held before leaked
into the high half, so green (and alpha) of the packed pairs came back huge or infinite while
red and blue stayed right. The bloom then spread the bad green over the intro cinematic.

agc_driver_sdwa_destination_tests runs the padded, preserved and plain encodings and the
packing idiom on the GPU against a model of the guest instructions.
2026-10-02 01:07:59 +13:00
boykopovar bc51b337ad
Merge pull request #148 from SamG-Coder/codex/shader-corpus-instructions
feat(shader): support 24-bit high products and fix image sample variants
2026-10-01 13:45:19 +03:00
SamG-Coder d9482ea3ae fix(agc): exclude hidden mesh words from vertex table lookup 2026-10-01 20:44:28 +10:00
SamG-Coder 4cd8e35366 fix(shader): preserve NGG passthrough launch and primitive inputs 2026-10-01 20:43:17 +10:00
SamG-Coder 7fea9dec9b test(agc): build mesh smoke test on Windows 2026-10-01 20:42:49 +10:00
SamG-Coder dfdbeae901 fix(shader): preserve comparison image flags in disk cache 2026-10-01 20:36:28 +10:00
boykopovar 4a82f04113 refactor(agc): organize driver modules into subdirectories 2026-10-01 13:31:24 +03:00
boykopovar 98b175f938 refactor(agc): fix deps after splitting 2026-10-01 13:24:48 +03:00
SamG-Coder f5e1fcfad3 fix(agc): bind native depth textures for comparison sampling 2026-10-01 20:23:58 +10:00
boykopovar 719b9328b3 refactor(agc): split driver into logical modules 2026-10-01 13:18:40 +03:00
SamG-Coder c329ad26b7 fix(shader): preserve upstream parameter validation during interpolation 2026-10-01 20:15:52 +10:00
SamG-Coder a8311e9d1a fix(shader): preserve interpolation instruction operands 2026-10-01 20:11:53 +10:00
boykopovar bbba29ea61 refactor(cmake): add local library configs and move test definitions 2026-10-01 12:44:01 +03:00
boykopovar a32715f71f refactor(cmake): require explicit runtime target for png and jpeg decoders 2026-10-01 12:38:06 +03:00
boykopovar 867167e2ff refactor(cmake): move prx.a import libraries to implib directory 2026-10-01 12:32:22 +03:00
boykopovar 61ba4d661a refactor(cmake): place all test executables in build tests directory 2026-10-01 12:28:06 +03:00
boykopovar b22ede6c93 refactor(cmake): move some libs test definitions to local cmakelists 2026-10-01 12:21:46 +03:00
SamG-Coder a6ea90b919 fix(libc): reject unsupported format extensions explicitly 2026-10-01 12:00:50 +03:00
SamG-Coder 4e2b200a91 fix(libc): invoke guest exit callbacks with the SysV ABI 2026-10-01 12:00:49 +03:00
SamG-Coder d9d34a47ac fix(libc): translate guest scanning and wide formatting arguments 2026-10-01 12:00:41 +03:00
SamG-Coder 3a651055bb feat(libc): support C locale wide stream input 2026-10-01 11:59:11 +03:00
SamG-Coder 7f834fc415 feat(libc): add C locale conversion and sample runtime exports 2026-10-01 11:58:51 +03:00
boykopovar e57ee5120d
Merge pull request #206 from Praetorian0420/main
Implement network control and socket functionality improvements
2026-10-01 11:41:41 +03:00
boykopovar 63071deb03
Merge pull request #205 from oneandonlydean/fix/recompiler-fma-mix-op-sel
fix(recompiler): select v_fma_mix source precision by OP_SEL_HI and the half by OP_SEL
2026-10-01 11:32:45 +03:00
boykopovar db5ce0f83c
Merge pull request #204 from oneandonlydean/fix/agc-misaligned-buffers-in-shader-data
fix(agc): patch the memory offsets of misaligned guest buffers in the shader data buffer
2026-10-01 11:31:57 +03:00
boykopovar 33e11c7ea2
Merge pull request #203 from oneandonlydean/fix/libkernel-direct-memory-memfd
fix(libkernel): back direct memory with a memfd on Linux
2026-10-01 11:31:43 +03:00
boykopovar 4a73353eda
Merge pull request #202 from oneandonlydean/fix/agc-misaligned-draw-snapshots
fix(agc): snapshot misaligned draw inputs from the offset the shader reads
2026-10-01 11:31:30 +03:00
boykopovar 4c1a92fe32
Merge pull request #199 from MichonGoddijn231849/fix/command-buffer-reserve
fix(agc): grow a command buffer whose free space is below its reserved words
2026-10-01 11:30:39 +03:00
boykopovar 5ab2fb00ee
Merge pull request #132 from oneandonlydean/feat/agc-cb-eliminate-passes
feat(agc): run CB fast-clear eliminate and DCC decompress passes within the DCC model
2026-10-01 11:29:22 +03:00
boykopovar 9623054a12
Merge pull request #181 from oneandonlydean/fix/agc-sample-2d-over-array
fix(agc): sample a 2D instruction over a 2D array texture through its first layer
2026-10-01 11:28:42 +03:00
boykopovar e4eaba6b2e
Merge pull request #198 from MichonGoddijn231849/fix/reserve-virtual-fixed
fix(libkernel): honour MAP_FIXED in sceKernelReserveVirtualRange and sceKernelMemoryPoolReserve
2026-10-01 11:28:18 +03:00
boykopovar cfb1f590bd
Merge pull request #197 from MichonGoddijn231849/fix/alias-view-granularity
fix(libc): map a shared-memory alias from the allocation granularity below its offset
2026-10-01 11:27:28 +03:00
Dean Galvin aa9a5c02a7 feat(agc): run CB fast-clear eliminate and DCC decompress passes within the DCC model
Draws with CB_COLOR_CONTROL MODE ELIMINATE_FAST_CLEAR (2) or DCC_DECOMPRESS
(6) were rejected as "only normal color rendering with copy ROP". On
hardware these full-target blits write the fast-clear value into the
fast-cleared pixels (or store the pixels uncompressed); the shader's output
never lands. In this driver's DCC model (surfaces stored uncompressed,
uniform fast-clear keys make every read return the clear value) that is:

- keys that are a clear code: the target's texels become that value and
  its keys read uncompressed. Reads see the same values before and after.
- uncompressed keys, or a target without DCC: nothing changes.
- mixed keys (per-block metadata), a mipmapped DCC target (its keys are not
  decoded) or a register clear of a texel over 64 bits: throw.

The texels go into the target's resident image (its refresh already
cleared it to a code's value; the register code is cleared on the GPU with
FillClear) and reach memory through its write-back, or into guest memory
on the CPU when there is no resident image. A resident image made under
other DCC keys is remade under the target's keys by the storage cache
before the pass reads it. DecodeColorMetadataPass
requires the draw to be only that pass: copy ROP, no depth or stencil
work, no multisampling, a viewport and scissor covering each target.
Indirect passes throw. The CB_COLOR decode moves into DecodeColorBuffer,
which also reads CB_COLOR_CLEAR_WORD0/1.

The register clear code (DCC key 0x20) had no value before: its keys were
read as the stored texels. A target under register keys now reads as its
CB_COLOR_CLEAR_WORD texel: a resident target is cleared to it before a draw
renders into it (then its keys read uncompressed), and a non-resident
target's copy starts from it.

Every decision that materializes a clear reads the keys through
CurrentDccKeys, which first waits for the batches up to the newest recorded
writer of the key range. The title's fast-clear fill of the metadata can
still be pending on the GPU when the next draw is decoded; reading the
stale bytes there made a later draw clear the target over the results of
the earlier ones.

The remaining CB modes (resolve, decompress, FMASK decompress) keep the
rejection, which now names the mode.
2026-10-01 20:59:03 +13:00
Dean Galvin 74abc7acc3 fix(agc): sample a 2D instruction over a 2D array texture through its first layer
A shader sampling with MIMG DIM 2D over a T# of type 2D array was
refused: "guest texture dimension disagrees with the shader's declared
image shape (shape 1, dimension 2)". The access carries no slice
coordinate, so the hardware samples slice 0 of the resource view, the
BASE_ARRAY layer, as it does for the storage access of the previous
commit.

A 2D array Texture now also makes a 2D view of that layer
(Texture::FirstLayerView), whether it holds its own snapshot or views the
surface's storage image, and the sampled binding uses it for such an
access. Every other shape/dimension mismatch still throws.
2026-10-01 20:57:49 +13:00
boykopovar 89570be51b
Merge pull request #191 from asimplestray/feat/shader-vopc-cmpx
feat(shader): implement VOPC I16/U16 cmpx compares
2026-10-01 10:52:25 +03:00
boykopovar e0b923621b
Merge pull request #178 from oneandonlydean/fix/agc-label-waits-after-submission
fix(agc): satisfy label waits from stores made after their submission
2026-10-01 10:50:47 +03:00
boykopovar aca6566746
Merge pull request #166 from asimplestray/feat/libc-tail
feat(libc): implement RaiseEv, catchReturnFromMain and reallocalign
2026-10-01 10:50:27 +03:00
boykopovar 116351b242
Merge pull request #163 from MichonGoddijn231849/fix/dcc-key-fill-coverage
fix(agc): make DCC key fills clear what reads through the surface's keys
2026-10-01 10:50:04 +03:00
boykopovar 8764959f2c
Merge pull request #137 from oneandonlydean/fix/pixel-inputs-at-parameter-slots
fix(recompiler): declare pixel shader inputs at their parameter slots
2026-10-01 10:49:16 +03:00
boykopovar bc3528be44
Merge pull request #136 from oneandonlydean/feat/pixel-input-vgpr-layout
feat(agc): centroid pixel inputs and NoPerspective by I/J pair
2026-10-01 10:49:01 +03:00
boykopovar 4a78540e38
Merge pull request #134 from oneandonlydean/feat/recompiler-structurize-by-cloning
feat(recompiler): structurize externally entered selection regions by cloning or route variables
2026-10-01 10:48:35 +03:00
Dean Galvin edb1358117 fix(agc): bind a 2D storage access to a 2D array surface as its first layer
A compute shader addressing an image with MIMG DIM 2D over a T# of type 2D
array was refused ("guest storage texture dimension disagrees with the
shader's declared image shape"). Such an access carries no slice
coordinate, so the hardware reads and writes slice 0 of the resource view,
which is the BASE_ARRAY layer of the surface.

The storage element is now bound through a 2D view of that layer of the
surface's shared storage image (StorageTexture::FirstLayerView, created on
demand per mip and released with the image). Every other shape/dimension
mismatch still throws, and both mismatch messages now name the shape and
the dimension.

The recorder test device sets formatProperties, which storage images need
to pick their Vulkan format.
2026-10-01 10:23:36 +03:00
boykopovar 74f84dd048
Merge pull request #130 from oneandonlydean/feat/agc-texture-min-lod
feat(agc): apply a texture descriptor's MIN_LOD clamp through the image view
2026-10-01 10:17:19 +03:00
Praetorian0420 e3eeac4a81 Implement network control and socket functionality improvements
- Enhanced the network control library to check for host addresses and update connection states accordingly.
- Added support for socket operations including connect, listen, accept, send, and recv in the UDP and TCP socket implementations.
- Introduced error handling for various socket operations, ensuring proper feedback for unsupported actions.
- Created comprehensive tests for both TCP and UDP socket functionalities, validating the expected behavior of the network stack.
- Refactored existing code to improve clarity and maintainability, including the removal of unused functions and the addition of necessary error checks.
2026-09-30 23:29:01 -05:00
Dean Galvin b556b87db3 fix(recompiler): select v_fma_mix source precision by OP_SEL_HI and the half by OP_SEL
v_fma_mix_f32 and v_fma_mixlo/hi_f16 read a source as f16 when its OP_SEL_HI bit is set, with
OP_SEL choosing the high half; otherwise the source is an f32. readMixF32 had the two bits swapped,
so a low-half f16 source (op_sel_hi set, op_sel clear) was read as the whole register's f32 bits.
PPSA21564's material shaders lerp packed f16 colours this way: red and blue (the low halves)
collapsed to near zero while green and alpha survived, giving the green cast on lit surfaces.

agc_driver_mix_precision_tests runs the mix encodings on the GPU against a model of the guest
instructions.
2026-10-01 16:21:48 +13:00
Dean Galvin 81d6f94ceb fix(agc): patch the memory offsets of misaligned guest buffers in the shader data buffer
A guest buffer view off minStorageBufferOffsetAlignment is bound from the
aligned offset below it, and the difference goes into the shader's memory
byte offsets (3dec6ced), but only when those live in the push constants:
a shader whose shader data is a buffer failed with "a guest buffer off the
storage buffer offset alignment in a shader whose shader data is a buffer
is not implemented".

The adjustment now goes into the shader data buffer's byte at
memoryOffsetDword * 4 + element, and a template's data refresh writes the
dispatch's words with the same patches applied.
2026-10-01 16:09:16 +13:00
Dean Galvin d544596283 fix(libkernel): back direct memory with a memfd on Linux
std::tmpfile() places the shared direct memory backing in /tmp, so a
title's direct memory counts against that filesystem's size (a tmpfs is
half of RAM by default): once /tmp fills, touching a backing page raises
SIGBUS. memfd_create gives the same shared memory pages without a
filesystem or its size limit.
2026-10-01 16:06:42 +13:00
Dean Galvin f5355d917a fix(agc): snapshot misaligned draw inputs from the offset the shader reads
A guest buffer view off minStorageBufferOffsetAlignment is bound from the
aligned offset below it, and the shader adds the difference to every
access (3dec6ced). PrepareDrawBindings (9f1c680b) copied such a read-only
in-place view into a snapshot that starts at the view itself, so the
shader read the snapshot that many bytes past the view.

The snapshot now covers the view from the binding's start.
2026-10-01 16:05:24 +13:00
asimplestray 889af1d542 feat(shader): implement VOPC I16/U16 cmpx compares 2026-09-30 23:55:29 +00:00
asimplestray 4816e105ad fix(tests): match default convention of ApplicationHeapRealign 2026-09-30 23:55:00 +00:00
asimplestray b42db4b6f3 feat(libc): implement RaiseEv, catchReturnFromMain and reallocalign 2026-09-30 23:55:00 +00:00
Michon 548162a203 fix(agc): grow a command buffer whose free space is below its reserved words
A command buffer with fewer free dwords than reserved_dw (an empty one whose
title allocates its storage in the callback, as Marvel's Wolverine does)
threw "reserved space exceeds command buffer capacity" before its callback ran.
Its available space is now 0, so the allocation goes to the callback with the
reserved words added, as for any other full buffer.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 00:02:31 +02:00
Michon 1d806a4688 fix(libkernel): honour MAP_FIXED in sceKernelReserveVirtualRange and sceKernelMemoryPoolReserve
Both ignored the flags and the requested address and reserved wherever the arena
had room, so a title that reserves a fixed range (Marvel's Wolverine passes
0x400010, MAP_FIXED | MAP_NO_COALESCE) and then uses the address it asked for
touched memory it never reserved. A fixed reservation now lands at the address,
after checking the range is free; other reservations are placed as before.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 00:00:22 +02:00
Michon e404e7f0aa fix(libc): map a shared-memory alias from the allocation granularity below its offset
MapViewOfFile3 takes an offset that is a multiple of the allocation granularity
(64 KiB), while shared guest pages are 16 KiB. An alias of a range starting at
a 16 KiB page that is not 64 KiB aligned was refused ("the section offset is not
a multiple of the allocation granularity"), so its host import failed. The view
now starts at the granularity boundary below the offset, the alias points past
the lead, and unmapping rounds back to the view's base.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 23:57:56 +02:00
Dean Galvin 258e4d526d fix(agc): fuse geometry shader halves into one self-contained program
sceAgcUnknownFuseShaderHalves (fd4700b9) fuses both kinds of halves at
the register level: the back half's registers with the front half's
program address in PGM_LO_ES (PGM_LO_LS for hull halves). For geometry
halves the driver then compiles that front half as the draw's whole
program (type 4, Stage::Mesh) and skips the back (Role::GeometryBack);
nothing links the two. The front ends in s_setpc_b64 s[6:7] and has no
s_endpgm, so the decode runs on into the s_code_end padding and the
program trailer. In PPSA21564 the geometry shader draws were skipped
with "unsupported SOPP opcode 31" (s_code_end) and "unsupported scalar
source operand code 115 at program counter 64".

Geometry halves are now fused into one Gs program: the front half's code
up to its final s_setpc_b64 s[6:7] (its length comes from the program
trailer), s_nop padding to the next 256 bytes, then the whole back half,
so the front falls through into the back. Its SH registers are the back
half's, with PGM_LO/HI_GS pointing at the copied back code, the ES
program address at the fused code, RSRC1 taking the larger VGPR and SGPR
counts of the two halves, RSRC2 taking the front half's user-SGPR count
(the SPI loads the front layout; the back reloads its own from memory
through s[0:1]), and the front's other SH registers except its checksum
appended. Context registers are merged the same way. Inputs come from
the front, outputs, specials and user data from the back; the scratch
size is the larger of the two.

Everything the fused Shader points to, including a copy of the header
itself, is written into the caller's memory after the code, and the
header is registered with the driver as a self-contained shader. Titles
pass memory without honouring the reported alignment, so the program is
placed at the first 256-byte boundary inside it, and the size query
returns the total plus 255 bytes of padding (alignment reported as log2
8). Halves with embedded constant buffers, a front half without a
trailer or final s_setpc_b64, a front half that needs RSRC2 state the
back half does not enable, and geometry halves without fused memory
throw.

Hull halves keep the register-level fusion, which the tessellation
path's separate local and hull programs fit. The half-type and stage
checks stay shared.

The driver now loads s[0:1] of a Gs program from its user-data address
registers whenever they are set, not only for GsFront programs, since
the back half of a fused program reloads its user data from there; a
program without those registers keeps zero there (from SamG-Coder's
8345fbc1).
2026-10-01 08:45:51 +13:00
Michon 4ce40333ea fix(agc): make DCC key fills clear what reads through the surface's keys
A buffer fill that starts at a surface's DCC keys and covers at least its key range (titles fill
the padding too) is a key fill. A uniform key fill leaves the image's texels and pending results
in place and records the fill's code: a sampled read through the surface's keys binds the clear
value, a color target through the keys starts from it at its next refresh, and reads that bypass
the keys still see the texels. Key scans return the fill's code until its write lands, and a
write-back of results drawn before the fill keeps the keys holding that code. The immediate clear
of the covered images is opt-in (APS5_KEYS_FILL_CLEAR=1): it fixes titles whose sampled reads
reach the pending image before a refresh, at the cost of reads that bypass the keys (Astro Bot's
title logo, reported by @oneandonlydean).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 21:40:15 +02:00
Dean Galvin a36ef52b33 fix(agc): decide a 64-bit label wait by the dwords its mask compares
A WAIT_REG_MEM_64 whose mask leaves the high dword out compares the low
dword alone, but the wait paths looked for all eight bytes: the
recorder's label table and the stores committed since the submission
want an entry for each dword, while a producer's RELEASE_MEM or
WRITE_DATA stores 32 bits, so neither ever satisfied such a wait, and the
held-at-submission check refused it when an earlier packet stored the
unrelated high dword.

Pm4::WaitAwaitedBytes gives the bytes that decide the compare (4 for
WAIT_REG_MEM and for a WAIT_REG_MEM_64 whose high mask dword is zero,
else 8), and the wait paths use it. The timeout report now prints a
64-bit wait's reference and mask (it printed the reference's two halves
as "ref" and "mask").
2026-10-01 08:39:53 +13:00
Dean Galvin 7df4ce4007 fix(agc): satisfy label waits from stores made after their submission
A title may reclaim a label (reset it to 0) as soon as the submission
that released it is done, trusting every queue waiting on it to have
passed its WAIT_REG_MEM within microseconds, as the CP polls from the
moment it reaches the wait. A worker that reaches a later wait of the
same submission long after (it records and compiles in between) found
the reset label and timed out.

A memory wait now also passes when
- a label store the driver committed (recorded on the GPU, as a
  completion action, or on the CPU) after the wait's submission gave the
  awaited bytes a value the wait accepts (the last four stores per dword,
  with their eventSerial stamps). Such a store belongs to this use of the
  label or a later one, since the title reset it before submitting.
- the awaited bytes held such a value when the game submitted, and no
  earlier packet of the queue (in the submission, or one still queued or
  running) stores to them.

A store made before the submission never satisfies a wait.
2026-10-01 08:39:53 +13:00
Dean Galvin 6a33a3d371 fix(recompiler): declare pixel shader inputs at their parameter slots
SPI_PS_INPUT_CNTL_n.OFFSET (bits 0-5) names the parameter slot pixel
input n reads, so several inputs may read one slot and an input may read
a slot the vertex stage never exports. With OFFSET bit 5 set and
FLAT_SHADE clear the input is the DEFAULT_VAL constant instead (bits 8-9:
0000, 0001, 1110, 1111). With OFFSET bit 5 and FLAT_SHADE both set the
slot in the low bits is passed through with its three vertices unchanged:
v_interp_mov P0, P10 and P20 read vertices 0, 1 and 2 rather than P0,
P1-P0 and P2-P0. The PS5 compiler writes such inputs as 0x422 and 0x423.

The old mapping masked OFFSET to five bits, so a defaulted input landed
on a real slot, and gave the second of two inputs reading one slot either
the same Location (two variables, "duplicate shader interface location")
or, when one was flat, a free Location the vertex stage never wrote
("graphics interfaces disagree at location N").

Now one input variable is declared per slot actually read, at Location =
slot, and inputs reading that slot share it. A slot read both flat and
interpolated (or through the perspective and linear pairs) is read per
vertex: flat readers take the provoking vertex, the others interpolate
with the barycentrics of their own pair. Pass-through inputs are read per
vertex at their slot without subtracting vertex 0, and reading one with
v_interp_p1/p2 is refused. Defaulted inputs read their DEFAULT_VAL
constant and declare nothing; inputs the program never reads are no
longer declared.
2026-10-01 08:38:47 +13:00
Dean Galvin cb66ec2004 feat(agc): centroid pixel inputs and NoPerspective by I/J pair
SPI_PS_INPUT_ENA/ADDR with PERSP_CENTROID (bit 2) or LINEAR_CENTROID
(bit 6) was rejected; PPSA21564 binds 0x326 (perspective center and
centroid, linear center, POS_X/Y).

The PS input VGPR layout now follows the hardware rule: SPI_PS_INPUT_ADDR
places every input it names in SPI order (two VGPRs per I/J pair, three
for the pull model, one otherwise), loaded or not, and ENA & ADDR selects
the loaded ones. ShaderPixelStageInfo carries inputAddr (replacing
perspectiveCenterVgpr) plus perspectiveCentroid and linearCentroid; the
recompiler places each loaded input with PixelInputVgpr. This also fixes
the system inputs, which were always written from v0 (psSystemInputBase
was never set), so POS_X overwrote the center I in any draw with
barycentrics enabled.

Draws are rasterized single-sampled, where the centroid is the pixel
center: with fragment barycentrics the centroid pairs carry the center
barycentrics (BaryCoordKHR for perspective; the linear center and
centroid pairs now get BaryCoordNoPerspKHR).

NoPerspective was decided for every parameter by one flag (LINEAR_CENTER
loaded). v_interp_p2 now records whether it reads the J of a linear or a
perspective pair, and a parameter is NoPerspective when it is read
through a linear pair; parameters read through neither keep the old
rule. A parameter read through both kinds of pair throws. Only pixel
stages consult this.

The request serializer moves to version 5 (older requests read back with
their loaded inputs as the layout); the cache key and the driver's draw
key compare and hash the new fields. The unsupported-input error names
ENA and ADDR.
2026-10-01 08:37:45 +13:00
Dean Galvin b57ab5a0e9 feat(recompiler): structurize externally entered selection regions by cloning or route variables
A selection whose region (the blocks reachable from its arms before its
merge) is also entered from outside the header cannot be expressed as a
SPIR-V selection construct, and the structurizer gave up with "semantic
block cloning is disabled". Pixel shaders hit this through a shared
discard tail (s_mov_b64 exec, 0 / exp null / s_endpgm) that several
selections branch to, compute shaders through short-circuit conditions
that jump into a shared body, and ray-traced compute passes through an
s_cbranch_execz that skips past a join into the middle of a selection.

Such a region is made single-entry in one of two ways, chosen per region
by its estimated translated size:

- Cloning (node splitting): the blocks the outside edges reach inside the
  region are copied and the outside edges redirected to the copies. When
  the header's merge is a shared linear return tail, giving the header a
  private copy of that tail is tried first. Each block now carries an
  estimate of the SPIR-V words it translates to. The per-instruction
  weights come from a fit of the recompiler's per-block output (before
  spirv-opt, phis excluded) over 8,300 blocks of captured shaders: VALU
  60, buffer and flat 120, SMEM 180, image 220, LDS 400. SALU (8) and
  exports (20) fit near zero and keep a small weight. Lane ops (120) and
  image_bvh_intersect_ray (2000) were too rare there to fit and are
  weighted for the wave and traversal expansions they need. A region is cloned only when it is at most 1024 estimated
  words and at most an eighth of the program (at least 256), and while
  all clones stay within a quarter of the program.
- Routing through a junction, for larger regions: every edge into the
  entered part (from outside, and from the header's own arms) and every
  edge from the arms to the merge is sent through a new empty junction
  block. Each rerouted edge first passes empty blocks that assign
  Boolean route variables (the IR's goto variables); the junction tests
  them in order to reach the edge's original target. The entered part
  then follows the junction and is emitted once. Branch conditions are
  still evaluated only at the end of their original blocks: a route
  variable records the edge a block already took, so a later SCC, VCC or
  EXEC write cannot change the route, and in the two-lane wave64 layout
  the source branch is combined across both halves as before while the
  route variable holds the same constant in both. Routing is refused
  when a rerouted edge is a back edge or leaves an indirect branch, when
  the region wraps around to a dominating block, or when it would change
  the natural loops or make the graph irreducible; cloning bounded by the
  program's estimated size is the fallback, and otherwise it throws with
  the header, the entered block and both reasons.

Selections whose arms only meet again after private return tails had no
post-dominator merge. When the existing rules find none, the merge is
now looked up with edges into private return tails ignored, or taken as
the other arm when one arm only returns; the candidate must still exit
the construct only through the merge. applyBlockOrder also remaps
indirect branch targets.

agc_shader_control_flow_tests (under ctest) covers hand-assembled
gfx1030 programs: the cloned shapes above, and routed ones (an
s_cbranch_execz into an expensive region with a loop, a region inside a
loop, nested entered regions, a shared body reached after SCC is
overwritten, early returns beside an entered region, an arm that only
returns). It checks that every selection construct exits only through
its merge, follows route variables to check that the structured graph
runs the same instruction ranges under the same branch conditions as
the original, bounds the cloned instructions, recompiles each program
for 64- and 32-lane subgroups, and keeps the routed execz program within
10% of the SPIR-V of the same program without the entering branch.
Given .req files it checks their graphs instead. agc_shader_replay --cfg
prints a request's graph, now with each block's estimate, before and
after structurization.
2026-10-01 08:36:11 +13:00
Dean Galvin 2be78b6965 feat(agc): apply a texture descriptor's MIN_LOD clamp through the image view
T# word1 MIN_LOD (unsigned 4.8, in levels of the whole surface) was
rejected. Sampled views now chain VkImageViewMinLodCreateInfoEXT
(VK_EXT_image_view_min_lod, enabled when the device offers the minLod
feature). Its minLod counts levels of the whole image exactly as MIN_LOD
counts levels of the whole surface, because the image holds every mip and
the view starts at BASE_LEVEL.

- A clamp at or below BASE_LEVEL cannot change which level a sample reads
  and is left off; one past the view's last level is bounded by it (the
  view selects that level anyway, and Vulkan requires the bound).
- A clamp that binds on a device without the feature throws.
- The texture cache already keys by the eight descriptor words, so views
  with different clamps are not shared.
- Storage views address one level: a clamp at or below that level is
  accepted, one above it still throws.
2026-10-01 08:30:05 +13:00
boykopovar a67b644ff6
Merge pull request #192 from MichonGoddijn231849/perf/validation-failure-memo
perf(agc): remember shader validation failures and reject repeats without throwing
2026-09-30 22:12:58 +03:00
boykopovar c71be475fc
Merge pull request #187 from MichonGoddijn231849/feat/demons-souls-exports
feat: export the AMPR command buffer waits and writes, sceAgcFuseShaderHalves, sceAgcSetSubmitMode, sceNpSessionSignalingCreateContext and sceNetEpollAbort
2026-09-30 22:03:54 +03:00
boykopovar 7b767489f3
Merge pull request #172 from STL1te/fix/savedata-params
fix(savedata): the native module keeps save directory params and moun…
2026-09-30 21:46:55 +03:00
boykopovar 78a34f8e82
Merge pull request #180 from oneandonlydean/feat/audioout2-dualsense-ports
feat(audio): play the DualSense speaker and vibration ports on its USB sound card
2026-09-30 21:35:16 +03:00
boykopovar d2d221a123
Merge pull request #179 from oneandonlydean/fix/pad-sdl-hidapi
fix(pad): build SDL with HIDAPI so DualSense output reaches the controller
2026-09-30 21:18:57 +03:00
boykopovar ced561723a
Merge pull request #177 from oneandonlydean/fix/agc-storage-image-moved-dcc-keys
fix(agc): remake a surface's storage image when its DCC keys move
2026-09-30 21:18:00 +03:00
STL1te a812d6314a fix(savedata): throw on a param file that cannot be read or has the wrong size
A .param file of a save directory or of save data memory that exists but cannot
be read, or whose size is not sizeof(SaveDataParam), was silently ignored or
truncated. It now throws, naming the file and, for a size mismatch, both sizes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 21:14:20 +03:00
boykopovar 52ab9e3544
Merge pull request #176 from oneandonlydean/fix/agc-indexed-draw-index-offset
fix(agc): apply GE_INDX_OFFSET as the base vertex of direct indexed draws
2026-09-30 21:13:57 +03:00
boykopovar d7ab5e371e
Merge pull request #175 from Qznad/feat/decoder-png
feat(pngdec): implement the PNG decoder
2026-09-30 21:12:56 +03:00
boykopovar f583d2638c
Merge pull request #165 from MichonGoddijn231849/perf/skip-report-single-write
perf(agc): write each skip report in one call and cap its request dumps
2026-09-30 21:05:39 +03:00
boykopovar 95f34bed3d
Merge pull request #171 from asimplestray/feat/kernel-time-signal
feat(kernel): implement Sleep, sigprocmask and pthread finalize
2026-09-30 21:03:48 +03:00
boykopovar c3aed31639
Merge pull request #169 from asimplestray/feat/kernel-file-ops
feat(kernel): implement file metadata ops and address conversion
2026-09-30 21:03:08 +03:00
boykopovar ba1d32f450
Merge pull request #168 from asimplestray/feat/kernel-psem
feat(kernel): implement pthread semaphore lifecycle
2026-09-30 21:01:53 +03:00
boykopovar 6756edb91f
Merge pull request #164 from MichonGoddijn231849/fix/munmap-across-mappings
fix(libkernel): unmap ranges that span several mappings
2026-09-30 20:55:43 +03:00
boykopovar f66789ada2
Merge pull request #186 from MichonGoddijn231849/fix/host-import-shared-alias
fix(agc): import shared guest memory through a read-write alias and never offer read-only pages
2026-09-30 20:41:23 +03:00
boykopovar fe712e7b9e
Merge pull request #101 from asimplestray/feat/rt-miss-config
feat(shader): configurable ray tracing miss fallback
2026-09-30 20:40:33 +03:00
boykopovar 488e678aa8
Merge pull request #161 from asimplestray/feat/libc-lifecycle
feat(libc): implement cxa lifecycle aliases and init_env
2026-09-30 20:35:36 +03:00
boykopovar 9444753275
Merge pull request #188 from MichonGoddijn231849/fix/d16-depth-integer-reads
fix(agc): read a 16-bit integer view of a depth plane as its stored values
2026-09-30 20:24:56 +03:00
Michon f4be8f435d fix(agc): throw when guest memory can be neither imported, aliased nor copied exactly
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 19:14:22 +02:00
asimplestray 976fa82054 feat(shader): configurable ray tracing miss fallback 2026-09-30 16:53:03 +00:00
asimplestray a4e755ccb1 feat(kernel): implement file metadata ops and address conversion 2026-09-30 16:51:37 +00:00
Michon 98d48ec8d2 perf(agc): remember shader validation failures and reject repeats without throwing
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 18:43:55 +02:00
boykopovar f881e021a8
Merge pull request #160 from asimplestray/feat/libc-wide-io
feat(libc): implement fputwc, fputws and fscanf
2026-09-30 19:40:31 +03:00
boykopovar ec0c39bf6c
Merge pull request #158 from carman24r/main
feat(agc): implement register commands and count patching
2026-09-30 19:33:52 +03:00
boykopovar e33abc1ad6
Merge pull request #155 from Pacuka/fix/sysmodule-unload-unknown
fix(sysmodule): unload unknown module ids as no-ops
2026-09-30 19:26:54 +03:00
boykopovar 4bfd97cdef
Merge pull request #154 from Pacuka/fix/userservice-invalid-argument
fix(userservice): report invalid arguments as 0x80960005
2026-09-30 19:25:46 +03:00
Michon 2b5f2d32d3 feat: export the AMPR command buffer waits and writes, sceAgcFuseShaderHalves, sceAgcSetSubmitMode, sceNpSessionSignalingCreateContext and sceNetEpollAbort
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 18:19:55 +02:00
boykopovar a56313375f
Merge pull request #138 from oneandonlydean/feat/agc-eop-interrupts
feat(agc): register driver eq events and deliver end-of-pipe interrupts
2026-09-30 18:56:52 +03:00
boykopovar 1c1d8fb9df
Merge pull request #135 from oneandonlydean/fix/agc-drop-exports-past-attachments
fix(agc): drop pixel shader exports past the draw's attachments
2026-09-30 18:55:39 +03:00
boykopovar 14b883dbbb
Merge pull request #133 from oneandonlydean/feat/shader-ngg-mesh
feat(shader): translate NGG geometry programs to mesh shaders
2026-09-30 18:54:44 +03:00
boykopovar 7411f17cb7
Merge pull request #128 from oneandonlydean/feat/videoout-open-param
feat(videoout): accept a zeroed open param
2026-09-30 18:54:15 +03:00
Michon bbf430e22d fix(agc): read a 16-bit integer view of a depth plane as its stored values
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 17:54:01 +02:00
boykopovar 6b731a9ee2 fix(agc): update graphics test to use pixel export mappings 2026-09-30 18:42:16 +03:00
Dean Galvin 48687eefab fix(contentexport): refuse init parameters without allocators or with reserved fields set
sceContentExportInit2 accepted any non-null parameter block. It now throws
when the malloc or free function is missing or a reserved field is not
zero. A test covers these refusals and the init and term order.
2026-09-30 18:35:36 +03:00
Michon 8b8b710b07 fix(agc): import shared guest memory through a read-write alias and never offer read-only pages
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 17:17:17 +02:00
boykopovar 119a74952a
Merge pull request #126 from oneandonlydean/feat/systemservice-hdr-tone-map
feat(systemservice): report the SDR tone-map luminance
2026-09-30 18:12:00 +03:00
boykopovar 077d4a487f
Merge pull request #125 from oneandonlydean/feat/pthread-prio-inherit
feat(libkernel): accept priority-inheritance mutexes
2026-09-30 18:11:38 +03:00
boykopovar c02a614b06
Merge pull request #123 from oneandonlydean/fix/flaky-shader-memory-coverage
test(agc): accept a bindless table entry captured across a page boundary
2026-09-30 18:11:17 +03:00
boykopovar f952bbeeb7
Merge pull request #121 from oneandonlydean/feat/linux-guest-write-watch
feat(agc): track guest memory writes on Linux with async userfaultfd write protection
2026-09-30 18:10:48 +03:00
boykopovar 03fa5a146e
Merge pull request #120 from oneandonlydean/fix/agc-untracked-target-results
fix(agc): keep render target results where the write tracker cannot prove memory fresh
2026-09-30 18:09:58 +03:00
boykopovar 3b1fc95ff4
Merge pull request #119 from oneandonlydean/feat/packed-vertex-formats
feat(agc): decode the packed 2_10_10_10 and 10_11_11 float vertex buffer formats
2026-09-30 18:06:04 +03:00
boykopovar d1bf55ca14
Merge pull request #118 from oneandonlydean/feat/dispatch-tunnel-hint
feat(agc): accept the dispatch tunnel hint
2026-09-30 18:05:45 +03:00
boykopovar 837a222b54
Merge pull request #117 from oneandonlydean/feat/cdbg-branches
feat(recompiler): conditional debug branches translate as never taken
2026-09-30 18:04:55 +03:00
boykopovar eaa47d66ed
Merge pull request #114 from oneandonlydean/fix/inert-depth-write
fix(agc): accept depth writes that the disabled depth test makes inert
2026-09-30 17:56:37 +03:00
boykopovar 6bceb47ba4
Merge pull request #113 from oneandonlydean/test/agc-graphics-tests-link
test(agc): link agc_driver_graphics_tests again, run it under ctest and bring its stale expectations up to date
2026-09-30 17:55:46 +03:00
boykopovar 1e1f0562c6 refactor(videodec2): use shared ffmpeg-core submodule + remove black fallbacks 2026-09-30 17:41:49 +03:00
Pacuka 7ac2468621 build(videodec2): leave FFmpeg off by default on Windows
FFmpeg's configure runs in the found sh and writes MSYS paths into its
Makefile, which a native MinGW make cannot open (Windows CI: "No rule to
make target '/d/a/.../3rdparty/FFmpeg/Makefile'"). Windows builds keep
the black-picture fallback unless ANYPS5_ENABLE_FFMPEG=ON is set in an
MSYS2 environment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:31:00 +03:00
Pacuka 62cb92716a build(videodec2): build FFmpeg from a pinned submodule
Add FFmpeg n9.0.2 as the 3rdparty/FFmpeg submodule (shallow) and build
it with ExternalProject_Add through its own configure and make, instead
of using the system libraries from pkg-config.

Only avcodec, avutil and swscale are built, with the H.264 decoder as
the single component (--disable-everything, --disable-autodetect), as
static PIC archives linked into libSceVideodec2.prx with
--exclude-libs,ALL. Without nasm the x86 assembly is disabled.
ANYPS5_ENABLE_FFMPEG=OFF, or a missing sh/make, keeps the black-picture
fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:31:00 +03:00
Pacuka a38ef6132f feat(videodec2): decode H.264 with FFmpeg
Adds libSceVideodec2. Access units (Annex B, or length-prefixed rewritten to
Annex B) are decoded by FFmpeg's H.264 decoder into the title's NV12 frame
buffers (256-byte pitch, chroma after the visible luma rows). Decode hands
out at most one picture per call, Flush drains the reordered ones, Reset
clears the decoder; timestamps and attached data travel with the picture.
FFmpeg is found through pkg-config and is optional: without it the decoders
return black pictures. guest_videodec2_tests checks the pictures of an
embedded stream against reference hashes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 17:30:58 +03:00
Dean Galvin dee927ea76 feat(audio): play the DualSense speaker and vibration ports on its USB sound card
A title can open AudioOut2 ports of type 0x3 (the controller's speaker)
and 0x6 (its two voice-coil actuators) next to its bed and object ports.
Both were folded into the TV mix, so the haptics came out of the PC
speakers as low thumps and the controller got nothing.

A USB DualSense is also a 4-channel 48 kHz sound card: channels 1-2 feed
the speaker and headset jack, channels 3-4 the left and right actuators.
When SDL lists such a card, a context with these ports opens it and
queues a grain on it with every push: the speaker port on channels 1-2
(a mono port duplicated) and the vibration port's left and right
channels on 3-4, at the port volumes and clamped. Both ports then leave
the main mix. The card's queue gets the main queue's silence cushion when
it runs dry and drops grains that run more than two grains beyond the
main queue, so the controller keeps pace with the TV. An unplugged card
is released (its ports return to the main mix) and looked for again
every 2 s. Without a card nothing changes, and other port types and
channel counts keep their routing.

SDL2's PulseAudio backend labels a 4-channel stream FL FR FC LFE instead
of quad, and the sound server then folds channels 3-4 into the speaker.
Under that backend the card is opened as 5.1 with FC and LFE silent and
the actuators on the back pair, which lands on the card's RL/RR.
2026-10-01 01:24:12 +13:00
Dean Galvin f25695fac7 fix(agc): remake a surface's storage image when its DCC keys move
The storage image cache keys a surface by memory, extent, layout and
storage format, and the image keeps the DCC key range of the first
descriptor that made it. When a later descriptor names other metadata
(the title reallocated the keys, or the memory held another surface
before), the image kept the old keys: fast clears of the new keys never
reached it, and its write-backs marked keys the surface no longer owns.

A descriptor whose DCC address differs from the cached image's now evicts
that image (its pending results are flushed first) and a new one is made
from memory under the named keys. A sampled view of another image's
pending results is taken only under the same keys. A descriptor without
metadata keeps whatever image the surface has.
2026-10-01 00:45:12 +13:00
Dean Galvin e2609a87be fix(pad): build SDL with HIDAPI so DualSense output reaches the controller
The bundled SDL was configured with SDL_HIDAPI OFF, so a DualSense went
through the generic joystick driver of the platform: no touchpad, no
light bar and no DualSense effect reports, which left the light bar,
trigger effect and (on Linux) rumble requests that PadInput already
sends through SDL without effect on the controller. With HIDAPI, SDL's
PS5 driver handles the pad: touchpad, light bar, rumble, trigger effects
and the motion sensors.

A USB pad always uses the driver's enhanced reports.
SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE enables them for a Bluetooth pad as
well, which otherwise stays on the simple report without effects.

pad_sdl checks that the bundled SDL is built with the HIDAPI joystick
driver.
2026-10-01 00:35:57 +13:00
Dean Galvin 13aecb4f7c fix(agc): validate a mesh stage's push block when it has no push data of its own
A mesh-stage program reads its draw parameters from the end of the
pipeline's push block (MeshDrawPushOffsetBytes), so its SPIR-V always
declares the push-constant variable. When its user data do not fit the
push range it has no push data of its own and
RecompileResult::pushConstants is empty, and validation refused the draw
with "invalid push constant interface".

Validation now expects the push block of every mesh-stage program and
still requires it to match the recompiler's metadata for the other
stages. agc_driver_mesh_tests draws the triangle list with a geometry
program given no push range for its own data.
2026-10-01 00:27:41 +13:00
Dean Galvin f4143d6186 fix(agc): apply GE_INDX_OFFSET as the base vertex of direct indexed draws
The GE adds GE_INDX_OFFSET to every index it fetches. The driver applied
it to auto draws only, so DRAW_INDEX_2 and DRAW_INDEX_OFFSET_2 fetched
from vertex 0 whatever the register held. Both packets now take it as
their base vertex, and like an auto draw they refuse a queue state without
the register (its reset value, 0, is part of the initial state).
2026-10-01 00:26:00 +13:00
Dean Galvin d8c7c0ccdf feat(agc): track guest memory writes on Linux with async userfaultfd write protection
GuestMemory::CollectWrites was built on the Windows arena's MEM_WRITE_WATCH
and answered 0 on Linux, so every cached copy of guest memory (textures,
resident render targets, buffers, DCC key proofs) read as changed at every
check: resident targets were stored and re-uploaded at every refresh and
unit shadows stayed off. Astro Bot's intro ran at ~3 fps.

libc gains GuestWriteWatch, the Linux counterpart of GetWriteWatch. Every
guest mapping libkernel makes (MapAligned: fixed, hinted and aligned) is
registered with one userfaultfd in asynchronous write-protect mode
(UFFD_FEATURE_WP_ASYNC: the kernel lifts a page's protection on its first
write without a handler thread, for user and kernel-mode writes alike), and
PAGEMAP_SCAN with PM_SCAN_WP_MATCHING reports the pages written since the
last scan of a range and protects them again in one call. Unmap forgets
the range. Direct memory is mapped from shared backings over its
reservation and a fixed remap replaces the mapping, so both register the
new mapping afresh. The watch is per mapping: a write through one mapping
of shared physical pages is not seen at another, so physical pages mapped
at more than one address leave the watch in every mapping of them.

A registered mapping reads as written until a collect covers it. The watch
keeps that itself instead of relying on how the kernel classifies pages
never faulted in: Linux 6.17 reports a range without page tables as not
written and leaves it unprotected, 7.2 reports it as written. The first
collect of a fresh range reports it written and write-protects it with
UFFDIO_WRITEPROTECT, which puts markers on its unpopulated pages
(UFFD_FEATURE_WP_UNPOPULATED), so from then on only real writes report.

Fallback: the userfaultfd is opened with UFFD_USER_MODE_ONLY where
vm.unprivileged_userfaultfd restricts it, and a probe at startup checks the
mechanism on scratch pages (a populated and an unpopulated page written
after protection report exactly, untouched ones do not). Without it (kernel
older than 6.7, no userfaultfd permission, headers without PAGEMAP_SCAN, or
APS5_NO_WRITE_WATCH=1) the watch reports unavailable and the tracker stays
unwatched exactly as before: CollectWrites answers 0 and callers compare
bytes. A range with a page outside the registered mappings also answers 0,
and a protection or scan that fails reports its remaining pages as written
and answers 0.

The driver's tracker keeps its contract and generations. On Linux its
block stamps live in 4 GiB leaves over the user address space, made on
first stamp, instead of the arena's flat arrays; the collect memo now works
on both platforms. GuestMemory::WriteWatched and Watched replace the arena
queries in UnitShadowEnabled and ShadowDestinationFor, so unit shadows run
on Linux over watched memory and stay off everywhere else. The Windows
arena path is unchanged apart from going through the same stamp helpers.

Host imports: a driver may lift the write protection of imported pages
itself. amdgpu validates the userptr BO behind a VK_EXT_external_memory_host
import with a writable HMM fault on every submission after the pages were
protected again, so PAGEMAP_SCAN reports them as written with no CPU store,
and a resident display image read as written at every present (found by
Pacuka on an RX 6650 XT with RADV: the presented image went black). NVIDIA
pins the pages once at the import and stays exact from then on. A probe at
device setup decides per device: it maps and watches scratch pages, collects
them clean, imports them, collects, submits a GPU copy that reads the import,
waits, and collects again. Pages written after the submission mean imports
resolve write protection: every import from then on takes its range off the
watch (GuestMemory::Unwatch) before it is made, so Watched is false for it,
CollectWrites answers 0 and callers compare bytes; GPU writes to watched
memory keep their MarkWritten stamps. The result is logged once:
"[write-watch] host imports resolve write protection: yes/no". A probe that
cannot run takes the unwatch side. APS5_WRITE_WATCH_IMPORTS=watch|unwatch
overrides the probe (default probe; anything else throws), and
APS5_NO_WRITE_WATCH=1 still turns the watch off. On the RTX 4090 the probe
reads 0 of 4 pages written after the GPU read (4 after the import itself),
so imports stay watched there.

The import itself lifts the protection once where imports stay watched:
on the RTX 4090 the pinning at vkAllocateMemory reports every imported page
as written (4 of 4 in the probe), with no CPU store. Such a report would
read as a CPU write over any GPU results pending in the range and drop
them. So every import of a watched range is made inside an import window
(GuestMemory::ImportWatched), under the tracker lock: the range is
collected right before the import, so earlier CPU writes are stamped as
usual, and again right after it, and what the window reports is stamped
"maybe written". Readers without pending results see it as a change
(UnchangedSince fails, ChangedBlocks reports it), so caches re-upload or
compare. Decisions about pending GPU results read it as untracked:
ChangedBlocks reports BlockMaybeWritten apart from BlockWritten, and the
drop rule, the write-back's keep blocks, the alias checks, the unit
shadow's stale drop and the whole-image stale checks (through the new
WrittenSince, which also answers false for a range off the watch) store
the results instead of dropping them. A real CPU store racing an import
also races the pending GPU writes to the same memory, which has no
defined order on hardware either, so the GPU results winning is
acceptable. From the second collect on the range is protected again and
watched normally. A range the watch does not cover whole, or a collect of
the window that fails, is taken off the watch instead.

An unwatched import stays off the watch for the rest of its mapping: a
remap registers the range afresh, the import kept over it takes it off
again at the next reconcile, and a re-import after an unmap follows the
decision. Unwatch invalidates the collect memo, so a collect memoized
before the import answers 0. A range that leaves the watch while a storage
image holds a generation for it no longer reads as CPU-written:
ChangedBlocks now tells whether the range is watched, and the drop rule,
the write-back's keep blocks and the alias borrow treat an unwatched range
as untracked (stored, never dropped), as a generation of 0 is.

Tests: guest_memory checks the watch through libkernel mappings (a CPU
store, a read, a kernel write through read(), another thread, a memcpy
across pages, an mprotect cycle, a partial munmap and a fixed remap) and
over a fresh 2 MiB-aligned mapping without page tables, checks direct
memory (watched, an alias takes the shared pages off the watch in both
mappings, a fixed direct remap over flexible memory is watched afresh), and
names the failing line and the reported pages. The recorder tests allocate watched
memory on both platforms, so the UnchangedSince, key proof, close race and
unit shadow tests run on Linux, and the storage refresh test gains a
watched variant: results kept on the GPU reach a CPU reader, and a plain
CPU store into one unit with newer results pending is found by the watch
alone. The recorder tests now also run the real import probe, check the
decision with the result injected (unwatch: an import leaves the watch, a
memoized collect, a partly imported range and the unimported neighbour
answer as they should, MarkWritten stamps only watched memory, a remap and
a re-import after an unmap follow the decision; watch: the import stays
watched and stamped), and check that results pending when their memory
leaves the watch are stored rather than dropped. A further test imports the
memory of a storage image with results pending in watch mode: the
results survive the import window and reach guest memory, a cache
generation taken before the import sees a change, the window reads as
maybe written and not as a CPU store, and a CPU store after it reads as
one again. Unit shadows and the
watched storage refresh report themselves as not run when imports are
compared.
2026-10-01 00:08:08 +13:00
Dean Galvin 33f9109999 feat(shader): translate NGG geometry programs to mesh shaders
The geometry path's merged ES/GS programs (VGT_SHADER_STAGES_EN.GS_EN)
were compiled as mesh-stage programs whose input metadata was never
filled in, so every such draw failed with "mesh shader translation
configuration is not supported".

Recompiler:
- BuildShaderStageInputInfo takes the draw's MeshConfiguration; the mesh
  input helpers (primitive size, step and counts) are implemented.
- The prologue emulates one NGG subgroup per workgroup: s2 GS_TG_INFO,
  s3 the merged wave info per wave, the GS vertex offsets (ES thread
  index times VGT_ESGS_RING_ITEMSIZE, odd strip triangles swapped), the
  primitive id, and the ES vertex and instance ids. An indexed draw's
  vertex id is read from the index buffer through a raw V# the driver
  puts in hidden user words 4..7.
- s_sendmsg GS_ALLOC_REQ becomes MeshAllocate. The epilogue zeroes the
  allocation first, clamps it to the output limits, culls primitives no
  thread exported and decodes the 9-bit vertex indices.
- The draw parameters live in the last six push dwords. A BDA fault in
  a mesh program no longer stops the invocation (as for other programs
  with barriers, the fault is recorded and the read returns zero), so
  every invocation reaches the subgroup barriers and the epilogue.
- The cache keys cover the mesh configuration; requests serialize its
  new esgsItemSize field (version 4).

Driver:
- DecodeShaderStages reads VGT_ESGS_RING_ITEMSIZE (now in the draw key)
  and sizes the subgroup for its ES vertices, GS primitives and outputs.
- Stages compile below the mesh draw parameters, which every mesh draw
  pushes; the mesh stage always takes part in the push range.
- The index-buffer V# is set per draw (per record on the CPU-resolved
  indirect path); the index-buffer alias check spares read-only
  elements.
- The workgroup and LocalSize checks count two guest lanes per
  invocation on 32-wide subgroups; mesh draws may carry a first vertex
  or instance.

agc_driver_mesh_tests (EXCLUDE_FROM_ALL, needs VK_EXT_mesh_shader)
recompiles a hand-assembled merged ES/GS program in the PS5 compiler's
layout and draws indexed and non-indexed triangle lists in one- and
two-wave subgroups and a triangle strip across odd-starting subgroups,
reading the pixels back. agc_shader_replay prints a request's draw and
mesh configuration.
2026-09-30 23:57:47 +13:00
Dean Galvin 544646ee39 fix(agc): keep render target results where the write tracker cannot prove memory fresh
Two paths lost a render target's results whenever CollectWrites answers 0
(no write watching: the Linux guest arena, or memory outside the Windows
arena), where every unit reads as changed at every check.

StorageTexture::Refresh dropped every pending result whenever the
surface's DCC keys read as a clear code, not only when the keys changed to
one. Draws never update the title's keys, so a resident target cleared
under a clear code keeps that code while holding newer draw results, and
the lookup of the next draw sampling the target re-cleared the image.
Astro Bot's intro composite sampled an empty UI layer on Linux. Only new
clear keys drop results now; results kept under the image's own clear code
are stored whole (the store marks every key uncompressed, as writeBack
does) and re-uploaded like any untracked unit.

A unit shadow slab is fresh only at a tracker generation and MarkShadowed
ignores generation 0, so a write-back retiled into a slab over unwatched
memory was never marked, published or read back: its texels were lost and
the next upload re-read the stale import. UnitShadowEnabled now also
requires a write-watched arena, and ShadowDestinationFor offers no slab for
a range outside the arena; those retiles go into the import, as with
APS5_NO_UNIT_SHADOW=1.

agc_driver_recorder_tests gains a GPU test over unwatched memory: a target
cleared under 0000 keys, drawn into, then refreshed keeps the draw's
texels and stores them to guest memory; no shadow slab is offered for it;
new 0001 keys still drop pending results.
2026-09-30 23:38:42 +13:00
Dean Galvin 52ffef8255 fix(agc): accept depth writes that the disabled depth test makes inert 2026-09-30 23:38:09 +13:00
Dean Galvin 4ad7103e56 test(agc): run agc_driver_graphics_tests under ctest and build it outside Windows
Nothing built the graphics test target, so it is now registered with the other AGC tests. It set
APS5_PIN_WAIT_MS through _putenv_s only, which does not exist outside Windows; it now uses setenv
there. The heap mirror tests need a write-watched guest arena and are skipped with a notice
without one, as the recorder tests already do.
2026-09-30 23:37:40 +13:00
Qznad a0e2f88048 feat(pngdec): implement libScePngDec on the shared PNG decoder 2026-09-30 11:10:00 +01:00
boykopovar fc0596240d
Merge pull request #115 from oneandonlydean/feat/primitive-restart-strips
feat(agc): primitive restart with an all-ones index for strips, and for lists with VK_EXT_primitive_topology_list_restart
2026-09-30 12:27:42 +03:00
boykopovar 64d2122386
Merge pull request #112 from oneandonlydean/fix/spirv-1d-capabilities
fix(agc): accept the core Sampled1D and Image1D SPIR-V capabilities
2026-09-30 12:20:25 +03:00
carman24r da35dcd89b
Merge branch 'boykopovar:main' into main 2026-09-30 05:05:49 -04:00
Dean Galvin cf721a2794 feat(agc): persistent shader disk cache and Vulkan pipeline cache
Every run recompiled every shader: the recompiler's variant cache and
the device's VkPipelineCache only lived in memory, and the first frames
of a title spent hundreds of milliseconds per large program in the
front end, the emitter and the optimizer.

Compiled variants (the SPIR-V plus the compiled shader info and binding
allocation that per-snapshot binding population needs) are now stored
on disk, one file per key, written atomically by a background thread,
and a later run loads them instead of compiling. The key holds every
input the in-memory variant cache matches on: the in-memory recompile
key (stage, code hash, stage registers, user data count, target), every
code word, the host subgroup size, the binding layout, the resource
specialization, and the values of the APS5_* switches the recompiler
sources read (found at build time; switches that only report are left
out). Entries live under a directory per source version, a build-time
hash of the recompiler and AGC driver sources and the build
configuration, and carry their key and checksums: an entry whose
format, version, key, size or checksum does not match, or whose payload
does not decode exactly, is ignored and recompiled. Directories no
build used for two weeks and stale temporary files are removed. Requests
under the debug probe bypass the disk cache.

The device's VkPipelineCache is loaded at creation when the file's
checksum and Vulkan header match the device (vendor, device and
pipelineCacheUUID; the driver version is in the file name), saved every
10 s while it grew, and saved at teardown.

Location: a shader_cache folder beside the running executable (not the
working directory), so the relinked game stays a self-contained folder;
ANYPS5_SHADER_CACHE_DIR overrides it. ANYPS5_NO_SHADER_CACHE=1 turns both caches off; the AGC
tests run with it set so they never write to the user's cache.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-30 12:01:25 +03:00
carman24r b9955d8e53
Update Registers.cpp
fix conflict I think
2026-09-30 04:55:24 -04:00
Michon 962fc34e5a fix(libkernel): unmap ranges that span several mappings
As on FreeBSD, a munmap range covering more than one registered allocation (or gaps between them)
is unmapped allocation by allocation instead of throwing "unmap crosses allocation boundaries".
GTA V unmaps such ranges in its Story Mode prologue.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-30 10:54:47 +02:00
STL1te 3a76b18646 fix(libc): the process starts in the root directory again
Starting in app0 when the folder exists made the working directory, and with it the tests, depend
on the layout next to the executable. The title opens its files by absolute /app0 paths, so the
fallback was never used: the route to story mode runs the same without it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-30 11:15:29 +03:00
STL1te 9cfdbff17c refactor(libc, kernel): drop the libc exports the title takes from its own libc.prx
The C11 thread layer (_Mtx_*, _Cnd_*, _Thrd_*, _Xtime_get_ticks, std::_Pad) and the libc additions
_FNan, _FDtest, _FExp, __udivti3, _Throw_Cpp_error, generic_category, localeconv, wcsncpy_s and the
aligned operator new came from the --skip-sce-module route, where our libc stood in for the title's.
With the title's sce_module loaded, its libc.prx exports every one of these NIDs and the relinker
lists the guest modules ahead of the host prx, so the imports never reach our copies. Checked both
by the NID tables (the executable imports them from libc, the guest libc.prx exports them) and by
making the four std::_Pad functions throw: the title boots, reaches the menu and loads story mode
without calling them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-30 10:56:03 +03:00
boykopovar 5e08eb4cce perf(memory): skip redundant page scans in shared write tracking 2026-09-30 09:59:51 +03:00
boykopovar f7c53a4481 fix(memory): restore write-watch tracking for shared mappings 2026-09-30 09:59:51 +03:00
boykopovar abb9c85266 fix(kernel): share direct memory mappings and track physical offsets 2026-09-30 09:59:51 +03:00
STL1te ee942805cd test(libc): guest_formatting runs only on Windows
It checks the Windows formatter (the guest va_list must stay untouched).
On Linux the guest variadic path hands the call to glibc, which advances
the va_list, and snprintf_nid_postfix with arguments on the stack
crashes; upstream never registered this test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 09:34:57 +03:00
STL1te 97443fd108 fix(savedata): the native module keeps save directory params and mounts at /savedata<N>
sceSaveDataSetParam dropped the params, and sceSaveDataGetParam and
sceSaveDataDirNameSearch returned zeros, so a title that checks the params of
the save it found took its profile for a new one and rewrote it with defaults
on every boot. The params now live in a <directory>.param sidecar next to the
save directory, written by SetParam (mtime refreshed) and returned by GetParam
and by the directory search, with the directory's write time when no param
was stored yet.

The mount point is /savedata<N>, as on the console: a title read its profile
through /host//_sm/0/Profile when the mount point had another shape, and that
path does not exist.

The module logs the first three calls of each entry point, like the core
module; APS5_SAVEDATA_TRACE lifts the limit.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-30 08:23:02 +03:00
asimplestray c6d098d487 feat(kernel): implement Sleep, sigprocmask and pthread finalize 2026-09-29 23:40:48 +00:00
asimplestray 064006b617 feat(kernel): implement pthread semaphore lifecycle 2026-09-29 22:13:07 +00:00
Dean Galvin 5a257bee52 feat(recompiler): conditional debug branches translate as never taken
S_CBRANCH_CDBGSYS, S_CBRANCH_CDBGUSER, S_CBRANCH_CDBGSYS_OR_USER and S_CBRANCH_CDBGSYS_AND_USER
(SOPP 0x17-0x1a) branch only while a debugger sets the conditional debug bits in the wave's
status, which never happens on a retail console, so they decode to one no-op opcode.
2026-09-30 10:56:31 +13:00
asimplestray 9f81bddf6d fix(libc): normalize thread-atexit module handle on Windows 2026-09-29 21:38:52 +00:00
Michon 8cf2f65806 perf(agc): write each skip report in one call and cap its request dumps
mingw's fprintf writes an unbuffered stderr a character at a time: a title skipping many draws
spent seconds per frame printing 17 KB RecompileRequest dumps (GTA V ran at 0.1 fps). Reports are
built into one string and written once; dumps stop after 8 per reason (APS5_SKIP_REQUEST_DUMPS,
-1 for all).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 23:36:02 +02:00
asimplestray 40eeb4be40 fix(libc): use guest calling convention for atexit callbacks 2026-09-29 21:33:44 +00:00
asimplestray 85a0ec2e69 fix(libc): convert sysv va_list for fscanf on Windows 2026-09-29 21:32:30 +00:00
asimplestray 3bf115585c feat(libc): implement cxa lifecycle aliases and init_env 2026-09-29 21:29:13 +00:00
asimplestray 77194e4561 feat(libc): implement fputwc, fputws and fscanf 2026-09-29 21:25:07 +00:00
carman24r a2c639ff2d
Update CMakeLists.txt
Missing a required Windows runtime dependency, causing a __gxx_personality_v0 linker error with windows build.
2026-09-29 16:43:10 -04:00
carman24r bf25ec499e
Update CMakeLists.txt
test build target and CTest registration.
2026-09-29 16:23:15 -04:00
carman24r 6032ba4af9
Create RegisterCommands.cpp
new regression tests.
2026-09-29 16:08:47 -04:00
carman24r 5afbeca23c
Update Packet.cpp
validated count-replacement helper.
2026-09-29 16:06:41 -04:00
carman24r 94035e6367
Update Packet.hpp
declaration for SetIndirectCount.
2026-09-29 16:06:07 -04:00
carman24r 01f6311bd3
Update IndirectRegisters.cpp
three register-count setters.
2026-09-29 16:05:27 -04:00
carman24r 1f1e39dccf
Update Registers.cpp
eight register-write and size-query implementations.
2026-09-29 16:04:50 -04:00
Pacuka a2520aa071 fix(sysmodule): unload unknown module ids as no-ops
sceSysmoduleLoadModule and sceSysmoduleIsLoaded already accept ids the
project does not know and log them; unloading such an id threw, so a title
that loads and later unloads an unknown module aborted at the unload.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:32:15 +02:00
Pacuka c618f53301 fix(userservice): report invalid arguments as 0x80960005
SCE_USER_SERVICE_ERROR_INVALID_ARGUMENT is 0x80960005; 0x80960002 is
NOT_INITIALIZED (the neighbouring NO_EVENT 0x80960007 and BUFFER_TOO_SHORT
0x8096000A already match the real sequence). The privacy getter returned the
raw value and now uses the constant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:31:53 +02:00
STL1te 03465e769c test(kernel): a second view of direct memory shares the page
Since direct memory mapped at two addresses is shared read-only instead of
refused, the guest memory test expected an exception that no longer comes.
It now maps the second view, reads the first view's bytes through it, and
writes through the first view once the second is gone, which faults unless
its protection came back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:28:49 +03:00
STL1te 6b36c050fe style: drop the branch's code comments per CONVENTIONS.md
Only the lines this branch added lose their comments; the commits before
keep them, with the reasoning behind each change, for whoever digs into
that code later.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:25:29 +03:00
STL1te 119560206d feat(agc-driver): heap ranges the host imports did not take are mirrored
An address-based build maps every readable registered range. A heap
range past APS5_HOST_IMPORT_MIB (or refused by the driver) was copied by
every such build: about 3200 ranges, 670 MiB and 500 ms per build on the
story-mode load, which then stalled. Such ranges are now served by
persistent host-cached mirrors, as the main image is, and the load
reaches its next failure.

- a heap mirror keeps no shadow; it keeps a write-tracking generation
  per 64 KiB block and a build copies only the blocks stamped since. The
  generation is stored by the copy, so a build that throws before it
  leaves no block marked current with stale bytes
- the build gathers its heap mirrors, sorts them and collects each run
  of adjacent ranges once (a collect costs about 4 us whatever its size;
  ~3000 mirrors took 16 ms per build, now about 3 ms)
- writable ranges are mirrored too: each build keeps the bytes its merged
  written ranges held at upload and write-back stores only what the GPU
  changed from them, so a CPU store made meanwhile stays; recorded work
  writing a range completes before a refresh reads it
- the mirrors are limited by APS5_HEAP_MIRROR_MIB (24 GiB by default); a
  mirror past it, or one whose buffer the driver refuses, stops the
  process. Heap mirrors are not given to descriptor sub-ranges, image
  mirror serials or reusable direct regions
- past APS5_ADDRESS_COPY_MAX_MIB (64 MiB by default) of committed bytes
  still copied, a build stops the process, naming the largest ranges and
  why each is copied (unreadable pages, an image mirror the driver
  refused, a range outside the write-watched arena, mirrors disabled)
- a direct memory page mapped at several addresses is read-only in every
  view while its range stays writable: copies, descriptor regions and
  mirrors take every readable page, write-back stores the writable ones
  and fails on a GPU change inside a read-only page instead of dropping it
- a store through the BDA table into a mirrored or copied range faults
  as before (only writable ranges imported in place are writable there);
  the fault now names the table range and that rule
- the BDA resource tests run with a storage range limit that holds the
  fault buffer and cover a mirror's fill, reuse, per-block refill, an
  interrupted refresh, a descriptor store beside a concurrent CPU store,
  and the copy limit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:23 +03:00
STL1te c8913314bc test(agc-driver): the graphics and BDA device tests link and run to the end
Both suites stopped at their first stale expectation, so nothing after
it ran; the BDA device tests did not link.

- the BDA device tests define the one recorder entry Resources.cpp
  reaches (no recorder) and fail loudly on the others
- Buffer::Invalidate refuses memory that is not host mapped again (lost
  in 8a69fef); the device tests expect it for a device-local buffer
- APS5_PIN_WAIT_MS (60000 by default, unchanged) bounds the wait before
  a mutation of a leased range is refused, and the refusal names it; the
  graphics tests set 200 ms, as they expect about a dozen refusals
- the expectations follow the behaviour the code chose since: a buffer's
  four-DWORD V# is refused as a T#, a sampler exceeds the mock's zero
  sampler slots, a V# at unmapped memory binds its committed pages only,
  a rect-list fragment input without a vertex export reads as zero,
  detiled rows span the padded block width, mip ranges are checked in
  address order, block-compressed and 128/129/132 formats use render
  target tiling, an XOR swizzle is refused only over a base that is not
  64 KiB aligned, DCC and partial mip chain views decode, a cube reads as
  a 2D array, the sampler fixture's max LOD fits the 4.8 field, a BDA
  program with barriers is accepted, a tessellation control stage is
  refused, a corrupt request fails on its signature and a newer one on
  its version
- the DCC comment in the texture decoder no longer claims metadata
  compression is refused

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:23 +03:00
STL1te ee1d34230d feat(kernel): sceKernelDebugWriteCppExceptionInfo prints the uncaught C++ exception
A title libc from sce_module calls it from __cxa_throw/__cxa_rethrow when
no handler is found, right before std::terminate, with the thrown object,
0x400 (meaning unknown), the demangled type name and what() (or null).
The console keeps it for the core dump; there are no guest core dumps
here, so it is printed to stderr. It was the only import such a libc
needed beyond the existing libs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:23 +03:00
STL1te 8dbff97486 chore(agc-driver): agc_shader_replay --spv writes the recompiled SPIR-V
--spv saves <request>.spv in the working directory for spirv-val; the usage
line lists --asm and --mem too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:22 +03:00
STL1te 4622efb4bb chore(agc-driver): APS5_WATCH_MEMORY watches several ranges
APS5_WATCH_MEMORY takes <hex address>:<hex bytes> ranges separated by commas;
a snapshot holds them back to back, in order, and is kept when any changed.
Each range matches its own heap base above bit 36, and watching starts once
all are mapped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:21 +03:00
STL1te d76ecfac06 fix(shader): DPP row and bank masks gate the instruction's VGPR write
The decoder puts an instruction's DPP fields on its source, and only a
destination carrying them has writeRawU32 keep the lanes the masks leave out
(and, without bound_ctrl, the lanes with no source lane). destinationOperand
copied them over, but no write used it, so every row was written: a wave64
scan adding the other row's total into the odd rows only (row_mask:0xa) added
it into every row, the prefix sums a key pass indexes primitives by came out
wrong, and the tree built from the keys held cycles its walkers looped on.

As in the Kyty recompiler (writes through DestinationOperand):
TranslateInstruction gives the destination its source's DPP fields once, and
a mac accumulator reads the destination without them (accumulatorOperand).
agc_dpp_write_tests checks a masked DPP add writes through DppUpdateU32.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:21 +03:00
STL1te f98b28d0d7 chore(agc-driver): debug aids for looping shaders
- The loop guard's report names the shader (its code address when its plan
  was built, now the translator's shader hash), and LoopGuardTripped() tells
  whether any dispatch reported one.
- APS5_WATCH_MEMORY=<hex address>:<hex bytes> (with APS5_SYNC_DISPATCH=1)
  keeps the last 64 contents of a range with the dispatch that left each, and
  writes them to watch_<n>_<program>.bin when the loop guard first trips; the
  address matches any heap base above bit 36.
- agc_shader_replay --mem prints the guest buffer V#s and which the shader
  writes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:21 +03:00
STL1te 3d3f71224e feat(shader): V#s at address 0 access nothing
A V# with records but a base address of 0 threw at bind time ("null shader
buffer descriptor address"), although a shader that never reaches that slot
works on hardware; an access through it would fault there, so a working
title does not make one.

Such a V# is specialized empty like one without records (every access out of
bounds) and binds the placeholder buffer; the draw cache's alias check skips
it as the build does. The tests expecting the old rejections are dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:20 +03:00
STL1te 6a73ec426f fix(shader): a selection whose arm continues merges where the other arm goes
findSelectionMerge took the nearest common post-dominator of a selection's
targets, computed across the loop's back edge. When one arm only continues
(reaching that block in a later iteration) and the other target is shared
with an enclosing selection, the shared merge was split off the header, the
post-dominator stayed where it was, and splitting repeated until the budget
threw.

Inside a loop, an arm that reaches the post-dominator only past the continue
or merge block now leaves the selection by continuing, and the merge is the
other arm's target; after one split that is the header's own synthetic merge.
agc_structurizer_tests builds the smallest such graph; it hit the budget
before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:20 +03:00
STL1te 3dec6ceda7 feat(agc-driver): bind guest buffers below their view at the storage offset alignment
A view whose offset in its GPU owner is not a multiple of
minStorageBufferOffsetAlignment could not be bound, and an address-based
build (its registered heaps imported whole) put descriptor-bound buffers at
arbitrary offsets inside them, so such dispatches failed.

GuestBufferMemory::Descriptor now binds from the aligned offset below the
view and reports the difference; ShaderResources stores it, per guest buffer
element, into the push constant block at the shader's memory byte offsets
(RecompileResult::memoryOffsetDword), which the shader already adds to every
access. Every push constant path (dispatches, recorded and synchronous draws,
draw recipes) takes the patches; the assembling overload of
Pipeline::PushConstants is gone. A shader whose shader data is a buffer fails
when it would need one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:19 +03:00
STL1te 000d0bf4f0 feat(shader): retire threads past a partial thread-dimension dispatch
A dispatch sized in threads (USE_THREAD_DIMENSIONS) launches a partial last
workgroup on RDNA2, but the host rounds it up to whole groups, so the extra
threads ran: past the end of a node list they read past it and wrote over
live records.

Such dispatches now compile a separate variant (ShaderComputeStageInfo::
partialThreads, keyed only on whether it is set) whose entry EXEC excludes
threads at or past the requested size. The size reaches the shader as three
shader data dwords after the memory offsets (StageInputKind::
DispatchThreadLimit), is mixed into the dispatch cache key and the result
memo hash, and serialized in recompile requests (version 3). Whole-group
dispatches keep their variant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:19 +03:00
STL1te 029dcdacac feat(agc-driver): null V#s access nothing, as on hardware
A V# without records (all zero, say, for a slot the taken path never
uses) makes every access out of bounds on hardware: loads read zero or the
format's default, stores and atomics are dropped. The recompiler now
specializes such a buffer as empty, so every access through it is out of
bounds, and the driver binds a small per-device placeholder buffer to the
element instead of rejecting the V#. A V# with records at address zero
still throws.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:18 +03:00
STL1te 21cb5676c7 feat(shader): buffer access through V#s computed on the GPU
A V# the SRT walker cannot compute (loaded from a descriptor heap at a
GPU offset, or built by the program) has no binding to hold it. Raw
dword loads and stores of 1-4 dwords through one now decode the V# in the
shader, apply the RDNA2 bounds rules (OOB_SELECT, stride, swizzle,
ADD_TID, format 0) and go through the BDA page table, as Kyty does.

Stores need Write permission, which only ranges that are a writable
allocation's host import get, so a store into a mirror or a copy faults
rather than being lost. The shader notes each written page in an
open-addressed set behind the fault record; once the work completed the
host marks those pages GPU-written, and an overflowing set throws.
Formatted, typed, sub-dword and atomic access through such a V#, and
their use outside compute shaders, still fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:18 +03:00
STL1te c1692bf939 feat(shader): read the bits of a D32 depth plane as a 32-bit integer texture
A sampled T# of a 32-bit integer format over a depth layout (a Z swizzle
mode) reads the raw bits of a depth plane, and a host cannot view a depth
image with an integer format. Such an image is specialized as float and
bound as the depth surface's float view: a fetch returns the same bits,
which the shader keeps as they are, and swizzle constants read as the
integers 0 and 1. Filtering is forced to point, as for integer formats.
The same T# over guest memory rather than a depth surface throws.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:18 +03:00
STL1te 19521c2ecd feat(agc-driver): occlusion counters from Vulkan occlusion queries
EVENT_WRITE PIXEL_PIPE_STAT_DUMP (event 0x39) dumps the DB sample
counters. The recorder, once a title asks for them, keeps an occlusion
query open over each batch (precise when the device supports it) and adds
the result to a running count when the batch is reaped. A dump drains
recorded work like a label and writes the count in the PS5 layout: 16 DBs
16 bytes apart, begin and end counters interleaved, the count in the
first and bit 63 marking each ready. Kyty and SharpEmu write a fixed
"visible" result instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:17 +03:00
STL1te 30c0cf1dfb feat(agc-driver): sample depth and stencil surfaces from their GPU images
A depth target lives only in a GPU image (its guest surface is never
written), so a texture over its depth or stencil plane now samples that
image through a view of the plane's aspect: R32_SFLOAT for D32, R16_UNORM
for D16, R8_UINT for stencil, one level and slice at the surface's extent.
Other shapes, and storage access to a depth surface, throw. Depth images
get the sampled usage, and the barriers after a render pass and before a
dispatch include depth attachment writes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:17 +03:00
STL1te b7eaabbc1e feat(kernel): share direct memory mapped at two addresses read-only
A title maps physical pages at a new address while the GPU still reads them
through the old one. Every view of such a page gets the same contents and
loses write access while the page is shared; the last view left gets its
protection back. A CPU write to a shared page faults, and views that differ
when one is unmapped (a GPU write through an import) throw, instead of the
views silently diverging.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:17 +03:00
STL1te 59a6998f1a fix(agc): EOP PatchData takes (cmd, data); -KRzWekV120 sets the index size
sceAgcQueueEndOfPipeActionPatchData is called with the packet and the new
64-bit label value only; reading a context id and a data selector from the
unused argument registers wrote garbage into the RELEASE_MEM, so fences
signalled with wrong values.

-KRzWekV120 is sceAgcDcbSetIndexSize with the per-instance object id flag
(VGT_INDEX_TYPE bit 14), as Kyty and SharpEmu build it. The no-op left the
previous index type in place, so 32-bit index buffers were read as 16-bit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:16 +03:00
STL1te 502a79381a feat(libs): system services for a console without PSN, dialogs or streaming
- NP: signed-out callbacks and reachability; owned add-on entitlements
  from anyps5-entitlements.ini next to the executable (or the file
  ANYPS5_ENTITLEMENTS names)
- web browser, message, player invitation and player selection dialogs
  finish without a UI; Remote Play, IME keyboard, SharePlay, live
  streaming and video recording lifecycles for a console without them
- app content temporary data mount, format and free space (download data
  quota from param.json); content export, search and delete lifecycles
- pad output-only calls, system service notice-screen flags, RazorCpu
  markers, ulobjmgr
- throwing stubs for the remaining imports, so missing behavior fails
  loudly

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:16 +03:00
STL1te 028d465e98 feat(audio): AJM MP3 through FFmpeg, 16-bit and ambisonic AudioOut2, voice
- AJM codec 0 (MP3) decodes with FFmpeg, prebuilt through the
  ffmpeg-core submodule as in Kyty; sceAjmBatchJobDecode and the Run job;
  the PCM encoding follows the job flags; other codecs throw
- AudioOut2 ports of 16-bit integer samples, and the ambisonics speaker
  array decode for the reported layout
- the voice library for a console with no headset, with a frame size for
  voice ports

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:15 +03:00
STL1te 2476bfda56 feat(agc-driver): depth/stencil and mip-chain targets, more color formats
- Depth/stencil: draws that test depth or stencil against a bound surface
  render with a GPU-only depth/stencil attachment (DepthSurface), cleared
  to DB_DEPTH_CLEAR/DB_STENCIL_CLEAR when made. Z test/write/function and
  per face the stencil function, operations and masks (BACKFACE_ENABLE);
  replacements by another value where Vulkan's single reference can carry
  them. Clear and copy draws, add/sub other than 1, array or mip views
  and MSAA throw, and texture reads of a surface's memory are refused.
  Scaleform menus mask with the stencil (REPLACE 0, ADD_CLAMP, EQUAL);
  their masked content was skipped before.
- Mipmapped color targets render through the resident image of the whole
  chain with a view of the mip, so mips in the packed tail are drawn too;
  CB_COLOR_VIEW's mip level is read from bits 26-29 (GFX10).
- Color: SNORM targets, UNORM16/SNORM16 exports, one-component formats
  honouring COMP_SWAP (A8), 32_R/32_GR/32_AR exports, linear rows padded
  to 256 bytes, BLEND_BYPASS.
- INDIRECT_BUFFER jumps are followed when copying a submission; thin 3D
  textures in display and rotated XOR swizzles; only the bytes the GPU
  changed are written back; resource registration.
- VideoOut: a flip stalls the GPU queue while the flip queue is full and
  holds the submitter back.
- APS5_DUMP_FRAMES_EVERY dumps every k-th presented frame.
- The graphics test target builds again (missing sources, a hand-aligned
  64 KiB buffer, stale expectations updated) and gains DepthStencilTests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:15 +03:00
STL1te fd4700b909 feat(agc): packet sizes, register writes, GS/HS fusion, jump patches
- packet sizes for the existing builders and the tessellation ring
  config
- direct register writes and end-of-pipe action data, type and cache
  patches
- GS/HS shader halves fused by merging their registers, after Kyty
- jump target patches; reserved jumps are allowed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:14 +03:00
STL1te c206f7049a feat(kernel, libc): memory, files and threads for retail title boot
libkernel:
- direct memory keeps its contents per physical page across unmap and
  remap; a page mapped at two live addresses at once throws
- sceKernelDirectMemoryQuery answers from tracked allocations
- SCE protections read back as set, GPU and AMPR bits included
- APR prefix path resolve, file size and stat by id, positional reads,
  fsync/pread/pwrite; directories open as descriptors on Windows
- sceKernelCheckReachability, getpeername, shutdown
- Dinkumware C11 threads (_Mtx_*, _Cnd_*, _Thrd_*) in the title libc
  layout; any pthread stack size, rounded at thread creation

libc:
- unaddressed guest mappings go to the system-managed area from
  0x2_0000_0000, leaving the application area to fixed mappings
- the process starts in /app0
- guest sscanf on Windows; a null %s prints as (null) as on FreeBSD
- localeconv, _FNan, _FDtest, _FExp, __udivti3, wcsncpy_s, aligned
  operator new, _Throw_Cpp_error

Tests: direct memory following physical pages, guest formatting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:13 +03:00
boykopovar 75a8668b5e
Merge pull request #116 from oneandonlydean/fix/json2-reference-getters
fix(json2): referValue returns null for a missing member, getters return references
2026-09-29 20:51:57 +03:00
boykopovar ffe1427017
Merge pull request #139 from SamG-Coder/codex/font-module-names
fix(font): build PS5 module-named font libraries
2026-09-29 19:29:12 +03:00
Julien Legay bd3e41b28f Implement player invitation dialog HLE stub 2026-09-29 19:07:03 +03:00
boykopovar 83358bec94
Merge pull request #146 from Qznad/feat/jpegenc
feat(jpegenc): implement the JPEG encoder
2026-09-29 17:52:36 +03:00
Qznad f9f02e3736 fix(jpegenc): link libc into the guest test for Windows exception support 2026-09-29 15:38:30 +01:00
boykopovar 2e9761753d
Merge pull request #86 from OverkillLabs/feat/misc-prx-additions
feat(prx): ConvertKeycode, VoiceChat stubs, PlayGo chunk-id fix
2026-09-29 17:30:06 +03:00
Qznad 6ef4ae3cec fix(jpegenc): hide shared encoder symbols and document grayscale output 2026-09-29 15:17:27 +01:00
Qznad aad41aa907 feat(jpegenc): encode images through the shared JPEG encoder 2026-09-29 15:17:27 +01:00
Qznad 94c7319202 feat(decoder): add shared JPEG encoder and decoder in core/Decoder/Jpeg 2026-09-29 15:17:27 +01:00
Qznad aa56049fbf feat(jpegenc): validate sceJpegEncEncode arguments 2026-09-29 15:17:27 +01:00
Qznad 2829cf92f4 build(jpegenc): add stb as a submodule 2026-09-29 15:17:27 +01:00
Qznad 98a5228cf7 feat(jpegenc): implement sceJpegEncCreate and sceJpegEncDelete 2026-09-29 15:17:27 +01:00
Qznad 16290424b9 feat(jpegenc): implement sceJpegEncQueryMemorySize 2026-09-29 15:17:27 +01:00
Qznad 442082612c feat(jpegenc): add parameter structs and real function signatures 2026-09-29 15:17:27 +01:00
OverkillLabs 020579d4fd refactor(prx): drop the PNG encoder from this PR
Per maintainer feedback: PNG encode/decode belongs together in a
future core/Decoder/Png shared by the relinker (icon loading) and
PRX layer, not a one-off libScePngEnc-only encoder. Reverts
libScePngEnc/Export.cpp to the upstream stub and removes the vendored
stb_image_write.h dependency, leaving ConvertKeycode, VoiceChat and
the PlayGo chunk-id fix.
2026-09-29 14:12:42 +03:00
boykopovar 563a1749dd
Merge pull request #111 from oneandonlydean/fix/s-getpc-absolute
fix(shader): make s_getpc_b64 return the shader's absolute address
2026-09-29 13:11:55 +03:00
boykopovar 9edb1f9a95
Merge pull request #110 from oneandonlydean/fix/device-replacement-race
fix(agc): don't let a queue worker record on a device the presenter is replacing
2026-09-29 13:06:30 +03:00
boykopovar c0755b9ec8
Merge pull request #102 from asimplestray/feat/kernel-aio
feat(kernel): implement Aio request lifecycle
2026-09-29 11:07:10 +03:00
boykopovar d841b8420a
Merge pull request #97 from SamG-Coder/codex/kernel-notifications
feat(kernel): deliver plain-text notifications to host output
2026-09-29 10:51:52 +03:00
boykopovar 4ed3199171
Merge pull request #84 from OverkillLabs/feat/pad-gamepad-haptics
feat(pad): motion sensors, rumble, adaptive triggers and light bar over SDL
2026-09-29 10:47:52 +03:00
boykopovar d998717588
Merge pull request #83 from OverkillLabs/feat/agc-shader-improvements
feat(agc,shader): remaining PM4 command-buffer opcodes and shader recompiler hardening
2026-09-29 10:35:36 +03:00
boykopovar 983109fe16
Merge pull request #81 from OverkillLabs/feat/kernel-libc-fixes
feat(libc,kernel): wide-char formatting, sub-tick waits, memory-pool querying, module loader wiring
2026-09-29 10:03:00 +03:00
OverkillLabs 56d061a350 style(prx): apply CONVENTIONS.md to misc PRX additions
Strip inline explanatory comments (comments are restricted to
technical-debt markers, #endif, and namespace-close trailers) from
HitLog.hpp, libSceConvertKeycode, libSceVoiceChat, libScePngEnc, and
the new hunk in libScePlayGo; add the missing #endif trailer comment
to HitLog.hpp's include guard. Rename the local helpers/params that
didn't match the naming convention: log_soft -> logSoft and
Readable -> readable (private free functions, camelCase), and
snake_case arguments (user_id, request_id, memory_address,
memory_size, output_info) to camelCase. NID export functions and
pre-existing upstream code (libScePlayGo's existing snake_case
parameters, PngEnc's vendored stb_image_write.h) are left untouched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 04:24:39 +03:00
OverkillLabs e532b19cee refactor(pad): trim comments and apply naming conventions
Bring the pad-gamepad-haptics diff in line with docs/dev/CONVENTIONS.md:
strip explanatory/rationale comments (struct layouts, algorithm notes,
rewired-NID rationale) down to code only, and rename the anonymous-
namespace helpers in PadState.cpp (Normalize/Fuse/EncodeZones/MaxOf/
ScaleStrength) to camelCase to match upstream's free-function style.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 04:24:39 +03:00
OverkillLabs 22b53e3f25 prx: implement scePlayGoGetInstallChunkId for real
Was a NotImplemented stub that returned an empty/undefined result.
For a package where every declared chunk is already local, the
installed-chunk set is identical to the full chunk set already
computed by ValidateChunks()/ValidChunks(), so this simply delegates
to the existing scePlayGoGetChunkId(). Driven by the title's own
playgo-chunkdefs.xml, not any hardcoded per-title chunk count.
2026-09-29 04:24:35 +03:00
OverkillLabs dc6baf629f prx: implement real libScePngEnc PNG encoder
Replaces the 4-stub placeholder with a working create/delete/encode
path backed by stb_image_write. The encode parameter block layout is
inferred by analogy with the decoder's and validated strictly
(dimensions, pitch, buffer sizes, readability of both the source and
destination buffers) before any pixel is touched; anything that does
not fit is rejected rather than guessed at. Handles RGBA and BGRA
source pixel formats.
2026-09-29 04:24:30 +03:00
OverkillLabs 556a7fcfdb prx: add libSceVoiceChat offline-safe HLE stub
Init/terminate/handler/event exports are real no-ops. Session and
channel request exports return SCE_VOICE_CHAT error SIGNED_OUT, since
voice chat sessions cannot be established without a network backend.
Matches the offline-stub pattern already used by other online-service
PRX modules in this project.
2026-09-29 04:24:20 +03:00
OverkillLabs 2982aa6a2e prx: add libSceConvertKeycode HLE module
sceConvertKeycodeGetImeKeyboardType is implemented for real (reports
keyboard type 0 for a valid user id). sceConvertKeycodeGetVirtualKeycode
has an unconfirmed ABI, so it only logs its raw arguments and reports
failure rather than guessing a pointer layout.
2026-09-29 04:24:16 +03:00
OverkillLabs 55ed2719d5 refactor: apply naming conventions and drop extern-C comment
Renames template parameters to the TKey-style the conventions doc
requires (TValue, TFunction), removes the extern "C" close comment
(not one of the two allowed structural exceptions), and replaces
the magic error/flag numbers left after the previous comment
cleanup with the existing SCE_KERNEL_ERROR_* constants and a named
RTLD_NOW constant so the code documents itself.
2026-09-29 04:20:28 +03:00
OverkillLabs a1814def3b style: strip explanatory comments per CONVENTIONS.md
Comments in this codebase may only mark technical debt (human-added
only), the end of #endif, and the end of a namespace, per
docs/dev/CONVENTIONS.md. Remove the inline rationale comments added in
the AGC PM4 opcode and shader recompiler robustness commits; the code
itself, the commit history, and the PR description now carry that
context instead.

Notably, Command::WriteMemSemaphore takes the corrected 4-argument
form (address, waitForMailbox, signalType, operation): an earlier
revision of this helper used a different, incompatible argument
order. sceAgc*MemSemaphore callers derive waitForMailbox/signalType
from the low two bits of clientCode, and operation from action
(0 = signal, 1 = wait). This ABI note previously lived as an inline
comment; it is recorded here instead per the no-comments convention.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 04:20:09 +03:00
OverkillLabs d9f8d87c27 refactor: strip explanatory comments to match repo conventions
Comments in this codebase may only mark technical debt (per
docs/dev/CONVENTIONS.md), plus the #endif and namespace-close
structural exceptions. Removes the descriptive comments added on
this branch across PreciseWait.hpp, FormattingWide.cpp, the
direct-memory pool query/free-run plumbing, and the module loader
wiring, keeping the two allowed structural markers intact.
2026-09-29 04:18:04 +03:00
OverkillLabs 5387aef3b7 Merge remote-tracking branch 'origin/main' into feat/kernel-libc-fixes
# Conflicts:
#	core/libs/prx/libkernel/DirectMemory/DirectMemory.hpp
2026-09-29 04:13:58 +03:00
Dean Galvin 6c98b6be58 feat(systemservice): report the SDR tone-map luminance
sceSystemServiceGetHdrToneMapLuminance was NotImplemented. Titles read
it at startup to set up their HDR tone mapping.

The presenter always outputs through a B8G8R8A8 sRGB-nonlinear swapchain,
so the display range the title has to map into is SDR: the maximum and
full-frame maximum luminance are the 100 cd/m2 SDR reference white and
the minimum is 0. A null output pointer returns
SYSTEM_SERVICE_ERROR_PARAMETER like the other getters here.
2026-09-29 13:56:45 +13:00
SamG-Coder 95bc3e6d73 fix(font): build PS5 module-named font libraries
(cherry picked from commit bfc08b5372b9b5e73dc0b277897799e0ee86c843)
2026-09-29 10:36:48 +10:00
Dean Galvin 962bc67952 test(agc): accept a bindless table entry captured across a page boundary
ShaderMemory captures guest memory per page, so a 32-byte table entry that straddles a page
boundary is held by two adjacent regions. The bindless test's coverage check required one region
to hold the whole entry, so it failed whenever the stack placed an entry at page offset 4080
(about one run in 75). The check now accepts adjacent regions that together cover the range.
2026-09-29 13:30:51 +13:00
Dean Galvin 2b0fa0bb74 fix(agc): drop pixel shader exports past the draw's attachments
An MRT export to a slot past the draw's color attachments (outside
CB_TARGET_MASK & CB_SHADER_MASK, e.g. MRT1 with only slot 0 enabled) is
dropped by the color backend. Vulkan discards a fragment output without
an attachment the same way, but validation rejected the draw ("fragment
shader must export float4 colors at locations below the attachment
count"). Such outputs are now left out of the written locations, and
only the exports that reach an attachment must be float4.
2026-09-29 13:26:41 +13:00
Dean Galvin 7447392f87 feat(videoout): accept a zeroed open param
sceVideoOutOpen threw for any non-null param. PS5 titles pass a 16-byte
open param whose first word is its size, so they could not open a port.

A param whose size word is 16 and whose other three words are zero
requests nothing beyond a null param and is accepted. Any other size,
or any non-zero option word, still throws.
2026-09-29 13:25:25 +13:00
Dean Galvin 70bbd700e2 feat(libkernel): accept priority-inheritance mutexes
scePthreadMutexattrSetprotocol threw for SCE_PTHREAD_PRIO_INHERIT, so a
title creating its mutexes with priority inheritance stopped at the
first one.

Guest thread priorities are recorded (scePthreadSetprio/Getprio) but
never applied to host scheduling, so there is no priority for a waiter
to lend to the owner: an inheriting mutex locks, unlocks and reports
errors exactly like a PRIO_NONE one here, and the protocol is accepted.
The POSIX pthread_mutexattr_setprotocol wrapper already accepts it.
Priority protection (PRIO_PROTECT, with its ceilings) and unknown
protocols still throw.
2026-09-29 13:22:21 +13:00
Dean Galvin 33d058fd35 feat(agc): register driver eq events and deliver end-of-pipe interrupts
sceAgcDriverAddEqEvent and sceAgcDriverDeleteEqEvent were NotImplemented,
so a title that waits on its equeue for the GPU to reach the end of a
command buffer could never be woken.

AddEqEvent now registers a graphics-core event (filter -14, ident = the
given id, EV_CLEAR, data counting the interrupts since the last wait) on
the kernel equeue and remembers the registration; DeleteEqEvent removes
both. An invalid equeue or deleting an event that is not registered
throws.

The driver delivers the interrupt when it executes a RELEASE_MEM whose
INT_SEL is non-zero. Such a packet is not deferred as a GPU label: the
recorded work before it is drained, its memory write (if any) is done,
and then the event registered with the id of the issuing queue is
triggered (0 for the graphics ring, the ACB queue id for compute), which
matches how titles derive their event ids from the ring they submit on.
2026-09-29 13:15:25 +13:00
Dean Galvin 8588b551a4 feat(agc): decode the packed 2_10_10_10 and 10_11_11 float vertex buffer formats
Vertex buffer formats 50-55 (2_10_10_10 UNORM, SNORM, USCALED, SSCALED, UINT, SINT: X in the low
10 bits, the 2-bit W on top) map to Vulkan's A2B10G10R10 packings, and format 36 (10_11_11_FLOAT:
X in the low 11 bits) to B10G11R11_UFLOAT, the same mapping TextureFormat uses for textures.
11_11_10_FLOAT (43), whose 10-bit X has no Vulkan packing, stays rejected.
2026-09-29 13:07:47 +13:00
Dean Galvin 8ada7510bd feat(agc): accept the dispatch tunnel hint
DISPATCH_INITIATOR bit 13 (TUNNEL_ENABLE) asks the SPI to launch the dispatch's waves ahead of
other work. It is a scheduling priority hint with no effect on the results, so direct and indirect
dispatches accept it like the other ignored modifier bits.
2026-09-29 13:05:49 +13:00
Dean Galvin 90855bbc18 fix(json2): referValue returns null for a missing member, getters return references
sce::Json::Value::getBoolean, getInteger, getUInteger and getReal return const references
(const bool&, const long&, const unsigned long&, const double&), so the guest reads the value
through the returned pointer. A value-returning implementation made callers dereference the value
itself. Cross-type conversions keep main's range rules and are stored on the node so the reference
stays valid.

Value::referValue(const String&) looks a member up without creating it: it returns null for a
missing key or a value that is not an object instead of inserting an entry or throwing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-29 13:02:54 +13:00
Dean Galvin 181457a0a6 feat(agc): primitive restart with an all-ones index for strips, and for lists with VK_EXT_primitive_topology_list_restart
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-29 13:00:42 +13:00
Dean Galvin 9735d82513 fix(agc): accept the core Sampled1D and Image1D SPIR-V capabilities
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-29 12:57:45 +13:00
Dean Galvin d9ac21c6c9 fix(shader): make s_getpc_b64 return the shader's absolute address
s_getpc_b64 produced the next instruction's offset from the start of the
shader, so code that addresses data stored behind itself built V#s at a
tiny address. Astro Bot's video-frame NV12->RGB pass draws its quad with
an NGG shader that fetches the four vertices from after its own code
(s_getpc_b64; s_add_u32 0x98; s_addc_u32) - the buffer resolved to 0xf0,
every vertex read as zero, the quad never rasterized and the PlayStation
Studios logo video stayed black.

The result is now GetShaderBase + offset. The resource walk already
evaluates GetShaderBase per request from the code address, so the V#
names the real data and the same code at another address still shares
its compiled variant.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-29 12:56:48 +13:00
Dean Galvin 7379830398 fix(agc): don't let a queue worker record on a device the presenter is replacing
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-29 12:55:36 +13:00
Dean Galvin 8f982168e2 perf(libc): replace the mspace block list with an ordered allocator
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-29 12:53:00 +13:00
boykopovar b01e0bbf52 fix(build): use portable save paths and validate all PRX libraries in CI 2026-09-29 02:24:56 +03:00
boykopovar cc41e847c8
Merge pull request #105 from SamG-Coder/codex/quake-native-imports
fix(relinker,libs): decode EMMS and add native string and thread APIs
2026-09-29 01:59:28 +03:00
boykopovar 9e3df3331c
Merge pull request #107 from asimplestray/feat/libc-mspace-reallocalign
feat(libc): implement sceLibcMspaceReallocalign
2026-09-29 01:46:19 +03:00
boykopovar c4c34ea3be
Merge pull request #80 from OverkillLabs/feat/avplayer-native-state-machine
feat(libSceAvPlayer): implement full AvPlayer state machine
2026-09-29 01:35:13 +03:00
boykopovar a5e7d1fb32
Merge pull request #79 from OverkillLabs/feat/net-rudp-offline-stack
feat(net): offline socket/epoll/resolver stack with FreeBSD errno mapping
2026-09-29 01:31:33 +03:00
boykopovar 23dad6b4d7
Merge pull request #78 from OverkillLabs/fix/msgdialog-state-machine
fix(libSceMsgDialog): real dialog state machine, auto-answer without UI
2026-09-29 01:27:31 +03:00
boykopovar 0d70866817
Merge pull request #77 from OverkillLabs/feat/savedata-core
feat(savedata): general mount/directory/memory-slot save-data core
2026-09-29 01:24:12 +03:00
asimplestray 02b431eb6d feat(libc): implement sceLibcMspaceReallocalign 2026-09-28 22:15:25 +00:00
boykopovar 4c2b052e35
Merge pull request #58 from oneandonlydean/feat/font-freetype
feat(font): port shadPS4's sceFont and sceFontFt on FreeType
2026-09-29 01:07:30 +03:00
SamG-Coder 5e708c1608 feat(kernel): add native pthread barriers and thread helpers 2026-09-29 07:39:01 +10:00
SamG-Coder 96b622c6ac feat(libc): add allocating strings and C locale wide conversion 2026-09-29 07:39:01 +10:00
boykopovar 64066b6e9a
Merge pull request #103 from boykopovar/feat/provide-release
Feat/provide release
Added a release workflow for v* tags: build Windows and Linux, run tests, and publish only if both platforms are successful. The release contains PRX archives, relinker executables, and documentation from docs/user. The build cache is reused.

- `prx-windows-v0.1.0.zip`
- `prx-windows-v0.1.0.tar.gz`
- `prx-linux-v0.1.0.zip`
- `prx-linux-v0.1.0.tar.gz`
- `relinker-v0.1.0.exe`
- `relinker-v0.1.0`
- `COMPATIBILITY.md`
- `INPUT_MAPPING.md`
2026-09-29 00:25:39 +03:00
asimplestray c25c543f1c feat(kernel): implement Aio request lifecycle 2026-09-28 20:39:33 +00:00
boykopovar 46382612cb fix(libcohtml): fix build libcohtml with target libs o linux 2026-09-28 23:15:22 +03:00
boykopovar 00261033fa refactor(docs): separated user and dev in docs + compatibility file 2026-09-28 22:58:17 +03:00
SamG-Coder d70d7ca268 feat(kernel): deliver plain-text notification requests to host output 2026-09-29 05:14:56 +10:00
boykopovar dee7ecb3d8
Merge pull request #27 from QDarkRex/refactor/kernel-error-header
refactor(kernel): share SCE kernel error codes through KernelErrors.hpp
2026-09-28 22:07:32 +03:00
boykopovar 829e8c14ae fix(tests): align agc flip waits and memory synchronization checks 2026-09-28 19:32:43 +03:00
boykopovar 1f595d883a fix(agc): propagate dispatch worker failures to waiting threads 2026-09-28 19:29:49 +03:00
boykopovar 39fd90b050 fix(kernel): orderly shutdown when closing the display window 2026-09-28 18:30:34 +03:00
boykopovar 143aec54c2 fix(agc): preserve inputs for deferred buffer copies 2026-09-28 18:08:09 +03:00
boykopovar 8e78ea0c28 fix(nid): always static linking for nid patcher 2026-09-28 16:28:11 +03:00
boykopovar 64732a64b6 fix(build): link json and fiber tests with libc 2026-09-28 14:18:35 +03:00
boykopovar d65a8ee633
Merge pull request #74 from SamG-Coder/main
fix(shader): support byte permutation and fix compiler lifetime bugs
Adds `V_PERM_B32` byte selection and fixes two existing bugs exposed while testing it: IR equality could merge buffer reads with different metadata, and concurrent shader compilation could crash during Windows thread-local destruction.

- Include instruction flags when comparing IR values so selections between different buffer offsets survive constant folding.
- Decode RDNA2 opcode `0x344` and translate all byte selectors through existing integer IR and the SPIR-V backend, including sign replication, zero/ones fill, and overlapping destinations.
- Reuse the existing `HostThreadLocal` helper for six destructible compiler scratch objects. Add async worker/destructor checks to the existing lifetime test. Scratch storage remains reusable.
2026-09-28 13:51:18 +03:00
boykopovar 0fe554943a
Merge pull request #73 from julienlgy/feat/lib-sce-mouse
feat(libSceMouse): implement stateful mouse API exports
Replace the libSceMouse stubs with an implementation that follows AnyPS5’s existing NID-based library integration. Mouse input comes from the host SDL event loop; this change does not add memory hooks or direct access to console HID devices.

Manage the mouse handle, button state, timestamps, and a thread-safe, 64-event history in src/mouse_impl.cpp. Reads are non-blocking.

Forward relative motion, supported buttons, vertical scrolling, and horizontal scrolling from libSceVideoOut’s SDL event loop.

Release pressed buttons when the window loses focus without reporting a hardware disconnection.
2026-09-28 13:45:13 +03:00
OverkillLabs 9673bce423 types: widen Ngs2WaveformBlock offset/size fields to 64-bit
PS5 grew Ngs2WaveformBlock's data_offset/data_size pair from 32-bit to
64-bit fields (40-byte record vs. the 32-byte PS4 layout). Standalone
correctness fix, unrelated to and non-conflicting with the pad work in
the preceding commits.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 13:43:40 +03:00
OverkillLabs 1d245cbeb2 videoout: bridge SDL sensor/haptics to pad output alongside existing input-mapping flow
Reconcile our SDL gamepad motion/haptics work with upstream's
configurable keyboard/mouse binding feature (PadInput now built around
Pad::LoadInputMapping() and a std::vector<Pad::InputBinding>). Upstream's
openFirstAvailableController()/openController(deviceIndex) flow and
HandleEvent/Update/publish logic for keyboard, mouse, and wheel
bindings are kept as-is (including APS5_NO_PAD_INPUT handling); the
sensor-enabling and host-haptics steps are grafted on as additional
work done once a controller is open:

- openController(deviceIndex) now also calls enableSensors() and
  marks a re-apply of the current guest output request pending.
- New sampleController()/applyOutput()/enableSensors() bring in real
  gamepad sampling, motion sensor reads, DualSense touchpad finger
  tracking, and pushing rumble/light bar/adaptive trigger state out via
  SDL_GameControllerRumble/SetLED/SendEffect. sampleController()'s
  button list and trigger/stick scaling are an exact copy of the
  button/trigger/stick reading that used to be inlined in publish()
  under the SDL_GameControllerGetAttached check (no deadzone added,
  no extra button remapped) -- only the motion, touchpad, and
  device-kind sampling on top of it are new.
- Update() now also samples the controller and applies pending output
  every tick, in addition to upstream's SDL_GameControllerUpdate() call
  and its keyboard/mouse/wheel timing logic.
- publish() seeds PadInputState from the sampled gamepad state first
  (buttons/sticks/analog triggers/motion/touch/device kind), then
  layers upstream's keyboard/mouse binding loop on top exactly as
  upstream had it, so a bound key still overrides the gamepad the same
  way it did before this merge. Upstream's L2/R2 button-flag derivation
  is preserved, just computed once at the end from whichever value
  (gamepad or a keyboard/mouse override) ends up in analogButtonsL2/R2.
- The background-events SDL hint is now set unconditionally (previously
  only inside the "not yet initialized" branch), since upstream's own
  VideoOutDriver already brings up SDL_INIT_GAMECONTROLLER before
  PadInput is constructed, which meant the hint would never run.

No changes were needed in VideoOutDriver.cpp: PadInput lazily
initializes SDL_INIT_GAMECONTROLLER itself in
openFirstAvailableController() (already a no-op if the subsystem is up),
and the class's public interface (default-constructible, HandleEvent/
Update) is unchanged, so upstream's existing `PadInput padInput;` /
HandleEvent / Update call sites keep working without modification.
VideoOutDriver.cpp's own independent flip-queue/vblank-telemetry rework
was left untouched as out of scope.

Confidence: high for the keyboard/mouse binding path (untouched) and
for the gamepad button/stick/trigger path (byte-for-byte copy of the
pre-existing mapping); the new motion/haptics/touchpad code is novel
and builds/links cleanly but has not been run against real hardware.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 13:43:27 +03:00
OverkillLabs 855176796b pad: real implementations for extended pad info/lightbar/trigger NIDs
Replace NotImplemented stubs with real implementations for
scePadGetInfo, scePadDeviceClassGetExtendedInformation/ParseData,
scePadGetExtControllerInformation, scePadSetLightBar,
scePadResetLightBar, scePadResetOrientation,
scePadSetMotionSensorState, scePadGetTriggerEffectState,
scePadSetProcessPrivilege, and scePadSetParticularMode, wiring them to
the new Pad:: output/orientation API. None of these NIDs are touched
by upstream's existing keyboard/mouse binding work, so this is a
clean additive change.

scePadSetVibration, scePadSetVibrationMode, and scePadSetTriggerEffect
are also given real implementations here, even though they were not
named in the audit's NID list: they are the only guest entry points
for the Pad::SetVibration/SetVibrationMode/SetTriggerCommand plumbing
added in the previous commit, so leaving them NotImplemented would
make the rumble/adaptive-trigger machinery unreachable from any title.

Every other previously-NotImplemented NID in this file (scePadGetHandle,
scePadSetAngularVelocityDeadbandState, scePadSetTiltCorrectionState,
scePadSetVibrationTriggerEffectWeakWhileEmbeddedMicInUse) is left
exactly as upstream had it; scePadOpen_nid_postfix, scePadRead_nid_postfix,
and scePadReadState are untouched (upstream's APS5_INVALID_ARG_EX
throw-based error handling is kept as-is, not replaced with plain
error-code returns).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 13:43:07 +03:00
OverkillLabs 4c349efe4f pad: motion sensor and haptics state/output plumbing
Add PadTouchPoint, motion-sensor fields, and a Mahony gyro/accel
orientation filter to PadInputState/PadState; add PadOutputState and
PadTriggerRequest plus Pad::SetVibration/SetVibrationMode/SetLightBar/
SetTriggerCommand/ResetOrientation/SetMotionEnabled and
PadFetchOutput_nid_postfix for pushing rumble, light bar, and adaptive
trigger requests out to the host pad. PadInfo/device-type constants
needed by the extended pad info NIDs are added to Pad.hpp.

Upstream's own PadInputState addition (analogButtonsL2/R2) is kept and
the new motion/touch fields are layered on top rather than replacing
it. Reported acceleration is converted from the internal m/s^2 fusion
scale back to g (rest = 1.0 on the "up" axis), matching upstream's
existing acceleration_y = 1.0f convention for a pad without sensors.

PadPublishInput_nid_postfix keeps upstream's change-detection (skip
the update, and the reported timestamp, when nothing changed), extended
to cover the new motion/touch/deviceKind fields so a pad with live
sensors still republishes continuously. Pad::ReadState still throws
when called before scePadInit, as upstream did.

The pad_dump.txt debug logger and an unreferenced mouse-emulated
touchpad helper are intentionally not ported: both were dead code,
never invoked, in the source they came from.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 13:42:51 +03:00
boykopovar 9f1c680b38 fix(agc): preserve per-draw input buffer contents until gpu completion 2026-09-28 13:35:53 +03:00
OverkillLabs e629f37481 feat(libSceAvPlayer): implement full AvPlayer state machine
Replace the stub AvPlayer export set with a general-purpose player state
machine covering the full API surface: sceAvPlayerInit/InitEx/PostInit,
AddSource/AddSourceEx, Start/StartEx, Pause/Resume/Stop/Close, IsActive,
CurrentTime, JumpToTime, SetLooping, SetAvSyncMode, SetTrickSpeed,
SetAvailableBandwidth, StreamCount/EnableStream/DisableStream/ChangeStream/
GetStreamInfo(Ex), and GetVideoData(Ex)/GetAudioData.

No real decoder is wired up: the player tracks lifecycle and timing state
and serves a fixed-length blank clip on a wall-clock media clock, firing
the READY/PLAY/PAUSE/STOP event callbacks a title expects from a real
playback session. This is enough for titles that gate progression on
AvPlayer's polling/event surface rather than on decoded frame content.

The non-native libSceAvPlayer/Export.cpp now forwards to the native
implementation via #include rather than carrying its own duplicate stub
definitions, consistent with how other libSceX/libSceX.native pairs in
this tree share one implementation.
2026-09-28 13:29:23 +03:00
OverkillLabs 2e8c1096fd feat(libSceMsgDialog): real dialog state machine, auto-answer without UI
Replace the unimplemented stubs with a working NONE -> INITIALIZED ->
RUNNING -> FINISHED state machine for the message dialog PRX. Open()
best-effort parses the SceMsgDialogParam layout to pick a sensible
default button (auto-focus-no variants answer No, everything else
answers Yes/OK), then auto-finishes the dialog after a couple of status
polls so a title that waits on a dialog for user input never blocks
forever. Progress-bar mode is instead closed by the title itself via
sceMsgDialogClose, with a time cap as a safety net. GetResult now fills
in a real SceMsgDialogResult (mode/result/buttonId) instead of leaving
the caller's buffer untouched.
2026-09-28 13:28:49 +03:00
boykopovar 76f1d48e60 debug(agc): detect gpu input buffer changes between recording and execution 2026-09-28 13:27:14 +03:00
OverkillLabs 0c41dc99d5 Agc: implement missing PM4 command-buffer opcodes (Jump/Rewind/Predication/MemSemaphore/CopyData/AtomicMem/DrawIndexMultiInstanced)
Fills in guest-facing sceAgc* entry points across Acb/Cb/DcbDraw/DcbFlow/DcbState/Misc
that were still stubbed with NotImplemented_nid_no_patch on current upstream, one layer
below upstream's Recorder rearchitecture:

- Command/Control.{hpp,cpp} (new): WriteJump, WriteRewind, WritePredication,
  WriteMemSemaphore helpers shared by the Acb/Dcb entry points below.
- Command/Memory.{hpp,cpp}: WriteCopyData, WriteAtomicMem helpers.
- Acb/Control.cpp: Jump/JumpGetSize, Rewind/RewindGetSize.
- Acb/Dispatch.cpp: DispatchIndirectGetSize.
- Acb/Memory.cpp: AcquireMemGetSize, CopyData(+Size), AtomicMem(+Size),
  AtomicGdsGetSize, PrimeUtcl2(+Size).
- Acb/Sync.cpp: CondExec(+Size), WaitOnAddressGetSize, EventWriteGetSize,
  QueueEndOfShaderActionGetSize, MemSemaphore.
- Cb/Dispatch.cpp: DispatchGetSize only (sceAgcCbDispatch itself left untouched --
  upstream's modifier mask 0xa038u|0x41u there is correct as-is).
- DcbDraw/DrawIndexed.cpp: DrawIndexMultiInstanced(+GetSize), still unimplemented
  even after upstream's own indexed-draw work.
- DcbFlow/Control.cpp: Jump, Rewind(+Size), and a real WaitUntilSafeForRendering that
  emits AgcDriver::RenderingWaitPacketHeader (recognized by the executor's fence wait
  in Driver.cpp) instead of upstream's plain-NOP stub, which the executor does not
  special-case.
- DcbFlow/Memory.cpp: AcquireMemGetSize, CopyData(+Size), DmaDataGetSize,
  AtomicMem(+Size), AtomicGdsGetSize, WriteDataGetSize.
- DcbFlow/Sync.cpp: CondExec(+Size), WaitOnAddressGetSize,
  StallCommandBufferParserGetSize, MemSemaphore.
- DcbState/Predication.cpp: SetPredication only (the file's 3 GetSize functions are
  left as upstream's diagnostic stubs, not real fixes).
- Misc/PacketInfo.cpp: sceAgcDcbGetSystemSoftwareVersion.

ABI correction: Command::WriteMemSemaphore takes the corrected 4-argument form
(address, waitForMailbox, signalType, operation). The Acb/DcbFlow sceAgc*MemSemaphore
entry points still expose the older (action, clientCode, address) guest signature;
their bodies now decode `action` into the signal/wait operation and the low two bits
of `clientCode` into signalType/waitForMailbox before calling the corrected helper.

Not ported (already superseded or out of scope per review): WriteMarker/WriteCustomNop/
WriteEventWrite/WriteCondExec/WriteDispatchIndirectAddress (duplicate upstream's
existing Marker/EventWrite/DispatchIndirect logic), Acb DmaData/DmaDataGetSize/
WriteData/EventWrite (already implemented upstream), DcbFlow EventWrite(+Size)
(upstream's version handles the 8-byte occlusion-address case more completely),
DcbDraw's other DrawIndex* entry points (already implemented upstream),
Misc/Trinity.cpp, Patch/WriteData.cpp, DcbState/Marker.cpp (all superseded by
upstream equivalents).
2026-09-28 13:25:15 +03:00
OverkillLabs cfe9a458cc kernel: direct-memory pool querying and module loader wiring
- DirectMemory: track each allocated block's type and extent in the
  physical pool (DirectMemoryBlock), splitting the record on a partial
  free, and expose DirectMemoryQueryBlock/DirectMemoryFreeRun. Wires
  sceKernelDirectMemoryQuery to answer with the real allocated range
  and type instead of a hardcoded one-page/type-3 guess, and
  sceKernelAvailableDirectMemorySize to report the actual free run
  instead of the whole remaining aperture. DirectMemory.cpp's mapping
  path already tolerates MAP_FIXED overlap into a registered range and
  already has honor-then-fallback address-hint handling and an
  ignored-flags mask, so it is unchanged here.
- MemoryPoolExport: implement sceKernelMemoryPoolBatch/Commit/Decommit/
  Expand/GetBlockStats/Reserve (previously all dead stubs) using the
  existing DoMprotect/DirectMemoryAlloc/DoReserveVirtual primitives and
  a small pool-state block counter.
- Module: wire sceKernelDlsym/sceKernelLoadStartModule/
  sceKernelStopUnloadModule to the existing host-module loader
  (dlopen_nid_postfix/dlsym_nid_postfix/dlclose_nid_postfix), replacing
  dead stubs. sceKernelGetModuleInfoForUnwind/FromAddr are unrelated
  and left as-is.
2026-09-28 13:18:25 +03:00
OverkillLabs 940f28d102 libc: wide-char formatting and precise sub-tick waits
- Add FormattingWide.cpp implementing vswprintf_nid_postfix and
  wprintf_nid_postfix, the only wide-char printf-family functions
  upstream had left as unimplemented stubs (Formatting.cpp's checked
  and unchecked narrow printf/scanf families are unaffected). Removes
  the dead vswprintf_nid_postfix stub from Export.cpp.
- Add PreciseWait.hpp: std::condition_variable::wait_for cannot return
  in under about one system tick on this MinGW toolchain regardless of
  the requested budget, even with NtSetTimerResolution; PreciseSleepUs
  uses a high-resolution waitable timer instead (~0.5ms vs ~15.6ms).
  Header-only for now: its guest-side callers (Equeue/EventFlag/
  Semaphore/AgcDriver wait loops) are out of scope for this change, so
  it is not wired into them here.
2026-09-28 13:18:07 +03:00
boykopovar 73e031a4dd perf(agc): downsample frame captures on GPU and queue disk writes 2026-09-28 13:06:15 +03:00
SamG-Coder 8cef034172 fix(shader): safely destroy compiler thread-local storage on Windows 2026-09-28 19:54:01 +10:00
OverkillLabs 77ed5e6d0c feat(savedata): mount aliasing, wildcard search, memory slots, async events
Rework the local SaveData implementation into a general-purpose, title-agnostic
backend used by both the native library and the standard libSceSaveData path:

- Directory aliasing: long save directory names are hashed into short mount
  point aliases (persisted to disk) so they fit the SDK's fixed-size mount
  point buffer, with the aliases reversed on directory search.
- Wildcard directory-name search (%/_ patterns) with sorting and optional
  reverse order, matching the DirNameSearch contract.
- Save-data "memory" slots: small per-user, per-slot blobs the title can
  set up, read and write without mounting a directory, backed by files under
  the save root with a companion parameter blob, size and range validation
  on every access, and a dirty flag consulted on commit.
- Async-flavored operations (backup, commit, memory sync) that queue
  SaveDataEvent records consumed through GetEventResult and can be bound to
  kernel event flags, plus transaction-resource and cancel/abort bookkeeping.
- Atomic file writes (temp file + rename) so a mid-write crash never leaves a
  torn save on disk, and corrected/duplicated SDK error code constants.
- Local storage app-status get/set/delete and transferring-mount support for
  PS4-to-PS5 style save transfers.

The native library keeps its own lighter-weight mount/memory implementation
(short "/_sm/<slot>" mount point aliases via the path-alias table) while
gaining the same per-user memory-slot separation, atomic writes and bounds
checking; the two implementations were merged by hand where upstream had
independently touched the native Export.cpp in the same area (backup/event
queue, short mount points) to keep both sets of improvements.

None of this is game-specific: it is a general local save-data backend that
works for any title and tolerates any user id.
2026-09-28 12:48:09 +03:00
OverkillLabs 3230352202 feat(net): offline socket/epoll/resolver stack with FreeBSD errno mapping
libSceNet: replace the always-fail stubs with a real offline network
stack. Sockets, epoll instances, memory pools and resolvers are tracked
in proper registries with create/destroy lifecycles; bind/listen/accept/
connect/send/recv/getsockopt/setsockopt/getsockname behave the way they
would on a console with no link up (bind and listen succeed locally,
connect/send fail with the errno a routeless host would give, blocking
calls such as accept/recv/epoll_wait return on close, abort or their
timeout). Infinite ("wait forever") timeouts are serviced in bounded
slices so a caller can never deadlock the process. Errno values match
the FreeBSD numbering the guest expects through sceNetErrnoLoc. Restored
sceNetGetsockopt and sceNetResolverStartAton (present upstream) using
the same registry-backed conventions as the rest of the rewrite.

libSceRudp: companion change giving the reliable-UDP library a genuine
context registry (init/create/bind/set-option/get-status) with
consistent error codes; connection attempts consistently fail since no
peer can ever be reached offline.
2026-09-28 12:45:34 +03:00
Julien Legay ddb8add753 feat(libSceVideoOut): route SDL mouse events to libSceMouse
Forward relative motion, supported button transitions, and horizontal and vertical scrolling from the existing SDL event loop. Reset pressed buttons on focus loss without reporting a device disconnect, and track window close and refocus transitions.

Link libSceVideoOut to the mouse library using the existing Pad integration pattern. Add targeted coverage for API errors, event mapping, focus changes, history overflow, and reopening.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-09-28 11:45:31 +02:00
Julien Legay 8fac768b9c feat(libSceMouse): implement stateful mouse API exports
Keep the existing Export.cpp entry point and System V ABI while moving mouse state into the library implementation.`n`nTrack initialization, a single handle, button state, timestamps, and a bounded non-blocking event queue. Define and assert the guest MouseData layout and expose an input publisher for the host backend.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-09-28 11:45:04 +02:00
Dean Galvin 588b5bb2bf build(font): build FreeType from a submodule instead of requiring a system package
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 22:03:39 +13:00
boykopovar 0d29a0a316 fix(video): terminate process on gpu and presentation thread failures 2026-09-28 11:46:18 +03:00
Claude 89ba1019e6
Merge upstream main into refactor/kernel-error-header
Upstream merged #25 and #26. Resolve DirectMemory.hpp and Equeue.hpp
by keeping this branch's side: the local error constants #26 fixed are
replaced by KernelErrors.hpp here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018emyZ4Rk8yoSJvxTFBe4DL
2026-09-28 08:34:25 +00:00
boykopovar 8bd030d531
Merge pull request #26 from QDarkRex/fix/kernel-error-codes
fix(kernel): use SCE kernel error codes in equeue, direct memory and mutex
| Constant | Before | After |
|---|---|---|
| `EQUEUE_ERROR_ETIMEDOUT` | `0x80010023` | `0x8002003C` |
| `EQUEUE_ERROR_EBADF` | `0x80010016` | `0x80020009` |
| `EQUEUE_ERROR_ENOENT` | `0x80010011` | `0x80020002` |
| `EQUEUE_ERROR_EINVAL` / `SCE_KERNEL_ERROR_EINVAL` (DirectMemory) | `0x80010005` | `0x80020016` |
| `EQUEUE_ERROR_EFAULT` / `SCE_KERNEL_ERROR_EFAULT` (DirectMemory) | `0x80010009` | `0x8002000E` |
| `SCE_KERNEL_ERROR_EAGAIN` (DirectMemory) | `0x80010002` | `0x80020023` |
| `SCE_KERNEL_ERROR_ENOMEM` (DirectMemory) | `0x80010007` | `0x8002000C` |
| `SCE_KERNEL_ERROR_EACCES` (DirectMemory) | `0x80010004` | `0x8002000D` |
| `SCE_KERNEL_ERROR_EDEADLK` (Mutex.cpp) | `0x80020023` (= EAGAIN) | `0x8002000B` |
2026-09-28 11:18:14 +03:00
boykopovar 089685b93d
Merge pull request #25 from QDarkRex/fix/audit-2026-09
fix(kernel,audioout,relinker): thread/mutex correctness fixes and --windows-gui
### libkernel (threads, mutexes, condition variables)
- **Deadlock in `scePthreadCondTimedwait` (normal/error-check mutexes):** `_owner` was not restored after the wait. If another thread locked and unlocked the mutex during the wait, the waiter woke up owning the mutex while `_owner` was empty. Its next `scePthreadMutexUnlock` returned `EPERM`, leaving the mutex locked forever (`lock → timedwait → unlock` pattern).
- **Wrong timeout code:** `SCE_KERNEL_ERROR_ETIMEDOUT` in `Cond.cpp` was `0x80020062`; it is `0x8002003C` (FreeBSD `ETIMEDOUT` = 60, matching `Semaphore.hpp`).
- **`scePthreadSelf()`** returned `nullptr` on Linux, and on both platforms for threads not created by `scePthreadCreate` (including the main thread). Such threads now get a lazily adopted, non-joinable handle (`scePthreadJoin`/`Detach` on it return `EINVAL`).
- **Linux `scePthreadExit`** skipped `FinishThread`, so `scePthreadJoin` got a garbage return value. Cleanup now runs from an RAII guard, so it survives glibc forced unwinding.
- **Linux detached threads** were never freed. They now use the same reference count as on Windows.
- **Recursive mutex unlock** by a non-owner, or with a zero count, was UB (`std::recursive_timed_mutex::unlock`). It now returns `SCE_KERNEL_ERROR_EPERM`, and `_owner`/`_count` are also saved and restored around a recursive cond wait.
- **`sceKernelLseek`** returned `int` instead of `off_t`; offsets above `INT_MAX` threw.
- **`sceKernelDeleteSema`** implemented: waiters are woken with `SCE_KERNEL_ERROR_EACCES` and the object is freed once they leave.

- `sceAudioOutOpen` accepted `freq == 0` / `len == 0`; the frequency was later used as a divisor. It now returns `SCE_AUDIO_OUT_ERROR_INVALID_SAMPLE_FREQ` / `INVALID_SIZE`.
2026-09-28 11:09:59 +03:00
boykopovar 94c443e32f refactor(agc): make frame timing logs optional by cmake option 2026-09-28 10:51:29 +03:00
Claude 0b560c6af1
Merge fix/audit-2026-09 into refactor/kernel-error-header
Bring in the Linux scePthreadExit fix from #25.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018emyZ4Rk8yoSJvxTFBe4DL
2026-09-28 07:47:20 +00:00
Claude a60256ea4d
fix(kernel): exit POSIX guest threads without forced unwinding
On Linux scePthreadExit called pthread_exit, whose forced unwind runs
the personality routine of every guest frame. Those resolve to
libc.prx's __gxx_personality_v0, which cannot read libgcc's unwind
context and aborts, so guest_thread_self crashed on Linux.

Record a jump target in the thread start routine and longjmp back to it
from scePthreadExit instead. Like _endthreadex on Windows, this skips
the guest frames without unwinding them; the start routine still
releases the thread normally. Threads not created by scePthreadCreate
keep the pthread_exit fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018emyZ4Rk8yoSJvxTFBe4DL
2026-09-28 07:47:12 +00:00
Claude 2aced8e8d9
Merge fix/audit-2026-09 (with upstream main) into refactor/kernel-error-header
Bring in the resolved #25 branch, which already carries upstream main
including boykopovar/AnyPS5#10, and re-apply the KernelErrors.hpp
refactor onto the rewritten files:

- Equeue: drop the local EQUEUE_ERROR_* constants and use the shared
  SCE_KERNEL_ERROR_* names.
- Pthread Attr/Thread: drop local error constants and include
  KernelErrors.hpp.
- Pthread Cond/Mutex: take upstream; they no longer define local
  SCE_KERNEL_ERROR_* constants.
- Semaphore: drop KERNEL_SEMA_ERROR_* in favour of KernelErrors.hpp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018emyZ4Rk8yoSJvxTFBe4DL
2026-09-28 07:40:42 +00:00
Claude a28cfb7585
Merge upstream main into fix/kernel-error-codes
Resolve the conflict with boykopovar/AnyPS5#10 in Pthread/src/Mutex.cpp
by taking upstream: its rewrite already returns EDEADLK as 0x8002000B.
The equeue and direct memory error code fixes are unaffected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018emyZ4Rk8yoSJvxTFBe4DL
2026-09-28 07:36:16 +00:00
Claude 210987745c
Merge upstream main into fix/audit-2026-09
Resolve conflicts with boykopovar/AnyPS5#10 (sce module loading) and
later upstream changes.

- Pthread Cond/Mutex: take upstream. It already releases mutex
  ownership across condition waits, returns ETIMEDOUT 0x8002003C, and
  rejects unlocks from non-owners for every mutex type.
- Pthread Thread: keep upstream's lifecycle, Windows adoption and job
  affinity; re-apply the POSIX fixes on top: reference-counted
  release on join/detach/exit, self-join rejection on both platforms,
  and scePthreadSelf adoption for threads not created by
  scePthreadCreate.
- Semaphore: keep upstream's TimedWait::Condition and wait tracing;
  re-apply sceKernelDeleteSema waking waiters with EACCES.
- Relinker: keep --windows-gui alongside upstream's --skip-sce-module,
  trampoline-aware Patch signature and new Python tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018emyZ4Rk8yoSJvxTFBe4DL
2026-09-28 07:34:25 +00:00
boykopovar 34f0379d8a
Merge pull request #48 from oneandonlydean/feat/linux-fibers
feat(fiber): implement fibers on linux
The state machine, the cross-thread resume handling and the entry trampoline are now shared between platforms. Only the context switch differs:
- `Aps5FiberSwitchStack` saves the SysV callee-saved set (`rbp rbx r12–r15`, MXCSR and the x87 control word) instead of the Win64 set.
- `Aps5FiberTrampoline` passes the fiber in `rdi`.
- There is no TIB to update, so `CurrentBounds`/`SetBounds` do nothing on Linux.
2026-09-28 10:22:04 +03:00
boykopovar 3b4e4f6de6
Merge pull request #65 from SamG-Coder/main
fix(agc): keep BGRA color targets resident between draws
BGRA color targets fail the exact guest-texture-format lookup and fall back to a synchronous framebuffer round-trip for every draw. This keeps them resident using compatible RGBA storage with the original BGRA attachment view. Presentation checks the actual display channel order, attachment views request only attachment usage, and host-write barriers include the host stage.

This follows the existing linked PRX/Vulkan path. It adds no interpreter, separate runtime process, or new shader compilation path.
2026-09-28 10:07:16 +03:00
boykopovar 861e79acfc
Merge pull request #62 from oneandonlydean/feat/agc-acb-markers
feat(agc): ACB markers, index buffer unbinding and address in errors
- The DCB marker helpers move from an anonymous namespace in `DcbState/src/Marker.cpp` to `Agc::Marker::Push`/`Pop` (declared in `Marker.hpp`). The ACB entry points use the same helpers, so ACB and DCB markers produce the same custom NOP packets. `SetMarker` is a push followed by a pop, and returns the push packet, as on the DCB. The color is ignored on both, as before.
- `sceAgcDcbSetIndexBuffer` emits the packet with address 0 instead of rejecting it. A non-null address still has to be 2-byte aligned.
- `Agc::Command::CheckAddress` includes the rejected address in its message.
2026-09-28 10:03:44 +03:00
boykopovar 6686e15ee4
Merge pull request #61 from oneandonlydean/feat/agc-dma-gds
feat(agc): DMA_DATA cache policy hints and GDS source/destination
- **Cache policy:** the source (bits 13–14) and destination (bits 25–26) cache-policy fields of `DMA_DATA` dword 1 are accepted. They're cache hints with no effect on the copied data. The remaining reserved bits are still rejected.
- **GDS storage:** GDS is modelled as one 64 KiB, zero-initialised store shared by the whole device, behind a mutex.
- **GDS source/destination:** select `1` reads from or writes to that store:
  - the validator requires the high address dword to be 0 and the range to fit inside the 64 KiB;
  - `Execute` copies between memory, immediate data and GDS in any combination;
  - `ResolveStore` returns nothing for a GDS destination, since there's no guest memory to write, and for a GDS source it resolves the bytes from the store.
- Register and prefetch destinations are still rejected.
- Nothing is faked for shaders: a shader that uses GDS still fails validation (unsupported descriptor role).
2026-09-28 09:59:54 +03:00
boykopovar 3fe80624f7
Merge pull request #60 from oneandonlydean/fix/primitive-restart-indexed
fix(agc): reject primitive restart only for indexed draws
- `DecodeState` still reads `0x24b` (so it stays in the recorded draw-key registers) but no longer rejects on it.
- `DrawRejection` takes an `indexed` flag, and reports restart only for indexed draws.
- The driver's draw path rejects an indexed draw with restart enabled before the precheck, so indexed draws with restart are still refused when the precheck is off. Restart itself is still not implemented.
2026-09-28 09:56:37 +03:00
boykopovar 9f2da178ef
Merge pull request #59 from oneandonlydean/fix/retain-replaced-device
fix(agc): keep a replaced Vulkan device alive
In the presenter path, after `PrepareForReplacement()` (which flushes cached textures, publishes shadows and waits for idle), the old device is kept in a function-local static list instead of being released. Its child objects stay valid for as long as anything still refers to them. The cost is one idle device for the life of the process; the replacement happens once, at the first flip.
2026-09-28 09:51:55 +03:00
Dean Galvin 0c06382d89 feat(agc): ACB markers, index buffer unbinding and address in errors
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 19:47:33 +13:00
Dean Galvin 41fb65761f refactor(fiber): keep the assembly entry points out of NID patching with _nid_no_patch
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 19:46:38 +13:00
Dean Galvin ba9201874f feat(fiber): implement fibers on linux
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 19:46:38 +13:00
boykopovar d942a604a9
Merge branch 'main' into feat/font-freetype 2026-09-28 09:44:53 +03:00
boykopovar b985d17f82
Merge pull request #57 from oneandonlydean/feat/json2
feat(json2): implement sce::Json values, strings, arrays, objects, parser and null-access callback
- **Layouts:** `String`, `Array`, `Object` and `Value` are pointer-sized handles to host-side storage. The title stores `String`/`Array`/`Object` at an 8-byte stride and `Value` in 0x20-byte slots, so none of them can be bigger. The pair an `Object::iterator` dereferences to has its key at +0x00 and its `Value` at +0x10, which the title reads directly. Array and object iterators are 8 bytes.
- **Parser:** a strict RFC 8259 parser.
  - Numbers: integers that fit `int64` become `Integer`, larger non-negative ones `UInteger`, and everything else `Real`.
  - Strings: `\u` escapes, including surrogate pairs, are decoded to UTF-8.
  - Errors: on any error `parse` returns a negative code (`0x80920101`) and leaves the target value untouched.
- **Serialisation:** compact output. Strings are escaped; reals use `%.17g`, and a non-finite real throws.
- **Null access:** a typed getter on a value of another type, a missing key or an out-of-range index goes through the null-access callback. The callback's result is used when its type matches (any type for `operator[]`). Otherwise a static default value of the requested type is returned. `terminate` clears the callback.
- **Integer getters:** `getInteger`/`getUInteger`/`getReal` convert between the integer kinds and to real where the value fits.
- `setGlobalNullAccessCallBack` (NID `00oCq0RwSAY`) was identified by hashing its mangled name.
- `MemAllocator`'s base constructor and destructor install the abstract class's vtable. A derived allocator replaces it with its own, so its entries (which throw, like a pure virtual call) run only if a pure virtual is called. `Initializer::initialize` throws on a null parameter instead of silently accepting it.
- Mutating a value that isn't the expected type (`referArray` on a string, etc.) throws.
2026-09-28 09:42:21 +03:00
boykopovar 73d014ed83
Merge pull request #56 from oneandonlydean/feat/linux-pread-getdents
feat(libkernel): pread, pwrite, getdents and getdirentries on linux
- **pread/pwrite:** use the existing `NativePread`/`NativePwrite` and don't move the file offset. A null buffer with a non-zero size returns `EFAULT`, a negative offset `EINVAL`, and host failures go through `SceErrorFromErrno`.
- **getdirentries:**
  - reads host `getdents64` records and converts them to the FreeBSD `struct dirent` layout the guest expects (`d_fileno` u32, `d_reclen` u16, `d_type` u8, `d_namlen` u8, NUL-terminated name, record padded to 4 bytes);
  - `*basep` gets the directory position from before the read;
  - when a record doesn't fit in the guest buffer, the descriptor is moved with `lseek` back to that entry's cookie, so the next call resumes there;
  - if not even the first record fits, the call returns `EINVAL` without consuming anything, and a name longer than 255 bytes returns `ENAMETOOLONG`.
- **getdents** is `getdirentries` without `basep`.
- Adds the guest `EFAULT`, `EINVAL` and `ENAMETOOLONG` constants.
2026-09-28 09:38:47 +03:00
boykopovar ae4e38f3f9
Merge pull request #53 from oneandonlydean/feat/userservice-profile
feat(userservice): user name, user number and accessibility settings of the initial user
They report the initial user, following `sceUserServiceGetGamePresets`:
- **Name:** `Player`. A buffer shorter than 17 bytes returns `SCE_USER_SERVICE_ERROR_BUFFER_TOO_SHORT` (`0x8096000A`).
- **User number:** 1.
- **Accessibility settings:** 0, the setting-off value on a fresh console.
2026-09-28 09:29:01 +03:00
SamG-Coder fa787cfbe9 fix(agc): keep BGRA color targets resident between draws 2026-09-28 16:26:02 +10:00
boykopovar c36881727c
Merge pull request #51 from oneandonlydean/feat/libc-runtime-functions
feat(libc): operator new/delete, bounds-checked functions, char locale facets and runtime helpers
2026-09-28 09:23:33 +03:00
boykopovar f558a7bcec
Merge pull request #52 from oneandonlydean/fix/libc-unhandled-exception-report
fix(libc): don't walk guest frame pointers when reporting an unhandled exception
Only log __builtin_return_address(0), which doesn't depend on the guest's frames. After the fix, the log prints the exception type and the terminate handler prints what().
2026-09-28 09:10:38 +03:00
boykopovar 244b915c75
Merge branch 'main' into feat/libc-runtime-functions 2026-09-28 09:01:41 +03:00
boykopovar ce6ac25b7e
Merge pull request #49 from oneandonlydean/feat/mspace-extensions
feat(libc): mspace memalign, malloc stats, thread-unsafe flag and nested mspaces
- Memalign uses the existing aligned allocation.
- Stats fill `SceLibcMallocManagedSize` (size checked against 0x28) from new `inUse`/`peakInUse` counters on the arena. The system size is the arena's extent.
- The thread-unsafe flag is accepted: the implementation always locks, so skipping locks is only an optimisation it doesn't need. Other flags are still rejected.
- An overlapping create is allowed only when the new range lies entirely inside a live block of the other mspace. Every other overlap is still rejected.
2026-09-28 08:58:28 +03:00
boykopovar d653d85538
Merge pull request #50 from oneandonlydean/feat/libkernel-mappings
feat(libkernel): hinted and no-overwrite mappings, virtual range names and usleep
- **Non-fixed mapping with an address hint:** `MapAligned` threw `Non-fixed mapping address hints are not implemented`. On the PS5 the hint is where the search starts. On Linux the mapping is now placed at the first free, aligned range at or above the hint, found from `/proc/self/maps` and mapped with `MAP_FIXED_NOREPLACE` so nothing existing can be replaced. `RequireAvailable` is now only checked for fixed mappings, because a hint may point at used memory. Windows still throws.
- **`SCE_KERNEL_MAP_NO_OVERWRITE` (`0x80`):** it was rejected as an unknown flag. With `MAP_FIXED` on Linux it maps with `MAP_FIXED_NOREPLACE`, and it no longer takes the "remap fixed into registered" path, so it fails instead of replacing a registered range. The unsupported-flags error now includes the flag value.
- **Virtual range names:** `sceKernelSetVirtualRangeName` was `NotImplemented` and `sceKernelClearVirtualRangeName` wasn't exported. Names are now kept in a registry, split and trimmed on overlap. `sceKernelVirtualQuery` reports the name and splits its reported region at name boundaries. `sceKernelMapNamedDirectMemory` and `sceKernelMapNamedFlexibleMemory` now name the range instead of ignoring the name.
- **`usleep`** is exported (POSIX, beside `nanosleep`).
2026-09-28 08:54:42 +03:00
boykopovar 9dd86e99bf fix(pad): add missing header for log macros to pad input cpp 2026-09-28 08:41:20 +03:00
boykopovar a878b31e52
Merge pull request #46 from MartinCajiao/feat/configurable-input-mapping
feat(input): support game controllers and configurable bindings
- Add optional per-game keyboard and mouse bindings through `anyps5-input.ini` or `ANYPS5_INPUT_CONFIG`. Unspecified actions keep their built-in bindings, and repeated action entries provide alternatives.
- Keep wheel presses and focus-loss state handling compatible with dynamically sized bindings. Report configuration errors through the existing video and pad failure path.
- Document the format and remove the resolved input-mapping debt item.
2026-09-28 08:34:29 +03:00
boykopovar 7b761115b2
Merge pull request #44 from oneandonlydean/fix/linux-virtualquery
fix(libkernel): build sceKernelVirtualQuery on linux
2026-09-28 08:28:45 +03:00
boykopovar a8d6f8664e
Merge pull request #63 from oneandonlydean/feat/libc-sscanf-s
feat(libc): sscanf_s on linux
sscanf_s was a NotImplemented placeholder in libc/Export.cpp, and a retail title uses it to parse strings. It's now implemented on Linux. Windows still throws NotImplemented.
2026-09-28 08:18:32 +03:00
boykopovar a8151f17d9
fix(libc): add missing header for not impl helper 2026-09-28 08:13:48 +03:00
boykopovar f38e97658f
Merge pull request #40 from Pacuka/feat/agc-draw-index-indirect
feat(agc): emit indexed indirect draws
This implements `sceAgcDcbDrawIndexIndirect` and `sceAgcDcbDrawIndexIndirectMulti`. They were stubs that aborted with "not implemented".

They follow the existing non-indexed `sceAgcDcbDrawIndirect` / `DrawIndirectMulti`:

- `DrawIndexIndirect` emits `DRAW_INDEX_INDIRECT` (0x25): data offset, base vertex / start instance SGPR locations, draw initiator (5 dwords, matching `GetSize` = 20).
- `DrawIndexIndirectMulti` emits `DRAW_INDEX_INDIRECT_MULTI` (0x38): the same fields, plus the draw-index location / count-indirect control word, count, count address and stride (10 dwords, matching `GetSize` = 40). The stride must be at least 20, the size of an indexed record.
2026-09-28 08:08:47 +03:00
boykopovar d1238299b7
Merge pull request #24 from SamG-Coder/main
fix: support SDK startup, linear framebuffers and indexed draws
Fix SDK startup with an empty allocator replacement table, add linear framebuffer presentation through the current presentation path, and implement explicit indexed draws with packet validation. Retain buffer-address regression coverage for the correction already upstream, and restrict the POSIX exception-runtime test to Unix so Windows test builds succeed.

Also fix two issues reproduced after rebasing: render-target format lookup probed unsupported formats by repeatedly throwing exceptions, costing about 78 ms per draw; the lookup now searches supported entries directly. Recorder buffers now use Windows FLS cleanup to avoid MinGW freeing emulated TLS storage before running their destructors. Cross-DLL tests check independent values and destruction on standard and native Windows threads.
2026-09-28 08:03:34 +03:00
boykopovar b1509a17a6
Merge pull request #34 from Pouare514/idea/prx-cohtml
libs: add libcohtml stub prx (50 NIDs) + Prospero deploy rename
2026-09-28 07:55:22 +03:00
boykopovar 368385ebb3
Merge pull request #33 from Pouare514/idea/prx-fmod
libs: libfmod/libfmodstudio with real FMOD signatures + SDL audio backend
66/93 NIDs mapped to real Itanium-mangled FMOD signatures (byte-verified), 27 stubs. Real SDL audio output (WAV/RAW audible, mixer, volumes), silent fallback via env. Coverage 51/51 + 42/42. Remaining: compressed decoders, Studio mixer, 5 unknown NIDs.
2026-09-28 07:51:08 +03:00
Dean Galvin 20cc23438f feat(libc): sscanf_s on linux
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 16:53:29 +13:00
Dean Galvin e1a8371bff feat(agc): DMA_DATA cache policy hints and GDS source/destination
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 16:51:01 +13:00
Dean Galvin 0479a5f5f0 fix(agc): reject primitive restart only for indexed draws
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 16:49:29 +13:00
Dean Galvin f6a23c9d15 fix(agc): keep a replaced Vulkan device alive
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 16:47:02 +13:00
Dean Galvin 00e4f7678d feat(font): port shadPS4's sceFont and sceFontFt on FreeType
Ported from shadPS4 (GPL-2.0-or-later) with system fonts removed, stubs made to throw,
and sceFontCloseFont implemented.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 16:45:30 +13:00
Dean Galvin 390e4cd800 feat(json2): implement sce::Json values, strings, arrays, objects, parser and null-access callback
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 16:42:29 +13:00
Dean Galvin f7e1bdf0b9 feat(libkernel): pread, pwrite, getdents and getdirentries on linux
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 16:40:22 +13:00
MartinCajiao 0644a8c38f feat(input): support SDL game controllers 2026-09-27 20:27:22 -05:00
Dean Galvin 99bdf81364 feat(userservice): user name, user number and accessibility settings of the initial user
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 14:22:48 +13:00
Dean Galvin eb79f0d412 fix(libc): don't walk guest frame pointers when reporting an unhandled exception
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 14:22:48 +13:00
Dean Galvin a599eca727 feat(libc): operator new/delete, bounds-checked functions, char locale facets and runtime helpers
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 14:22:48 +13:00
Dean Galvin 3058980d96 feat(libc): mspace memalign, malloc stats, thread-unsafe flag and nested mspaces
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 14:22:48 +13:00
Dean Galvin 9754937a5d feat(libkernel): hinted and no-overwrite mappings, virtual range names and usleep
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 14:22:48 +13:00
MartinCajiao 1007f6d64e fix(input): load per-game config beside executable 2026-09-27 20:20:17 -05:00
MartinCajiao 6dfa449e52 fix(input): handle UTF-8 BOM and duplicate bindings 2026-09-27 19:58:38 -05:00
MartinCajiao c13f0eee67 feat(input): allow configurable keyboard and mouse bindings 2026-09-27 19:54:19 -05:00
Dean Galvin 93a214836f fix(libkernel): build sceKernelVirtualQuery on linux
The host-region fallback added with the Demon's Souls work calls VirtualQuery and
includes windows.h unconditionally, so libkernel no longer compiles on Linux.
On Linux, read the containing mapping and its permissions from /proc/self/maps.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 13:32:36 +13:00
SamG-Coder e424b6b7bf fix(agc): preserve recorder buffers through Windows thread teardown 2026-09-28 09:55:01 +10:00
SamG-Coder 9814c93f75 fix(agc): avoid exception-driven render target format probing 2026-09-28 09:55:00 +10:00
SamG-Coder e1e3a12227 fix(build): restrict POSIX exception runtime test to Unix 2026-09-28 09:09:02 +10:00
SamG-Coder fc26cff30f test(shader): cover decoded buffer address operands 2026-09-28 09:09:02 +10:00
SamG-Coder b25025c682 fix(agc): support explicit indexed draw commands 2026-09-28 09:09:02 +10:00
SamG-Coder 07930c6726 feat(videoout): present linear framebuffer layouts 2026-09-28 09:05:49 +10:00
SamG-Coder 67fce999c5 fix(libc): support SDK startup without allocator replacements 2026-09-28 09:03:10 +10:00
devilismyfriend 9e5f8397f2 refactor(agc): drop outside references from the copy kernel comments
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-27 12:14:48 -07:00
devilismyfriend 72336201b2 perf(libkernel): resolve initialised mutexes and conditions without the global lock
Every lock, unlock, signal and wait took the process-wide initialisation
mutex to read the handle, serialising all guest synchronisation. The
handle is now read atomically and the lock is only taken to initialise a
static initializer or to report a destroyed object.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-27 11:26:59 -07:00
devilismyfriend e764385d51 fix(libkernel): drop the scePthreadOnce stub that shadowed the implementation
The merge brought a NotImplemented scePthreadOnce_nid_postfix next to the
existing scePthreadOnce. The NID patcher gives the NID to the postfixed
symbol, so the stub replaced the working export and the title aborted at
its first once-initialisation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-27 11:26:58 -07:00
devilismyfriend 1e4430e917 fix(agc): drop cached textures on Vulkan device replacement
When the presentation device was replaced, textures created on the old
device stayed in the global sampled and storage texture caches and kept a
reference to the destroyed TextureDetiler, whose VkDevice was then read
corrupted ("missing Vulkan function: vkResetDescriptorPool" at startup).
The replacement now flushes the old device's cached storage textures and
publishes every unit shadow before waiting for the device, and the device
teardown erases the cache entries that belong to it.

Patch author: boykopovar (fix-vulkan-texture-lifetime.patch, PR #5 review).

Co-Authored-By: boykopovar <boykopovar@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-27 10:53:11 -07:00
devilismyfriend a503d0b617 Merge remote-tracking branch 'origin/main' into feat/demons-souls-boot
Brings in main up to 9958d26 (homebrew runtime, POSIX wrappers in
libkernel, sce_module guest modules and --skip-sce-module, the --to-intel
general pipeline, libSceRandom, libSceRtc, libScePosixForWebKit,
libRenoirCore, test wiring).

Resolutions where both sides implemented the same thing:
- libkernel pthread: main's structure (lazy static initialisation,
  destroyed markers, MutexOperations/CondOperations, mutex protocol and
  condattr clock) with this branch's TimedWait deadlines and condition
  (precise timed lock/wait on Windows), wait tracing, the adaptive mutex
  type 4, POSIX default ERRORCHECK mutexes, EDEADLK/EPERM results instead
  of throws, and condition clocks honoured for absolute timeouts.
- libc locale: the guest Dinkumware ABI (_Locimp, facet vtables, short
  ctype/case tables, locale ids, stream storage) is kept because guest code
  inlines those layouts; main's C character functions are kept on top.
- libc stdio/strings/math: main's stream functions (guest FILE status
  sync), strerror/perror, remove, formatting, string and math exports win
  over this branch's duplicates.
- libc paths: main's working directory with this branch's path aliases
  resolved on the normalised guest path.
- libkernel file: this branch's sceKernel* results as SCE errors, main's
  POSIX wrappers and both fstat helpers.
- relinker: this branch's stub lowering keeps its trampolines through the
  main executable path; guest modules refuse lowerings that need stubs.
- AGC driver: main's rendering wait is executed by this branch's workers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-27 10:52:21 -07:00
Pacuka 83f43d1004 feat(agc): emit indexed indirect draws
sceAgcDcbDrawIndexIndirect and sceAgcDcbDrawIndexIndirectMulti emit
DRAW_INDEX_INDIRECT (0x25) and DRAW_INDEX_INDIRECT_MULTI (0x38) like their
non-indexed counterparts, with 20-byte records.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 19:43:16 +02:00
boykopovar 9958d26f4f
Merge pull request #31 from Pouare514/idea/prx-renoir
libs: add libRenoirCore.PS5 stub prx (23 NIDs)
2026-09-27 18:12:16 +03:00
Pouare514 5099184d4d feat(prx): fmodstudio unknown NIDs throw via NotImplemented
Convert 5 remaining pure stubs (log + return 0) to throwing with
literal NID, keep trailing return 0. Real SDL/state-tracking impls
(20 studio + 2 libfmod + C++ classes) untouched. Remove stale
logging-stub comments only around touched stubs.

Throwing: Cm2cmtCv8cA, EfM9xXvBmxk, Js90KQXVS4s, oCYWES02VPc, vVwA2cZA5e4
2026-09-27 16:10:41 +02:00
Pouare514 7cdb23eacd fix(libcohtml): throw via NotImplemented_nid_no_patch for 50 stubs 2026-09-27 16:06:18 +02:00
Pouare514 b6dea0b51b Renoir stubs throw with NID name for progress monitoring 2026-09-27 15:53:27 +02:00
Pouare514 a719359cd1 prx: make libRenoirCore.PS5 stubs throw NotImplemented 2026-09-27 15:49:18 +02:00
Pouare514 030e62dfa3 feat(prx): fmod real audio output via SDL + identify 22/27 NIDs
- libfmod: route createSound (OPENMEMORY WAV/RAW, file placeholder sine)
  + playSound + update() mixer pump into SDL queue (48k stereo F32,
  mirrors libSceAudioOut). Channel::setVolume/isPlaying/position now
  track real PCM cursor with loop support. Silent fallback via
  ANYPS5_FMOD_SILENT=1, NOSOUND output, or SDL open failure.
  Link SDL2-static like libSceAudioOut.
- NIDs: recompute from public FMOD headers (fmod.h/hpp + fmod_studio
  2.0) with exact Itanium manglings (g++ nm) + SHA1+suffix
  (NidCompute.cpp). Identify 2/2 libfmod (setFileSystem, setCallback)
  + 20/25 studio (const createInstance, getEvent, getCoreSystem,
  getSoundInfo, etc.). Replace stubs with ABI-compatible real
  impls; 5 studio remain unknown (Cm2cmtCv8cA, EfM9xXvBmxk,
  Js90KQXVS4s, oCYWES02VPc, vVwA2cZA5e4).
- Tests: coverage OK (51+42 Legends NIDs, missing 0), audio smoke
  (WAV 4800f + RAW 2048f, volume, channelsPlaying, stop) OK real
  and silent.
2026-09-27 13:24:34 +02:00
Pouare514 279587cb16 fix(libcohtml): provide libcohtml.Prospero.prx for DT_NEEDED
Copy the patched libcohtml.prx to libcohtml.Prospero.prx (exact DT_NEEDED name) via a post-build copy in the module CMakeLists, wired into the libs umbrella target. OUTPUT_NAME with a dot was rejected: the parent pipeline derives unpatched/patched paths from the directory target name, so renaming output would break it; dotted CMake target names are supported (e.g. libSceSaveData.native) but the parent-owned NID-patch rule is kept untouched. Adds DEPLOY.md deploy note. All 50 raw NIDs re-verified in the renamed file export table.
2026-09-27 12:57:23 +02:00
Pouare514 c0515bdcce feat(prx): add libfmod and libfmodstudio replacements covering Legends NIDs 2026-09-27 12:32:13 +02:00
Pouare514 a4248cb114 feat(libcohtml): add stub prx exporting 50 Minecraft Legends NIDs 2026-09-27 12:00:15 +02:00
Pouare514 0722f3e5fc prx: add libRenoirCore.PS5 replacement with 23 Renoir stubs for libcohtml
Minecraft Legends' libcohtml.Prospero.prx imports 23 NIDs from lib
libRenoirCore.PS5_v1 (docs/legends-unresolved-nids.json). Clear names are
unknown, so each export is exposed under its raw NID via APS5_EXPORT
alias (<NID>_nid_no_patch_cut), which nid_patcher strips to the
literal NID instead of hashing.

Stubs follow KytyPS5 UnresolvedImportStub policy (log call + return 0)
via APS5_LOG_OUT rather than throwing NotImplemented.
2026-09-27 11:57:54 +02:00
boykopovar e526f1f528 feat(libc): replace guest locale implementation with std::locale 2026-09-27 11:43:42 +03:00
boykopovar 9cc36a02fe feat(libkernel): add __progname str value 2026-09-27 11:43:40 +03:00
boykopovar f5ea673c10 feat(libkernel): impl posix stdio wrappers, reusing sceKernel file ops 2026-09-27 11:43:40 +03:00
boykopovar 7a925c68e5 fix(libkernel): handle clock_second 13 in clock_gettime and clock_getres 2026-09-27 11:43:39 +03:00
boykopovar 13c648bebb feat(libkernel): impl file, time, process, signal for posix 2026-09-27 11:43:38 +03:00
boykopovar 62c16792ff feat(libkernel): impl pthread condition variables + posix thread attribute queries 2026-09-27 11:43:37 +03:00
boykopovar a709e220f2 feat(libkernel): implement posix mutex locking and timed waits 2026-09-27 11:43:37 +03:00
boykopovar ae2e5cba7e feat(libc): implement heap trace info 2026-09-27 11:43:36 +03:00
boykopovar c9cb3cae39 feat(libkernel): implement disabled address sanitizer state + replacement tables 2026-09-27 11:43:36 +03:00
boykopovar 9fd6816356 fix(libkernel): store rtld allocator table separately from application heap 2026-09-27 11:43:35 +03:00
boykopovar dbb56adcf6 feat(libkernel): implement process, cpu, uuid, gpi, gpo, sync funcs 2026-09-27 11:43:34 +03:00
boykopovar 55e1c4a238 feat(libkernel): implement application heap and thread atexit registration 2026-09-27 11:43:33 +03:00
boykopovar 5887c8d6e2 feat(libkernel): add memory segment, backtrace, heap error report definitions 2026-09-27 11:43:32 +03:00
boykopovar 40101471ee feat(libkernel): add new posix, pthread, semaphore, process funcs definitions 2026-09-27 11:43:31 +03:00
boykopovar 0783e369da feat(libkernel): add definitions for standard guest libc imports 2026-09-27 11:43:31 +03:00
boykopovar fce5889d91
Merge pull request #21 from obelisk-complex/test/wire-up-exception-runtime-test
test: wire up the orphaned exception runtime test
- `core/libs/CMakeLists.txt`: registered `ExceptionRuntime.cpp` as `exception_runtime_tests`/`exception_runtime`, following the existing `Guest*.cpp` test pattern, linked against `libc`.
2026-09-27 11:39:23 +03:00
boykopovar 228802b7f5
Merge pull request #23 from obelisk-complex/test/fix-agc-driver-test-bitrot
test(agc): fix and re-enable 3 of 8 bitrotted AGC driver tests
- `agc_driver_graphics_tests`: fixed the link failure by adding the three missing source files and linking `shader_recompiler_agc_driver`. Still fails at runtime against stale assertions accumulated over many commits of not being built (an expected "not implemented" message that texture support since removed, and a sampler test fixture value that no longer fits its 12-bit field). Left `EXCLUDE_FROM_ALL`; fixing the assertions is a separate pass across the whole 1150-line test file, not a build fix.
- `agc_driver_recompiler_tests`: root-caused but not fixed. It needs `COMPUTE_NUM_THREAD_X` set, and its pass condition checks for a "not implemented" stub error that no longer exists now that the real recompiler is in. Restoring its original intent needs a shader deliberately built to fail recompilation, which is a design decision, not something this PR should decide unilaterally. Left `EXCLUDE_FROM_ALL`.
- `agc_driver_tests`, `agc_shader_memory_tests`, `agc_driver_flip_tests` and `agc_driver_pm4_tests` already passed; registered them with `add_test` so none of the four can bitrot silently again.
2026-09-27 11:34:45 +03:00
boykopovar 7894745fba
Merge pull request #15 from obelisk-complex/fix/sscanf-signedness-and-substr-copy
fix: correct sscanf %x signedness and avoid a substr copy
- `core/libs/prx/libSceSysmodule/Export.cpp`: `devMajor`/`devMinor` now `unsigned int`.
- `core/libs/nid/include/nid/NidPatcherUtils.hpp`: two `substr(0, n)` calls replaced with `resize(n)`.
2026-09-27 11:30:50 +03:00
QDarkRex 2081071237 refactor(kernel): share SCE kernel error codes through KernelErrors.hpp
Kernel error codes were redeclared per file under three prefixes
(SCE_KERNEL_ERROR_, EQUEUE_ERROR_, KERNEL_SEMA_ERROR_), which let wrong
values go unnoticed. Define them once as 0x80020000 | errno for errno
1..94 and use the SCE_KERNEL_ERROR_ names everywhere. Values are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 13:32:28 +07:00
QDarkRex ac0f8af228 fix(kernel): use SCE kernel error codes in equeue, direct memory and mutex
SCE kernel errors are 0x80020000 plus the FreeBSD errno. The equeue and
direct memory constants used an unrelated 0x8001xxxx range with mismatched
errno values (e.g. ETIMEDOUT was 0x80010023), so a guest checking
sceKernelWaitEqueue for SCE_KERNEL_ERROR_ETIMEDOUT saw an unexpected error.
SCE_KERNEL_ERROR_EDEADLK in Mutex.cpp held the EAGAIN value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 13:27:23 +07:00
QDarkRex 97cae1458e fix(kernel): use SCE kernel error codes in equeue, direct memory and mutex
SCE kernel errors are 0x80020000 plus the FreeBSD errno. The equeue and
direct memory constants used an unrelated 0x8001xxxx range with mismatched
errno values (e.g. ETIMEDOUT was 0x80010023), so a guest checking
sceKernelWaitEqueue for SCE_KERNEL_ERROR_ETIMEDOUT saw an unexpected error.
SCE_KERNEL_ERROR_EDEADLK in Mutex.cpp held the EAGAIN value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 13:22:01 +07:00
QDarkRex be127fd0f1 feat(kernel): implement sceKernelDeleteSema
Waiters are woken with SCE_KERNEL_ERROR_EACCES and the semaphore is freed
once they have left.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 12:38:59 +07:00
QDarkRex 15b749c2ba fix(kernel): return 64-bit offsets from sceKernelLseek
The SCE ABI returns off_t; offsets above INT_MAX threw instead of being returned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 12:38:59 +07:00
QDarkRex 76b7f998f5 fix(kernel): give every thread a pthread handle and keep mutex ownership consistent
- scePthreadSelf returned null on Linux and for threads not created by
  scePthreadCreate (including the main thread); such threads now get a
  lazily adopted, non-joinable handle
- scePthreadExit on Linux skipped FinishThread, losing the join value
- detached threads on Linux were never freed; use the reference count
  already used on Windows
- unlocking a recursive mutex from a non-owner was undefined behaviour;
  return SCE_KERNEL_ERROR_EPERM
- scePthreadCondTimedwait did not restore the mutex owner after waking,
  so another thread locking during the wait made the waiter's unlock
  fail with EPERM and left the mutex locked forever
- SCE_KERNEL_ERROR_ETIMEDOUT in Cond.cpp was 0x80020062 instead of 0x8002003C

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 12:38:59 +07:00
QDarkRex 7ac1198e74 fix(audioout): reject zero sample count and frequency in sceAudioOutOpen
A zero frequency was stored and later used as a divisor when computing
the output block duration. Return SCE_AUDIO_OUT_ERROR_INVALID_SIZE and
SCE_AUDIO_OUT_ERROR_INVALID_SAMPLE_FREQ instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 12:24:15 +07:00
devilismyfriend 29b4601564 perf(agc): dispatch and draw recipes, data-only cache hits, unit shadows, bindless image tables
Dispatch cache with per-key value variants and data-only hits (flat-SRT leaves the recompiler
proves pure are refreshed into the resource template instead of re-captured), dispatch and draw
recipes replaying a proven prepare, register-keyed draw entries, template data refresh, unit
shadows in device-local slabs, 64 KiB block-unit storage tracking with windowed detile, DCC
clear-key proofs, per-class GPU timing, a CPU copy path with batch read tracking, present slot
ring, rate-limited reaps and lazy completion counting, plan-failure and poisoned source memos,
bindless image tables (runtime-indexed descriptor arrays from a CPU-read table) so the
per-frame compute program that failed its plan now compiles. Worker affinity opt-in, per-draw
logs behind APS5_TRACE_DRAWS, wait-timeout reports include the recorder's view of the label.
Fixes a use-after-free behind BDA-miss dispatch snapshots and the CPU-write stamp of
UnchangedSinceCollected. Intro-video stage: 154 -> ~500 presents per 10 s at 4K.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-26 19:00:40 -07:00
devilismyfriend af3c2024ed feat(runtime): timed waits, sync primitive fixes, heap and RTC fixes, unattended-run switches
libkernel: a TimedWait service for condition variables, semaphores, event flags, rwlocks and
equeues with the scheduler tick; mutex/cond/sem corner cases the title hits; job worker
affinity is opt-in (APS5_JOB_AFFINITY). libc: calloc/realloc heap slot swap, a default
terminate handler with a backtrace, CPU topology helper. libSceRtc export fixes with tests.
libSceVideoOut: APS5_NO_PAD_INPUT ignores host input for unattended measurements,
APS5_FLIP_QUEUE_WAIT keeps a stalled process alive for a debugger. ApplicationHeap and
GuestRtc tests wired into the test build.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-26 19:00:39 -07:00
owner f4ff3be07f test(agc): fix and re-enable 3 of 8 bitrotted AGC driver tests
These EXCLUDE_FROM_ALL targets weren't registered with add_test, so
they silently bitrotted with no CI/ctest visibility:

- agc_driver_graphics_tests: fixed a link failure (Draw.cpp, Pipeline.cpp
  and GraphicsPipelineCache.cpp were never added to the target's sources
  when the test started calling into them). Still fails at runtime against
  several stale assertions (a removed "not implemented" error message, a
  sampler fixture value that doesn't fit its bitfield) accumulated over
  many commits of not being built; left EXCLUDE_FROM_ALL pending an
  assertion-maintenance pass.
- agc_driver_recompiler_tests: root-caused (missing COMPUTE_NUM_THREAD_X
  register setup, plus a pass condition checking for a stub error message
  that no longer exists now that the real recompiler is implemented) but
  left unfixed and EXCLUDE_FROM_ALL — restoring its original intent needs
  a shader deliberately built to fail recompilation, a design decision.

agc_driver_tests, agc_shader_memory_tests, agc_driver_flip_tests and
agc_driver_pm4_tests already passed; registered them with add_test too
so none of the five can bitrot silently again.

agc_driver_bda_device_tests: dropped from this commit's scope. Upstream
PR #20 already proposes the same one-line BdaContracts.cpp fix (matching
the runtime message's "signature" text), so BdaContracts.cpp is left
untouched here to avoid duplicating that fix. The test target stays
defined (EXCLUDE_FROM_ALL, still buildable by name) but is no longer
registered with add_test until #20 or an equivalent fix lands.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 14:49:14 -06:00
owner d3a1b89be3 test: wire up the orphaned exception runtime test
ExceptionRuntime.cpp existed complete and working but was never
registered in CMakeLists.txt, so it never built or ran. Wired it in
following the existing Guest*.cpp test pattern.

The other three orphaned test files (PthreadStart.cpp, FileStreams.cpp,
Formatting.cpp) were left out: each has genuine bitrot against current
code (a moved header, fseek returning errno instead of throwing on an
invalid whence, and vsnprintf's expected va_list mutation) that needs a
source-level decision, not a CMake wiring fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 14:36:33 -06:00
owner 63209b584f fix: correct sscanf %x signedness and avoid a substr copy
libSceSysmodule/Export.cpp parsed /proc/self/maps device major/minor
numbers into signed int with a %x format, which is undefined behaviour
per the C standard even though it happened to work on this target;
switched to unsigned int to match the format specifier.

NidPatcherUtils.hpp's StripNidPostfix built a truncated copy with
substr(0, n) where the prefix is already the string itself; resize(n)
does the same truncation without the extra allocation and copy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 14:11:50 -06:00
owner d01be2b0e9 fix(exceptions): alias uncaught_exception(s) to their purpose-built wrappers
Exports.cpp aliased the real std::uncaught_exception(s) mangled names
directly to __cxa_uncaught_exception(s)_nid_postfix instead of the
existing _ZSt18uncaught_exceptionv_nid_postfix/_ZSt19uncaught_exceptionsv_nid_postfix
wrappers, leaving the latter as dead code and breaking the file's own
bare-name -> matching-nid_postfix alias pattern (caught by fleet QA
review, no functional impact since it's a raw symbol alias and both
sides return in the same register).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 13:39:10 -06:00
owner a4c519b262 fix(exceptions): interpose libstdc++ ABI on Linux so the project's own unwinder drives it
On native Linux these PRX shared libraries and their test executables
dynamically link real libstdc++/libgcc, so a plain throw went through the
system's __cxa_throw/_Unwind_RaiseException. That still invoked this
project's own __gxx_personality_v0_nid_postfix (the CIE's personality
pointer is a raw function address, agnostic to which unwinder is walking
the stack), but handed it libgcc's incompatible private _Unwind_Context
layout, corrupting every field Personality.cpp reads and aborting with no
exception message.

Fix: OwnPersonality() now recognises the bare __gxx_personality_v0 wrapper
on Linux too (previously Windows-only), and Exports.cpp exports the real
ABI names (__cxa_throw, __cxa_begin_catch/end_catch, __cxa_rethrow,
__cxa_allocate/free_exception, __cxa_call_terminate, __cxa_get_exception_ptr,
__cxa_current_exception_type, __cxa_init_primary_exception, the std::
terminate/uncaught_exception(s) mangled names, and the core _Unwind_*
entry points) via the existing GCC_GLOBAL_ALIAS assembler-alias mechanism,
so ELF symbol interposition makes this project's own implementation win
process-wide over libgcc_s.so.1/libstdc++.so.6. __cxa_init_primary_exception
is newly implemented; GCC 13's inline std::make_exception_ptr needs it and
nothing provided it before.

Fixes 7 previously-aborting tests: guest_rendering_wait, guest_buffer_reuse,
guest_shader_link, guest_system_exit_parameters, guest_once, guest_memory,
guest_search.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 13:39:10 -06:00
boykopovar 1a0ebbc849
Merge pull request #9 from Pacuka/feat/scertc
feat(rtc): implement libSceRtc date and tick functions
- Ticks count microseconds since 0001-01-01 00:00:00 in the proleptic Gregorian calendar, up to 9999-12-31 23:59:59.999999. `sceRtcGetTickResolution` returns 1000000.
- Validation (`sceRtcCheckValid`, `sceRtcIsLeapYear`, `sceRtcGetDayOfWeek`) returns the matching `SCE_RTC_ERROR_INVALID_*` code (`0x80B50002`–`0x80B5000E`).
- Conversions: `sceRtcGetTick`/`SetTick`, `GetTime_t`/`SetTime_t`, `GetWin32FileTime`/`SetWin32FileTime`.
- Current time: `sceRtcGetCurrentTick`, `GetCurrentClock`, `GetCurrentClockLocalTime`. `sceRtcGetCurrentNetworkTick` uses the host clock.
- UTC and local time conversion through the host time zone.
- `sceRtcFormatRFC3339` (`YYYY-MM-DDThh:mm:ss.cc` plus `Z` or `±hh:mm`) and `sceRtcParseRFC3339`.
- Tick arithmetic (`sceRtcTickAdd*`) rejects results outside the valid range with `SCE_RTC_ERROR_INVALID_VALUE`.
- New exports: `sceRtcGetDaysInMonth`, `sceRtcTickAddMonths` and `sceRtcTickAddYears`. The last two clamp the day to the end of the target month (2024-01-31 + 1 month = 2024-02-29).
2026-09-26 13:41:16 +03:00
Pacuka c0508a7f5f feat(rtc): implement libSceRtc date and tick functions
Ticks count microseconds since 0001-01-01 in the proleptic Gregorian
calendar, up to 9999-12-31 23:59:59.999999. Implement validation, tick
and date conversion, time_t and Win32 FILETIME conversion, UTC and
local time conversion through the host time zone, RFC 3339 formatting
and parsing, and tick arithmetic. Add sceRtcGetDaysInMonth,
sceRtcTickAddMonths and sceRtcTickAddYears, which clamp the day to the
end of the target month.

The network clock uses the host clock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 12:21:23 +02:00
Pacuka d1c25097e3 feat(random): implement sceRandomGetRandomNumber
Fill the buffer from std::random_device and reject a null buffer or a
size above SCE_RANDOM_MAX_SIZE (64) with SCE_RANDOM_ERROR_INVALID, as
the system library does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 12:14:46 +02:00
Pacuka 37074ab893 fix(build): link guest library tests dynamically on Linux
Tests in core/libs link against the prx shared libraries, which the
global -static flag rejects on Linux ("attempted static link of dynamic
object"). Drop -static in that directory on non-Windows hosts while
keeping the static GCC runtime.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 11:15:16 +02:00
Pacuka f9695c1069 fix(agc): accept the SDK default GDS range in sceAgcCbReleaseMem
The SDK's inline release wrapper passes gdsOffset 0 and gdsSize 1 for
every release, not only GDS ones. The packet ignores the range unless the
GDS data selector is used, so accept that default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 11:15:16 +02:00
Pacuka b98257b75d fix(libc): register the main guest image on Linux
Guest mprotect calls on the executable's own segments failed with
"guest protection or unmap range is not registered" because only the
Windows build registered the main image. Register the PT_LOAD segments of
the main executable page by page, merging the protections of segments that
share a page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 11:15:16 +02:00
Pacuka ca23f10612 fix(kernel): accept AMPR and ACP access bits in memory protections
Retail titles pass protections such as 0xC2 (CPU read/write plus the
0x40 and 0x80 device access bits). The device bits do not affect CPU
access and were rejected as unsupported.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 11:15:16 +02:00
Pacuka d15e93681f fix(kernel): map SCE protections to readable host pages
SCE_KERNEL_PROT_CPU_RW (0x02) and CPU_EXEC (0x04) include read access,
but were translated to write-only and execute-only host pages. GPU read
and write bits also need host access because the emulated GPU reads and
writes guest memory from the CPU. Write-only mappings made the AGC driver
reject guest data segments as unreadable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 11:15:16 +02:00
Pacuka 998605fe4e fix(libc): swap calloc and realloc slots of the malloc replacement table
SceLibcMallocReplace lists calloc before realloc (malloc, free, calloc,
realloc, memalign, reallocalign, posix_memalign, ...), as the table in
retail titles shows. realloc therefore called the application's calloc
with the old pointer as the element count, and calloc called realloc.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 11:15:16 +02:00
Pacuka a4273c10dc fix(videoout): drop __stdcall from the window procedure
GCC on Linux rejects the attribute, which breaks the libs build since the
F11 fullscreen change. It has no effect on x86-64 Windows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 11:15:16 +02:00
boykopovar e4825fbdc2
Merge pull request #3 from SamG-Coder/main
Expand native PS5 homebrew compatibility and regression coverage
2026-09-26 09:54:21 +03:00
devilismyfriend 9c2a75601d feat(libs): agc packet builders, savedata memory, offline service stubs
- libSceAgc: SetIndexCount, SetBaseIndirectArgs, DispatchIndirect, wait
  and write-data patch functions, relaxed checks for what titles send,
  NOP fillers for LOD stats and wait-until-safe, NotImplemented stubs.
- libSceSaveData.native: short mount points, backup events, save-data
  memory slots.
- user/system service, store dialog, video-out flip modes and queue-full
  error, pad read, fibers, offline behaviour for network/NP modules, and
  new export-only modules Ampr, JpegEnc, Json2, MsgDialog.native,
  NpCppWebApi, NpUtility.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-25 16:27:49 -07:00
devilismyfriend 91557ebade feat(audio): AudioOut2 SDL output queue, ATRAC9 decoder in libSceAjm.native
- AudioOut2: one SDL device per context; the hardware grain queue level
  is derived from the SDL queued bytes so the title's poll-and-push loop
  runs at real time; ports are mixed per push with 7.1 folded to stereo.
- libSceAjm.native: instance and batch APIs; ATRAC9 decoding with
  variable-size frames inside superframes, padding, gapless parameters
  and handle re-creation on re-initialisation.
- AudioOut v1: sceAudioOutOutput(handle, NULL) drains instead of
  throwing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-25 16:27:49 -07:00
devilismyfriend 8a69fefe13 perf(agc): batch GPU work in a recorder with host-imported guest memory
Replaces the synchronous per-command execution model, and with it the
upstream render-target, pipeline-cache, tile-buffer, batched-draw and
memory-ownership commits (5a280ce, 7ed5a0b, 46c799d, 598caac, 40df528),
whose files are removed.

- Recorder: one open command buffer per device; dispatches, resident
  draws, uploads, write-backs, labels, fills and copies record into it;
  timeline-semaphore serials let drains wait without the GPU mutex;
  completions run in order at reap.
- one worker thread per PM4 queue; labels and stores written by the GPU
  into the host import; GPU-side DISPATCH_INDIRECT; the buffer-fill
  kernel replaced by vkCmdFillBuffer; a dispatch cache validated by
  write watch; filler packets tolerated; rejected submissions dumped.
- guest memory: page-state cache, 64 KiB write generations, host imports
  with VK_EXT_external_memory_host, persistent mirrors of the executable
  image, GPU copies of misaligned sub-ranges.
- textures: shader-written images stay resident with deferred
  write-back (adjacent-generation rule for packed video planes), sampled
  views of storage images, DCC key handling, addrlib swizzle equations,
  bidirectional detiler.
- draws: MRT, more formats, dynamic viewport/scissor, cached pipelines,
  resident 64 KiB targets, draws recorded into the recorder.
- ShaderResources: two-stage build, descriptor and sampler caches, a
  content-keyed resource cache; presentation from the resident image.
- a label deferred behind a completion is no longer re-stored by the
  CPU at reap time unless a write-back overwrote it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-25 16:27:49 -07:00
devilismyfriend f3ac61000d feat(runtime): guest arena, kernel thread/sync/file APIs, crash hooks
- libc: reserve guest memory in one arena below the PS5 map limit with
  MEM_WRITE_WATCH (GuestArena) and a caching guest heap; the allocation
  registry gains a generation counter, an invalidator callback for the
  driver's page cache and a pin waiter for leased ranges. This replaces
  the fault-based GuestMemoryTracking/GuestMemoryBacking layer, whose
  files are removed.
- libkernel: mmap/mprotect/munmap on the arena, flexible memory budget,
  real sceKernelVirtualQuery; POSIX pthread layer, rwlocks, timed locks,
  TSD, event flags; 0.5 ms scheduler tick and high-resolution sleeps;
  TSC/clock/time functions; file APIs return SCE errno codes; the APR
  file-streaming API.
- libc: vectored crash reporter with backtraces for fatal exceptions,
  SIGABRT, UCRT invalid parameters and process exit; SSE4a EXTRQ/INSERTQ
  emulation for Intel hosts; %ls/%lc/%S/%C with the guest's 16-bit
  wchar_t; hand-written setjmp/longjmp for the guest jmp_buf; a path
  alias table for short save-data mount points; more string, stdio and
  math exports.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-25 16:27:49 -07:00
boykopovar 40df5282e6 perf(agc): track guest memory ownership + optimize gpu synchronization 2026-09-25 19:47:18 +03:00
boykopovar e392506e0a feat(pad): add enums + edit mapping 2026-09-25 16:59:23 +03:00
boykopovar dde8fa53e6 chore(pad): update circle, cross, r1 input to pad mapping 2026-09-25 12:26:41 +03:00
boykopovar 598caac0ce perf(agc): batch draws and cache descriptors, samplers, and buffers 2026-09-25 11:40:03 +03:00
boykopovar 6b8e16b73e feat(video): fullsceen mode by f11 2026-09-25 11:18:58 +03:00
boykopovar 9453f47828 feat(video): open centered window at 60% of display size 2026-09-25 11:13:03 +03:00
boykopovar 11bee5527d fix(video): preserve client aspect ratio when resizing 2026-09-25 11:07:51 +03:00
boykopovar a7fb4cbf72 fix(video): recreate swapchain after window minimization 2026-09-25 10:49:46 +03:00
boykopovar 46c799da67 perf(agc): use device-local tile buffers and cache spir-v validation 2026-09-25 09:14:03 +03:00
boykopovar 7ed5a0beea perf(agc): optimize pipeline cache key construction 2026-09-25 08:25:59 +03:00
boykopovar 5a280ced87 perf(agc): keep render targets on gpu across acquire_mem 2026-09-25 08:22:43 +03:00
SamG-Coder 5a2790c93e style(libc): remove trailing blank line in process exports 2026-09-25 07:27:07 +10:00
SamG-Coder f37fffdacd feat(libc): expose guest vsprintf formatting 2026-09-25 07:26:06 +10:00
SamG-Coder 6cdf4a5be1 feat(libc): implement binary search with guest comparator ABI 2026-09-25 07:24:17 +10:00
SamG-Coder 473a4f8d1c fix(agc): preserve strict shader linkage failures 2026-09-25 07:22:06 +10:00
SamG-Coder 322dc24c9e feat(kernel): implement guest once initialization 2026-09-25 07:22:05 +10:00
SamG-Coder 95dc22c173 feat(agc): execute rendering waits against buffer reuse fences 2026-09-25 07:16:55 +10:00
SamG-Coder cca00c13ab feat(video): track ordered buffer reuse reservations 2026-09-25 07:13:15 +10:00
SamG-Coder 2187436d0d feat(agc): expose legacy register defaults entry point 2026-09-25 07:10:15 +10:00
SamG-Coder 2d8ec800c3 Merge remote-tracking branch 'upstream/main' 2026-09-25 07:08:17 +10:00
SamG-Coder d6f23df679 feat(agc): compose basic shader linkage register blocks 2026-09-25 07:08:10 +10:00
SamG-Coder 18ce03cba2 feat(libc): implement immediate guest process exit 2026-09-25 07:05:07 +10:00
SamG-Coder dd0debe967 feat(libc): reopen guest streams while preserving identity 2026-09-25 07:05:07 +10:00
boykopovar 05c8146744 refactor(pad): libScePad files structure refactor 2026-09-25 00:04:19 +03:00
SamG-Coder 2920c7f04c feat(system): handle console exit through runtime shutdown 2026-09-25 07:02:37 +10:00
SamG-Coder 79edb20f17 fix(libc): preserve 64-bit guest stream offsets 2026-09-25 07:00:45 +10:00
boykopovar ce287648bf feat(pad): add read input state logic to libScePad 2026-09-24 23:59:12 +03:00
SamG-Coder 39b81364b7 feat(libc): add C-locale character APIs and guest basename 2026-09-25 06:58:41 +10:00
SamG-Coder 7d07187ac8 feat(libc): add floating-point string conversions 2026-09-25 06:55:31 +10:00
SamG-Coder c7d26dda5e feat(libc): add missing guest math exports and 64-bit rounding 2026-09-25 06:54:49 +10:00
SamG-Coder 730afc79f8 feat(libc): add independent guest strtok state 2026-09-25 06:52:05 +10:00
SamG-Coder 1b45b0fe68 feat(libc): track guest working directory and resolve relative paths 2026-09-25 06:51:37 +10:00
SamG-Coder 453fec28c5 feat(kernel): add tracked dynamic module loading and NID lookup 2026-09-25 06:48:50 +10:00
SamG-Coder 91bf8e3a7a feat(libc): implement guest file removal and renaming 2026-09-25 06:45:30 +10:00
SamG-Coder 5301f89092 feat(libc): translate guest directory enumeration 2026-09-25 06:41:55 +10:00
SamG-Coder 18790691bd feat(libc): implement guest environment variable storage 2026-09-25 06:39:14 +10:00
SamG-Coder f49cace1ca feat(libc): implement guest formatted stream output 2026-09-25 06:35:32 +10:00
SamG-Coder b8c1097db4 feat(kernel): support socket nonblocking flags through fcntl 2026-09-25 06:34:30 +10:00
SamG-Coder e8ecb29170 feat(libc): expose guest standard streams and character IO 2026-09-25 06:30:30 +10:00
SamG-Coder 56c7a589db feat(kernel): bridge guest signal registration and delivery 2026-09-25 06:27:11 +10:00
SamG-Coder cbd22dd854 feat(kernel): implement guest system configuration queries 2026-09-25 06:25:16 +10:00
SamG-Coder 9cbefb7e04 feat(kernel): implement tracked UDP sockets and ioctl 2026-09-25 06:23:44 +10:00
SamG-Coder ff725218cb feat(kernel): translate guest IP address conversion APIs 2026-09-25 06:18:32 +10:00
SamG-Coder 97e6ce992b feat(libc): implement guest errno message APIs 2026-09-25 06:17:18 +10:00
SamG-Coder cbf8362251 feat(posix): translate guest address resolution APIs 2026-09-25 06:15:32 +10:00
SamG-Coder dec5841b2d feat(libc): implement caller-backed mspace heaps 2026-09-25 06:10:50 +10:00
SamG-Coder 8a4cc838e0 Merge remote-tracking branch 'upstream/main' into feat/homebrew-game 2026-09-25 06:06:31 +10:00
SamG-Coder 1bbdf7daa6 feat(kernel): support private anonymous guest memory mappings 2026-09-25 06:06:31 +10:00
SamG-Coder 6ba24a895c feat(libs): implement homebrew string compatibility functions 2026-09-25 05:59:07 +10:00
boykopovar 9a4c8eab8b fix(libc): update locale signatures + add sysv abi to math funcs 2026-09-24 22:57:49 +03:00
boykopovar 2778c1e86e perf(agc): keep render targets on gpu across draws 2026-09-24 21:30:00 +03:00
boykopovar bf43995e8e feat(shader): implement enable cache field in recompile request 2026-09-24 20:59:34 +03:00
boykopovar e98d2163f4 refactor(log): remove extra logs + refactor timing logging 2026-09-24 20:35:59 +03:00
boykopovar 2539e9787f perf(agc): avoid guest memory uploads for rect-list fault buffers 2026-09-24 14:57:39 +03:00
boykopovar fa6d023b1b feat(agc): support rendertarget64kb shader textures 2026-09-24 11:18:35 +03:00
boykopovar c9a82af00c fix(libc): add guest-compatible c++ locale abi 2026-09-24 10:51:11 +03:00
boykopovar 594656581e feat(libs): add new std symbols + unused filter off by default 2026-09-24 10:28:33 +03:00
boykopovar d765867146 feat(libs): add new sceAgcDriver functions def 2026-09-24 08:00:36 +03:00
boykopovar f5bc2d7649 feat(libs): add new sceAgc functions def 2026-09-24 07:54:15 +03:00
boykopovar 9f2b41b9a1 fix(libc): route guest allocations through application heap 2026-09-24 06:53:12 +03:00
boykopovar 7ed9ef1e9b perf(agc): move color transfers to + gpu resources cache 2026-09-23 22:32:42 +03:00
boykopovar 630d918b4a feat(agc): add timing logs for path after recompling 2026-09-23 22:11:41 +03:00
boykopovar 10e4d5e469 perf(shader): make -ools validation and optimization optional 2026-09-23 21:48:51 +03:00
boykopovar 65c6214a68 fix(agc): validate rect-list addressing model + logs refactor 2026-09-23 21:26:21 +03:00
boykopovar 3da19adf3f refactor(video): use presentation without maintenance extensions 2026-09-23 20:10:01 +03:00
boykopovar f129f6cde5 fix(agc): accept valid hardware screen offset values 2026-09-23 16:22:20 +03:00
boykopovar 069ee78158 feat(shader): generate tessellation shaders for rect-list primitives 2026-09-23 16:13:33 +03:00
boykopovar e341cd1b30 feat(window): add fps and frame counter to window title 2026-09-23 15:30:13 +03:00
boykopovar 762b91df59 feat(libkernel): app metadata param.json parsing impl 2026-09-23 15:18:48 +03:00
boykopovar cf1953058b feat(libkernel): add app metadata reading module 2026-09-23 15:09:31 +03:00
boykopovar 282257fd98 feat(video): add resizable aspect-ratio-aware window 2026-09-23 14:27:47 +03:00
boykopovar bbde0f4680 feat(agc): support tiled color target layout 2026-09-23 13:15:30 +03:00
boykopovar 2df58cf09c fix(kernel): support page-aligned mprotect for loaded images 2026-09-23 12:45:39 +03:00
boykopovar 0b3ffe47b0 fix(shader): distinguish descriptor resources by register 2026-09-23 12:20:33 +03:00
boykopovar 30987b6543 fix(agc): allow texture descriptor performance modulation 2026-09-23 11:49:36 +03:00
boykopovar 8cd216e9d7 fix(agc): remove raw buffer restriction and decode guest buffer descriptors 2026-09-23 11:44:46 +03:00
boykopovar ab7d9a180a fix(agc): fix texture detiler context lifetime 2026-09-23 11:17:53 +03:00
boykopovar b521e1f811 test(agc): add texture resource and detiling coverage 2026-09-23 10:57:27 +03:00
boykopovar fa09114296 feat(agc): add texture and sampler descriptor bindings 2026-09-23 09:40:06 +03:00
boykopovar 7a5f5da623 feat(agc): add guest sampler creation 2026-09-23 09:28:03 +03:00
boykopovar d617677967 feat(agc): add guest texture upload - gpu detiling 2026-09-23 09:09:08 +03:00
boykopovar 596830be3e feat(agc): add gpu texture detiling shader 2026-09-23 08:56:52 +03:00
boykopovar 81d9dfde54 feat(agc): add gpu-based texture detiling 2026-09-23 08:48:29 +03:00
boykopovar efa62f3546 feat(agc): implement texture tiling layout 2026-09-23 08:31:56 +03:00
boykopovar 0bb7f38510 feat(agc): texture format mapping and properties 2026-09-23 08:11:40 +03:00
boykopovar 1fd955711b feat(agc): implement guest sampler resource decoding 2026-09-23 08:06:06 +03:00
boykopovar 8e05ec2fa3 feat(agc): implement guest texture resource decoding 2026-09-23 08:00:22 +03:00
boykopovar f50946adf0 build(agc): wire agc texture support into cmake 2026-09-23 07:40:22 +03:00
boykopovar 5c7dc027ea feat(agc): add agc texture support definitions (wip) 2026-09-23 07:25:23 +03:00
boykopovar 77f44a1a8d refactor(agc): report unimplemented image/sampler resources 2026-09-22 21:51:35 +03:00
boykopovar bb27de6fac feat(shader): add fragmentShaderBarycentricEnabled flag to recompiler 2026-09-22 21:35:45 +03:00
boykopovar 4734f43c60 feat(agc): add ACQUIRE_MEM handling in agc driver 2026-09-22 20:35:15 +03:00
boykopovar 8fd65f2a25 add EVENT_WRITE support for CS/GS/PS_PARTIAL_FLUSH + relinker return exit code from autorun 2026-09-22 20:27:49 +03:00
boykopovar f7aaa2fb86 feat(agc): add DRAW_INDEX_AUTO handling impl 2026-09-22 20:07:09 +03:00
boykopovar bf7e41bb8b feat(agc): add new context state op impl 2026-09-22 19:44:17 +03:00
boykopovar 7fa0e0c469 fix(libc): add sort function manual impl for compare abi 2026-09-22 18:35:09 +03:00
boykopovar a43f73163d feat(libs): no patch already exported from libc.prx symbols 2026-09-22 18:21:08 +03:00
boykopovar e3a960e4d1 feat(libs): add sce pad read state default value 2026-09-22 12:08:56 +03:00
boykopovar 79c9aa587b feat(agc): add fragment shader barycentric support 2026-09-22 11:43:39 +03:00
boykopovar 5e3a13041c feat(agc): implement vertex attribute input and buffer binding 2026-09-22 11:34:54 +03:00
boykopovar 5b424406a5 fix(agc): enable float controls and validate subgroup capabilities 2026-09-22 11:23:58 +03:00
boykopovar 1da8521ffc feat(shader): add spirv validation and opt via spirv-tools 2026-09-22 10:43:54 +03:00
boykopovar 798e38f47e fix(shader): fix recompile request memory snapshot and descriptors 2026-09-22 10:19:48 +03:00
boykopovar e7633a7f07 fix(shader): thread cb_color0_info swap into pixel input color component mapping 2026-09-22 09:28:46 +03:00
boykopovar f38c6cd7af feat(shader): implement checked BDA reads and GPU fault reporting 2026-09-21 19:26:09 +03:00
boykopovar 2b7eec45ac test(agc): cover partial guest mappings 2026-09-21 19:02:06 +03:00
boykopovar 3028c87491 feat(agc): add bda memory mapping and resource management (wip) 2026-09-21 18:54:06 +03:00
boykopovar 48d08397d9 fix(shader): fix build break from bda cache page bits field 2026-09-21 18:08:03 +03:00
boykopovar 1490c0386c refactor(agc): unify shader resource bindings and push constants 2026-09-21 13:48:44 +03:00
boykopovar d1dd4590fa feat(shader): spirv image emitter functions impl (wip) 2026-09-19 07:33:30 +03:00
boykopovar 3c06704751 chore(agc): add vulkan device logs 2026-09-19 07:02:48 +03:00
boykopovar 3da76b9b33 refactor(graphics): add new graphics pipeline log + remove redunant ones 2026-09-18 21:03:11 +03:00
boykopovar 8be7c9d191 feat(shader): add test shaders return + graphic pipeline logs 2026-09-18 20:38:26 +03:00
boykopovar f7b5df1711 feat(shader): decode embedded vertex fetch metadata for vertex-family stages 2026-09-17 12:00:14 +03:00
boykopovar 50226e4260 feat(shader): impl agc-side register decode and translator input wiring 2026-09-17 11:02:58 +03:00
boykopovar 4b2fe93080 feat(agc): add standalone shader test for libSceAgcDriver 2026-09-16 07:43:05 +03:00
boykopovar 9c78d10044 fix(agc): support unrestricted vulkan depth range 2026-09-16 07:24:00 +03:00
boykopovar f0b13b6652 fix(agc): support negative depth range and inactive color targets 2026-09-16 07:21:13 +03:00
boykopovar 05ec432f75 fix(agc): non-homogeneous positions with all viewport transforms enabled 2026-09-16 07:11:00 +03:00
boykopovar f73834ce2f fix(agc): complete initial context state and tighten shader validation 2026-09-16 07:04:23 +03:00
boykopovar 74613f7e0f feat(agc): extend graphics compiler contract and add mesh and tessellation paths 2026-09-15 21:19:06 +03:00
boykopovar 215e3cbf48 fix(agc): fix missing register at DWORD 677 (wip) 2026-09-15 12:38:01 +03:00
boykopovar 77b96978c7 feat(agc-driver): add strict vulkan indexed draw pipeline 2026-09-15 12:28:25 +03:00
boykopovar d084eed394 feat(shader): rdna memory op decoder impl 2026-09-15 07:07:50 +03:00
boykopovar fd5e236aad feat(videoOut): add tiled buffer presentation and flip lifecycle handling 2026-09-14 12:38:16 +03:00
boykopovar b9cc7ffd85 feat(agcDriver): add draw handling and shader recompile preparation 2026-09-14 12:06:35 +03:00
boykopovar 699df8d5fa feat(agcDriver): add 54 PM4 execution and indirect dispatch support 2026-09-14 11:43:13 +03:00
boykopovar 990ae6a0ff feat(agcDriver): add opcode 18 handling as clearing 2026-09-14 11:18:21 +03:00
boykopovar 9f8225aa6d chore(libc): log only name for sibling file in fopen 2026-09-14 11:06:21 +03:00
boykopovar b0b1902b0f chore(libc): make file open slash preferred for system 2026-09-14 10:56:33 +03:00
boykopovar 1e4740ed4b fix(nid): no patch sdl exports for nid 2026-09-14 10:52:04 +03:00
boykopovar d31e35e1ab feat(agc): add flip presentation and suspend synchronization (wip) 2026-09-14 07:39:38 +03:00
boykopovar b024001a4a fix(libc): fix sprintf_nid_postfix register for linux 2026-09-14 07:23:23 +03:00
boykopovar ed171b23da feat(agc): add driver submission queue and vulkan compute path 2026-09-14 06:37:19 +03:00
boykopovar 87b52a99c8 feat(agc): add sceAgcGetDataPacketPayloadAddressUnk impl 2026-09-13 19:46:30 +03:00
boykopovar bed94ee90a fix(agc): add nullptr values handling for WriteRegisterRange 2026-09-13 19:41:29 +03:00
boykopovar bd0969c3a4 fix(libs): ex from libc prx: unwind for catch fix (mingw) 2026-09-13 19:21:31 +03:00
boykopovar bdff4874de feat(agc): add draw packets and register defaults with strict validation 2026-09-13 18:14:51 +03:00
boykopovar 8e95b27583 chore(cmake): add cmake option -DAPS5_AGC_CREATE_LOG 2026-09-13 17:44:17 +03:00
boykopovar 5d715ee549 refactor(libkernel): move from Export.cpp to separated files 2026-09-13 16:41:04 +03:00
boykopovar 8f2bca5481 refactor(libkernel): merged dup pthread functions from _sys and _web 2026-09-13 16:24:42 +03:00
boykopovar 1468fc7d6c refactor(libs): remove function dups from libSceAgcVsh 2026-09-13 15:17:07 +03:00
boykopovar 4863c251f1 refactor(AgcDriver): add subdirs to libSceAgcDriver + separated new src 2026-09-13 15:09:19 +03:00
boykopovar 888abd280f refactor(libSceAgc): add subdirs + new separated src 2026-09-13 15:06:31 +03:00
boykopovar 114c11aa88 feat(libSceAgc): implement command packet functions 2026-09-13 14:34:15 +03:00
boykopovar 7773bbcbf8 chore(sceVideoOut): throw ex instead of stubs 2026-09-13 13:52:41 +03:00
boykopovar 78f183ced8 feat(core): add and link to Agc not implemented shader recompilier 2026-09-13 13:47:13 +03:00
boykopovar fcb0764473 refactor(libs): organize libSceAgcDriver with cmakelists 2026-09-13 13:29:19 +03:00
boykopovar 7c44d13b3a feat(libs): global shared path resolver in libc 2026-09-13 12:45:50 +03:00
boykopovar f66a8fc5c4 feat(libkernel): libkernel file functions impl 2026-09-13 12:07:47 +03:00
boykopovar f19a234f38 feat(libkernel): add gettime getres gettimeofday impl 2026-09-13 11:21:37 +03:00
boykopovar 4781694512 feat(libs): NpTrophy2 impl + fopen not found logic update 2026-09-13 11:01:59 +03:00
boykopovar 0c2cfe0564 feat(NpTrophy2): add user data constants 2026-09-13 10:35:37 +03:00
boykopovar 42e1bad3d2 refactor(libs): move NpTrophy2 types from global SceTypes to libSceNpTrophy2 2026-09-13 10:30:13 +03:00
boykopovar 7d40561780 refactor(libs): organize NpTrophy2 with cmakelists 2026-09-13 10:19:56 +03:00
boykopovar 94ab47a417 feat(libkernel): some semaphore functions impl 2026-09-12 19:27:53 +03:00
boykopovar e38f76a823 refactor(libkernel): move some functions from export.cpp to new semaphore and file 2026-09-12 19:05:39 +03:00
boykopovar 8cd754c751 feat(libs) libSceNpGameIntent impl + refactor NpUniversalDataSystem 2026-09-12 18:53:36 +03:00
boykopovar 67996b7a69 feat(libs): libSceNpUniversalDataSystem functions impl (no net) 2026-09-12 18:29:57 +03:00
boykopovar 357d7fa373 refactor(libs): organize sceNpUniversalData with cmakelists 2026-09-12 18:12:18 +03:00
boykopovar b4db9fdd69 chore(sceSysmodule): log unknown module id loading 2026-09-12 18:00:34 +03:00
boykopovar d225df7449 feat(sceVideoOut): implement sdl2 window and present thread 2026-09-12 17:32:24 +03:00
boykopovar 49e200c88a feat(sceAudioOut): audio out init functions impl 2026-09-12 17:01:21 +03:00
boykopovar a7521f3a7e feat(libkernel): libkernel time functions impl 2026-09-12 16:33:29 +03:00
boykopovar 5d7bee9a1f refactor(libs): organize sceAuodioOut lib with cmakelists 2026-09-12 16:16:41 +03:00
boykopovar 37c8bafd13 fix(libkernel): fix export non-ps5 functions with extern c 2026-09-12 16:07:14 +03:00
boykopovar 31943e9a62 fix(sceVideoOut): add nid_postdfix to equeue libkernel exports 2026-09-12 11:21:01 +03:00
boykopovar 497821e94f feat(sceVideoOut): video out functions impl (wip) 2026-09-12 11:02:17 +03:00
boykopovar 69b8080ea4 feat(libkernel): add equeue functions impl 2026-09-12 10:40:27 +03:00
boykopovar bd16eaaacf refactor(libs): organize libSceVideoOut with cmakelists 2026-09-11 16:41:01 +03:00
boykopovar e9bbde1a6e refactor(libkernel): pthread functions separation 2026-09-11 14:12:44 +03:00
boykopovar 67b778055a refactor(libs): use local cmakelists in libc 2026-09-11 12:22:19 +03:00
boykopovar 08b1968b15 fix(libs): repack pe export names contiguously instead of edata no free space ex 2026-09-11 08:38:42 +03:00
boykopovar a1116fe948 feat(libc): windows way for ex handling (wip) 2026-09-11 08:17:12 +03:00
boykopovar ea3f7b5ae0 fix(windows): va_list sysv abi parse for fomatting functions 2026-09-11 07:49:14 +03:00
boykopovar 999a723a5f fix(windows): precommit guest thread stacks to prevent guard page skips 2026-09-10 20:25:25 +03:00
boykopovar b765cefa42 fix(libs): fix args sysv abi for types (windows) 2026-09-10 19:54:03 +03:00
boykopovar c0c1ac4424 fix(libs): fix build sysv abi on mingw 2026-09-10 14:34:43 +03:00
boykopovar 36c29c9a66 feat(libs): sysv abi macros for windows exports 2026-09-10 13:30:05 +03:00
boykopovar 74de895ac0 feat(libs): add new libSceAgc unknown functions 2026-09-10 09:43:59 +03:00
boykopovar 8400150f80 feat(libs): add new declarations to libSceAgc 2026-09-10 09:09:08 +03:00
boykopovar 411a4d00a5 feat(libs): add change export name macros 2026-09-10 08:22:39 +03:00
boykopovar abc72da741 feat(libs): define vabi macros + add to declarations 2026-09-10 08:07:03 +03:00
boykopovar e62c08f625 feat(libs): add new functions declarations 2026-09-09 09:12:30 +03:00
boykopovar 24620106c5 fix(nid): sort pe exports and preserve ordinal mappings 2026-09-09 08:46:43 +03:00
boykopovar a369e0126c feat(libs): nid patching for non-std imports from prx 2026-09-09 08:12:27 +03:00
boykopovar 81d7adea95 feat(log): log system detalization 2026-09-08 12:10:49 +03:00
boykopovar 13b30f93a9 feat(libSceAgc): libSceAgc shaderCreate impl 2026-09-08 11:16:02 +03:00
boykopovar 8730fa1e6e refactor(libSceAgc): create libSceAgc cmake project structure 2026-09-08 11:03:13 +03:00
boykopovar 814287ef47 feat(libs): libSce types impl + shaders refactor 2026-09-08 10:20:57 +03:00
boykopovar 7cf8576587 feat(build): all libs link libc + libkernel 2026-09-08 09:35:28 +03:00
boykopovar 6e8f04a65a feat(libkernel): cross platform libkernel build 2026-09-08 09:17:39 +03:00
boykopovar fca5dc8782 feat(libc): cross pltaform build 2026-09-08 09:08:00 +03:00
boykopovar 07d1463ae1 fix(libkernel): replace throwing with return err code for invalid len 2026-09-08 00:16:56 +03:00
boykopovar 8ad0a9897d feat(libs): libSceCommonDialog + stub libSceSaveDialog impl 2026-09-07 23:24:55 +03:00
boykopovar ce729fb9c7 fix(libkernel): fix random direct memory bug 2026-09-07 20:39:54 +03:00
boykopovar c5f82f0d5c chore(libc): add fopen error details 2026-09-07 20:06:51 +03:00
boykopovar fdd7049250 fix(libc): fix ftools exports 2026-09-07 19:54:01 +03:00
boykopovar 6c4d6c18b2 fix(libkernel): fix scePthreadCreate sync 2026-09-07 19:13:33 +03:00
boykopovar 5f7ef909f8 feat(libs): libcSceSaveData impl (wip) 2026-09-07 13:42:25 +03:00
boykopovar 96dd0e03dc chore(libs): skip monitor sensor check 2026-09-07 12:44:00 +03:00
boykopovar c3993df466 feat(libs): libScePad partial impl 2026-09-07 12:14:06 +03:00
boykopovar eb3af4e253 feat(libs): libSceuserService partial impl 2026-09-07 11:58:54 +03:00
boykopovar 73f0d15b63 feat(libs): add libSceSystemService impl 2026-09-07 11:53:43 +03:00
boykopovar 5ae2a810e9 feat(libult): add libsceult impl 2026-09-07 11:37:55 +03:00
boykopovar 7592031dc9 feat(libs): add windows branch for get sysmodule info 2026-09-07 11:21:44 +03:00
boykopovar 0bbf0923ef feat(sysmodule): add new modules mapping 2026-09-07 11:17:36 +03:00
boykopovar 14f8c16ac4 fix(libs): add _nid_no_patch_cut postfix and global cxa/unwind exports 2026-09-07 10:56:34 +03:00
boykopovar 1e0fc3f33a feat(libs): add libSysmodule impl 2026-09-07 10:55:32 +03:00
boykopovar bc14e4743c fix(relinker): map zero-flag ps5 load segments as rwx 2026-09-07 10:10:00 +03:00
boykopovar 9d4c87b686 fix(nid): fix updates detections for nid_patcher rerun 2026-09-07 09:55:41 +03:00
boykopovar d5bc6c9f66 refactor(libkernel): remove dup functions 2026-09-07 09:41:47 +03:00
boykopovar 975e4a72d4 refactor(libkernel): refactir direct memory exports organization 2026-09-07 09:08:59 +03:00
boykopovar e77d724a1b feat(libkernel): add pthread module impl(wip) 2026-09-07 08:50:31 +03:00
boykopovar e79f5ebc58 refactor(libkernel): separate direct memory impl 2026-09-07 08:08:31 +03:00
boykopovar 53b20aec77 refactor(nid): separate nid resolving logic 2026-09-07 07:52:09 +03:00
boykopovar 6ecfc35551 feat(libkernel): libkernel direct memory impl 2026-09-06 16:03:29 +03:00
boykopovar 72af167a9f fix(libc): add extern c for not impl helper header 2026-09-06 15:26:09 +03:00
boykopovar 8ac1af0513 fix(libc): no inline for not impl helper 2026-09-06 15:20:07 +03:00
boykopovar b000880913 chore(nid): restore skip nid_no_patch 2026-09-06 15:06:59 +03:00
boykopovar 6123893998 feat(libs): throw not impl ex in every stub 2026-09-06 15:05:04 +03:00
boykopovar 64ed717e77 fix(nid): no skip symbols without nid_postfix 2026-09-06 14:27:22 +03:00
boykopovar ec8faf3ed7 feat(libs): add general not implemented helper 2026-09-06 14:11:05 +03:00
boykopovar 58aef08fe1 feat(nid): add nid_no_patch rule 2026-09-06 13:49:24 +03:00
boykopovar 228d95be52 feat(nid): check exported symbols dup 2026-09-06 13:30:17 +03:00
boykopovar ba6d7afc22 refactor(libc): __attribute__ replacing and removing 2026-09-06 13:02:22 +03:00
boykopovar c8391bfb67 refactor(libc): remove non-std link.h 2026-09-06 12:51:24 +03:00
boykopovar 4fd128a40d refactor(libc): remove strings.h linux specific 2026-09-06 12:45:37 +03:00
boykopovar 1752e1d78e refactor(libc): separate platform and compiler specifics in libc 2026-09-06 12:41:33 +03:00
boykopovar 7e61d94b30 feat(libc): print unhandled ex type and what() on terminate 2026-09-06 11:45:06 +03:00
boykopovar baa8a8d9d3 feat(libc): add ex tests + remove bad_alloc dup 2026-09-06 07:30:59 +03:00
boykopovar 57aedfcff0 chore(libs): include exceptions to libc export 2026-09-05 22:32:29 +03:00
boykopovar f449ebb636 fix(libc): fix exception matching + foreign exception handling 2026-09-05 20:13:14 +03:00
boykopovar 36c874e296 feat(libc): implement exception unwinding + array cleanup 2026-09-05 19:54:11 +03:00
boykopovar 6fcbf1f829 feat(libc): init c++ exception runtime for x8664 linux (wip) 2026-09-05 19:34:15 +03:00
boykopovar 9ac0798c09 feat(libc): add new std functions 2026-09-05 19:13:39 +03:00
boykopovar 4945be96ef feat(libs): runtime std dynamic linking for libc 2026-09-05 18:57:58 +03:00
boykopovar 4f760dd6ff feat(libc): add new exception symbols 2026-08-30 14:24:43 +03:00
boykopovar 271a850022 fix(libs): link std lib only to libc prx 2026-08-24 20:47:53 +03:00
boykopovar e82abc96c4 fix(nid): remove jump_slot records filtering 2026-08-22 19:35:34 +03:00
boykopovar a5e09e7e16 feat(libs): add new sceAgcDriver and sceUserServiceTerminate stubs 2026-08-22 17:02:29 +03:00
boykopovar 24f78f57cc feat(libs): implement missing locale and mbstate stubs for libc 2026-08-22 16:50:55 +03:00
boykopovar c27c547810 feat(libs): add locale support funcs to libc 2026-08-22 16:34:48 +03:00
boykopovar 85e3047c04 feat(libs): add atexit and atomic functions to libc 2026-08-22 16:22:19 +03:00
boykopovar a89b9228f1 fix(libs): fix libc building on win 2026-08-22 16:16:11 +03:00
boykopovar 5a1d7525f9 feat(libs): libc impl (wip) 2026-08-22 16:00:29 +03:00
boykopovar b1f51a3e4b feat(nid): remap dynamic needed offsets 2026-08-22 14:11:42 +03:00
boykopovar e838a2d9df fix(nid): rebuild ghu hash for patched nid 2026-08-22 11:47:41 +03:00
boykopovar 8672a5cc3d fix(libs): libc export flag name fix 2026-08-22 11:18:42 +03:00
boykopovar b49279e832 fix(nid): update nid computing algorithm 2026-08-22 10:39:19 +03:00
boykopovar 54e66624ec fix(libs): fix nid compute algorithm - no lib name 2026-08-21 17:19:22 +03:00
boykopovar f23cc495f4 fix(nid): rebuild dynstr instead of in-place patch to avoid suffix-merge corruption 2026-08-21 16:24:16 +03:00
boykopovar e2646635d0 feat(libs): add lib ime backend stub 2026-08-21 16:08:10 +03:00
boykopovar 39ebe6a054 feat(libs): add libc shared lib stub 2026-08-21 15:56:03 +03:00
boykopovar 6dfd5a9296 refactor(nid): rename spec cpp + move utils 2026-08-21 15:16:25 +03:00
boykopovar c6550929e9 refactor(nid): windows and linux pathing separating via interface 2026-08-21 15:00:55 +03:00
boykopovar 55a120e318 fix(nid): detect linker suffix-merged symbol names postfixes 2026-08-21 14:45:07 +03:00
boykopovar ca37e667f9 fix(nid): patch linux nid in place + detailed overflow msg 2026-08-21 14:13:58 +03:00
boykopovar 486bb51167 fix(nid): exclude undefined dynamic symbols from elf nid patching 2026-08-21 00:32:00 +03:00
boykopovar 8627076df5 fix(libs): drop std name collisions via nid postfix + remove custom entry point 2026-08-21 00:26:40 +03:00
boykopovar ca38455917 fix(nid): grow export names in place within existing section padding for pe and elf 2026-08-21 00:15:21 +03:00
boykopovar 47099897ac fix(libs): fix libscelibcinternal crt symbol conflict, stray macro in pthread_once, missing typedefs, unnamed params 2026-08-20 23:58:06 +03:00
boykopovar 59bee8d187 feat(libs): add libs function signatures 2026-08-20 23:18:16 +03:00
boykopovar aba18915ba fix(libs): fix nid patching after libs build 2026-08-20 17:32:00 +03:00
boykopovar 9e21a054e0 feat(libs): add rpx library build as libs target 2026-08-20 17:06:41 +03:00