COND_WRITE (opcode 0x45) with a memory poll and a memory destination is
validated and executed: the driver drains the queue like WRITE_DATA,
reads the poll dword through the range synchronization, compares it
masked with the reference like a 32-bit WAIT_REG_MEM, and writes the
data dword on a match. Register polls and register or scratch
destinations are rejected.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The masked case loaded EXEC from a scalar literal. A scalar mask is read
by subgroup lane, so on a host whose subgroups are narrower than the wave
(llvmpipe: 8 lanes) lane 16 took bit 0 and stayed active. v_cmpx_gt_u32
on the thread id gives the same low 16 lanes on any subgroup size.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Both swap data0 with the dword at addr + offset0 and data1 with the dword
at addr + offset1, and return the two previous values in vdst and vdst + 1.
The offsets are scaled by 4 bytes, or by 256 bytes for the st64 form.
Each location goes through the existing SharedAtomicSwap32.
An encoding whose two offsets are equal is rejected at decode time.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceAgcAsyncCondExecPatchSetCommandAddress and
sceAgcAsyncCondExecPatchSetEnd patch the COND_EXEC packet like their
graphics counterparts, since sceAgcAcbCondExec writes the same packet
as sceAgcDcbCondExec. Both variants share one implementation, as the
REWIND patches do.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The query writes the maximum resource name length (0xfc) through its
output pointer and returns 0, as prosper does from a title's registration
configuration. The parameter follows the SDK wrapper
sce::Agc::ResourceRegistration::getMaxNameLength(unsigned int*). Resource
registration itself stays unavailable.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
PPSA22520 lists libSceNgs2.prx, not libSceNgs2.native.prx, among its needed
modules, so its NGS2 imports did not resolve against the dummy module. Both
modules are now built by add_sce_ngs2_library from the same sources, as
libSceFont and libSceFont.native share add_sce_font_library, and the render
tests also run against libSceNgs2.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Rack 0x2001 is created with its option layout and KytyPS5's defaults, takes
the setup (0x20010000) and I3DL2 (0x20010001) voice params and reports the
common voice state. The voice mixes its inputs and runs a Freeverb-style
approximation driven by the I3DL2 parameters: room and room HF, early
reflections and their delay, late reverb and its pre-delay, decay time and
HF ratio, and diffusion. Out-of-range params throw, param changes keep the
tail, a stop or kill clears it, and the tail ends once it decays below
1e-20. The console's algorithm is unknown; the approximation is recorded in
TechnicalDebt. The test context buffer pool grows to 64.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Mastering voice param 0x30000004 sets a full-band and an LFE level. They
scale the mastering voice when it is mixed into the render buffer, the LFE
level on channel 3 of 6- and 8-channel voices. Non-finite levels are
invalid arguments.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
SDL_CreateWindow with SDL_WINDOW_VULKAN loads and queries the Vulkan loader
while the render thread can be inside vkCreateInstance. On Windows the two
together intermittently made the NVIDIA ICD fail instance creation (-3) and
the loader return VK_ERROR_INCOMPATIBLE_DRIVER. libSceAgcDriver now exports
a loader lock that the VulkanDevice constructor and DisplayWindow::create
both hold.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A port without an SDL device slept one block after its previous output on
every call. Rounded-up sleeps held titles that write several ports from one
thread below real time. Such ports now keep a virtual queue that drains in
real time and only wait when it holds more than the target latency.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The SDK 9 libc.prx heap maps its arenas with flag 0x8000, which threw as
an unsupported flag. The flag is ignored for this function, as sharpemu
does; other unknown flags still throw.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A qualified import whose module name matches no DT_NEEDED entry now uses
the unqualified search order instead of failing with "Import module is
not a dependency". Restore the Linux rejection of duplicate exports
within one guest module.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
On Windows APS5_VABI is sysv_abi, so the exports did not convert to
plain function pointers and the test did not compile.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
MinGW rejects alignas(65536) on a global, as COFF objects allow at most
8 KiB, so the 64 KiB-aligned texels are taken from a larger buffer.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A sampler descriptor with BORDER_COLOR_TYPE 3 names an entry of the border
colour table, but the hardware reads it only through an axis that addresses
the border (clamp modes 4 to 7). DecodeSamplerResource threw for every
table border colour, so a sampler that clamps to the edge on all axes, as
PPSA21567's Armadillo Challenge 2 compute shader uses, stopped the title
although its border colour is never sampled. It now throws only when an
axis uses a border mode, the same rule the colour compare emulation
applies, and otherwise uses a fixed Vulkan border colour.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
s_movrels and s_movrelsd_2 read the source register through a chain of
selects keyed on the M0 offset, and the relative destination write is a
select between that value and the old register. When the old register
also appears in the chain, the NVIDIA compiler (RTX 5080, 610.74)
evaluates select(a, select(b, x, y), x) as select(a || b, y, x) instead
of select(a && !b, y, x), so s_movrelsd_2_b32 clobbered s13 whenever the
source offset was 3. Rewriting the select, a branch with a phi, a masked
xor or a small function array all fold back into the same form.
Build the read as an OR of select(offset == k, s[base + k], 0) terms, with
the base register used for offsets outside [1, count) as before. The
result is unchanged, and the select nesting the compiler mishandles no
longer forms.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
The test now catches the exception that Parser::parse throws for a number
that overflows a double. Windows test executables need
configure_windows_unwind, as guest_png_dec_tests has, or the exception
cannot be unwound and the process terminates.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01R5WJS4ZdQynAJesCZKH5hb
Whether the console's parser rejects 1e309 or stores an infinite real
is unknown, and RFC 8259 allows both. Following the exact-or-throw rule,
sce::Json::Parser::parse now throws with the number text and a note that
the behaviour is unverified, instead of returning JsonErrorParse. The
partially built tree is freed before the exception leaves the parser.
The case is listed under unknown function info in TechnicalDebt.md.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01R5WJS4ZdQynAJesCZKH5hb
The parser stored strtod's result for 1e309 and similar numbers, so a
document with such a value parsed as an infinite real. Serializing it
then threw "cannot serialize a non-finite number", which escaped the
guest call and terminated the process. sce::Json::Parser::parse now
returns JsonErrorParse for a number that is not finite after conversion.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01R5WJS4ZdQynAJesCZKH5hb
3D textures in the 64 KiB Z and S XOR swizzles threw. As in AMD
addrlib's GFX10 rules, a Z_X volume is thin: each depth slice is laid
out like an array slice with the 2D Z_X equation, as the R_X and D_X
volumes already were. An S_X volume is thick: it takes the standard
64 KiB thick block and mip tail with its own S3 XOR equation, generated
from addrlib for the same configuration as the other equations.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The Smurfs Dreams (Unreal Engine) asks only for the game details and
passes a null data pointer; on success it reads the trophy count from the
details, on a negative result it takes its error path. The function
already fills each output only when it is given, but rejected the call
unless both were. Only a call without either output is rejected now.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A T# of type 12 (1D array) threw while decoding. It now decodes to a
1D array dimension, checked like a 2D array with a height of one, and
holds depth + 1 layers laid out as a 2D array's. Its Vulkan image is
1D with that many layers, viewed as VK_IMAGE_VIEW_TYPE_1D_ARRAY for
sampling and storage, and the recompiler declares a 1D array shape for
arrayed 1D image resources instead of failing.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
image_gather4_lz_o on a 1D view threw. The 1D gather emulation picks
the two texels around the coordinate itself, so the 6-bit x offset of
the address is added to the left texel index before both texel
centres are sampled, as the hardware offsets the footprint.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Titles that link the native module (The Smurfs Dreams imports
sceAudiodecClearContext and the other decoder exports from
libSceAudiodec.native) found only the dummy export there. Both modules
are now built from the same sources, as libSceFont and libSceAvPlayer
already do for their native modules.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
scePadVrControllerRead and scePadVrControllerGetDeviceInformation are
imported by titles that open PSVR2 Sense controller port types. No
library exported them, so eager binding failed at startup.
Declare them as throwing stubs: the VR controller port types are not
supported, and scePadOpen already rejects them.
sceAgcWriteDataPatchSetDst, sceAgcWriteDataPatchSetCachePolicy, their
Async forms and sceAgcAsyncWriteDataPatchSetAddressOrOffset threw. They
now rewrite a WRITE_DATA packet in place: the destination in the
graphics (sceAgcDcbWriteData) or compute (sceAgcAcbWriteData) encoding,
the cache policy in bits 25-26 and the address in dwords 2-3, so the
patched packet equals the one written with those values. A register
destination is rejected when the packet requests write confirmation,
as when the packet is written.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Unreal Engine reserves SET_*_REG_INDIRECT packets with a null register
list and no registers, and fills them in later with the
sceAgcSet*RegIndirectPatch* functions. The writers rejected the null
address. A null list is now accepted when it holds no registers, which
reads nothing; a null list with registers still throws.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
PPSA14632 (Unreal Engine) writes sceAgcCbBranch(mode 1, compare
function 0, mask 0, reference 0) with a then buffer and a null else
buffer of 0 dwords. It leaves the compare address uninitialised, so it
is sometimes only 4-byte aligned. The writer rejected the null else
buffer and the misaligned compare address, and the driver accepted
opcode 0x3f only as the 4-dword INDIRECT_BUFFER, so the 14-dword branch
would have failed at submission.
sceAgcCbBranch no longer checks the compare address of an always-pass
branch, which reads nothing, or the address of a buffer of 0 dwords.
The driver runs the first buffer of an always-pass COND_INDIRECT_BUFFER
in modes 1 and 2 (if-then and if-then-else) in place of the packet. A
comparison, a predicated branch and other modes throw.
Co-Authored-By: Claude Opus 5.5 <[email protected]>