Use the synthetic shader input and export state when selecting the null pixel program. Keep ordinary shader validation unchanged. Written with AI assistance.
A compute program with COMPUTE_PGM_RSRC2.SCRATCH_EN takes its per-lane private size from the AGC
shader header (scratch_size_dw_per_thread) instead of being refused. The size travels in
ShaderComputeStageInfo (cache key, request serialization version 10) to the translator, whose
scratch accesses already lower to a per-invocation Function array of that many dwords.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
On the console a title whose param.json declares downloadDataSize finds
/download0 mounted from the start. The host directory was only created
by sceAppContentDownloadDataGetAvailableSpaceKb, so a title that opens
files there directly got ENOENT. libkernel now creates it when it loads,
reading only the run directory's param.json, without resolving guest
paths, so the libc path root is still fixed at first use.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Color targets with the SW_64KB_S swizzle (CB_COLOR_ATTRIB3 tile mode 9) use the standard element
order of the 4 KiB mode extended by the texture detiler's 64 KiB bits, and are resident like the
other tiled targets. The standard blocks are now wider than tall for 2- and 8-byte elements, as the
standard swizzle and the texture layout have them (they were transposed, aliasing texels).
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
A context that never wrote SPI_PS_INPUT_ENA or SPI_PS_INPUT_ADDR after CLEAR_STATE reads them as
zero, like the hardware, instead of refusing the draw for a missing register (a depth-only draw
whose pixel shader takes no inputs).
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
BnMAMrsfVWo is _ZSt19_Throw_bad_weak_ptrv. Replace the unknown stub
with a throw of a guest std::bad_weak_ptr, and add its type info,
vtable, destructors and what().
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Treat equal BASE_ARRAY and DEPTH as a six-face cube. Measured with image_load, image_sample and image_get_resinfo on RX 6600 gfx1032 using base slices 0, 5 and 6. Partial cube ranges still throw because filtered sampling differs from load bounds.
Graphics tests and GPU snapshot/storage sampling tests pass for all six faces at each tested base.
Assisted-by: OpenAI Codex
FreeBSD's setvbuf takes a zero size with _IOFBF or _IOLBF as "pick the
buffer size". The UCRT rejects sizes below 2 for those modes through
its invalid parameter handler, so the call failed on Windows and a test
process was terminated. A zero size now drops the given buffer and
asks the host for one of BUFSIZ bytes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Gathering every iovec into one host buffer threw for a total above
INT_MAX, which a console readv/writev accepts, and copied the whole
transfer twice. Each iovec is now read or written in place, in chunks
of at most INT_MAX bytes. A readv on a pipe returns after one read so
it does not block once the available bytes are consumed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01UTjpbMX7BUFMZZaxJE98zV
sceKernelReadv, sceKernelWritev, sceKernelPreadv and sceKernelPwritev threw on Windows. They now gather or scatter through one host buffer and issue a single read or write, with the same argument checks and error codes as the Linux path. Positioned transfers restore the file offset afterwards, as pread and pwrite do on POSIX, and report ESPIPE for handles that are not disk files. guest_file_vector now runs on Windows as well.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01UTjpbMX7BUFMZZaxJE98zV
COPY_DATA rejected source select 9 (GPU clock count) and any cache
policy bits. PPSA16064 (Minecraft Dungeons II, Unreal Engine)
calibrates its GPU timer at start-up with a submission of five
COPY_DATA packets, control 0x06016209: GPU clock source, memory
destination, 64-bit count, source and destination cache policy 3. The
submission was rejected and the title aborted.
The clock source now writes the same counter as a RELEASE_MEM
timestamp (the host steady clock in 10 ns ticks), read when the packet
runs, through the direct execute path and through ResolveStore for
stores recorded on the GPU. A 32-bit count writes its low half. The
source and destination cache policy fields are accepted and ignored,
as for WRITE_DATA and DMA_DATA. The reference clock (source select 10)
and the other unimplemented sources still throw.
agc_driver_pm4 runs the title's packet twice and checks a nonzero,
non-decreasing counter and an 8-byte resolved store, and that source
select 10 is still rejected.
MinGW's thread_local goes through emutls and winpthreads' pthread_getspecific, which holds a per-thread spinlock. A raise that redirected a thread holding it ran the handler on that same thread, and a handler reading any thread_local, scePthreadSelf for one, spun on the lock forever. A raise that finds the target inside libwinpthread-1.dll now resumes it and suspends it again, as one inside NtContinue does.
guest_raise_exception's new phase raises at a thread that calls scePthreadSelf in a loop and checks that the handler sees its own thread. It hung in every run without the retry. TechnicalDebt records that a handler can still reenter other host code the thread was interrupted in.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The guest's wchar_t is 16 bits, but wcslen, wcscmp, wcsncmp, wcscpy, wcsncpy, wcschr, wcsrchr, wcsstr, wcspbrk, wcsspn and the wmem functions forwarded to the host's wchar_t functions, which use 32-bit units on Linux. Implement them on char16_t. The wide conversions that still use the host's wchar_t are listed in TechnicalDebt.
NVIDIA (595.91.07) refuses VK_EXT_external_memory_host imports of
read-only or executable mappings with VK_ERROR_OUT_OF_DEVICE_MEMORY and
then fails every later vkAllocateMemory on the device. Check the range
is mapped read-write before importing on Linux, as the Windows path
already does for read-only memory, and copy it otherwise.
Refs #1022
Exclude COLOR_INVALID attachments from the effective write mask while preserving later MRT export indices and depth-only rendering. Validated with the graphics tests and Skyrim menu draws.
AI-assisted implementation and testing by OpenAI Codex.
guest_formatting called sprintf with four variadic arguments and
libc_printf with one, all in registers, and did not call sscanf, so only
snprintf had a check that fails with the old Linux register rebuild. sprintf
now formats six integers, sscanf converts eight fields and libc_printf prints
seven integers; on the old code the first gives "1 2 3 4 0 0" and the other
two crash.
Checks suggested by nauroth in #1435.
The host's EHOSTUNREACH was reported as ENETUNREACH (51); FreeBSD's
EHOSTUNREACH is 65, which libkernel's sockets already report. EADDRNOTAVAIL,
ENOBUFS, EISCONN, ENOTCONN and EACCES had no translation and became EIO;
they now map to 49, 55, 56, 57 and 13, as in libkernel/Socket/src/Udp.cpp.
guest_sce_net connects the connected client again and expects EISCONN
(0x80410138); before this change it received EIO.
A CMASK holds 4 KiB per 1024x512-pixel metablock, not one nibble per 8x8
tile of the target: 1920x1080 spans 0x6000 bytes, as titles clear it,
not 16200. The swizzled nibbles of the lower-right tiles lie past the
packed size, so the fast-clear check missed them and the expanded store
left them cleared.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A non-blocking sceNetConnect that cannot complete at once must fail with
EINPROGRESS (36, 0x80410124), as FreeBSD's connect does, and a repeated call
while it is pending with EALREADY (37). On Windows, Winsock reports the
first case as WSAEWOULDBLOCK, which was translated to EAGAIN (0x80410123); on
Linux, EINPROGRESS and EALREADY had no translation and became EIO
(0x80410105). Code that waits for the connection only when connect reports
EINPROGRESS treated both as a failed connection.
guest_sce_net connects a non-blocking socket to the loopback listener and
accepts 0 or EINPROGRESS; before this change it received EAGAIN on Windows.
sceKernelGetModuleInfoForUnwind and sceKernelGetModuleInfoFromAddr each
parsed .ehmeta and the eh_frame_hdr it names. Both now read them through
Module/EhFrame.hpp, so a bad table fails the same way in both: an
eh_frame_hdr version other than 1, an indirect or non-absptr/pcrel
encoding, a 64-bit record length or anything outside the image throws.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01JkiyF6p7oDAaTtVe8ci5zP