fputws and wprintf write a UTF-16 surrogate pair as one four-byte
UTF-8 sequence, but fgetwc decoded that sequence into a single code
point above 0xFFFF, which is not a 16-bit guest wchar_t value, and
fgetws stored it truncated: fputws(u"A\U0001F600\n") read back as
A, U+F600, newline.
fgetwc now returns the high surrogate and keeps the low one in the
stream for the next read, so fgetws stores the pair, also when the
buffer fills between the two halves. A successful seek discards it,
as FreeBSD's fseeko resets the stream's mbstate. Sequences that
decode to an overlong form or above U+10FFFF, and lead bytes F8 to
FF, fail with EILSEQ instead of returning made-up characters; the
three-byte surrogates that fputwc writes for a single unit are still
read back as that unit.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QegaHM5QeCynUQ2ZLWHE4b
A buffer V# whose TYPE is not 0 threw "buffer descriptor uses an
unsupported type" for every access. Measured on a PS5 (CFI-1115B,
firmware 12.20): through a V# with TYPE 2 or 3 and FORMAT 0 or a valid
format, buffer_store_dword and buffer_store_format_x write nothing and
don't fault, so a buffer a shader only stores to through one is bound as
a null V#. Loads and atomics through those V#s leave the destination VGPR
unchanged, which a null V# can't reproduce, so they still throw. Through
a TYPE 0, FORMAT 0 V#, vector loads return 0 and stores are dropped, and
those buffers are bound as a null V# too. TYPE 1 faults the GPU for every
access measured and keeps throwing.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A comma-separated list of hex program addresses (optional 0x prefix) now
writes only those programs' requests, so one expensive shader can be
captured without serializing every request a title prepares. Any other
value, such as 1, keeps writing every request. A filtered-out program
returns no name, so diagnostics never point at a file that was not
written, and it stays eligible for a later list.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A title with param.sfo gets bit 23 (0x00800000) of its ATTRIBUTE key,
the PS4 Pro (Neo) mode support flag, and 0 without the key, as shadPS4
answers on a Neo console; sceKernelHasNeoMode and sceKernelIsAuthenticNeo
already report one. A title with param.json still throws: what a PS5
application gets is unknown. The param.sfo parser now reads ATTRIBUTE and
libkernel exposes it to the other libraries.
sceNetGetStatisticsInfo threw NotImplemented_nid_no_patch. It now fills
the six 32-bit fields of the statistics block (kernel memory free and
minimum free, packet count, QoS packet count, library memory free and
minimum free) and fails with NET_EFAULT, setting errno, for a null
pointer. The layout and the "plenty free, nothing queued" answer follow
shadPS4's net.cpp and net_types.h; the host has no counter for the
console's network memory, so the values are not measured. The debt file
records this, and the test checks the null pointer, the field
invariants and that the flags argument is ignored.
sceNetShowIfconfigWithMemory, sceNetShowPolicyWithMemory and
sceNetShowRoute6WithMemory threw NotImplemented_nid_no_patch. They now
behave like the existing sceNetShowRouteWithMemory: an unknown memory
pool id fails with NET_EBADF (errno set), a live pool returns success
without printing. The behaviour follows shadPS4's net.cpp, which does
the same for these three. The new silent stubs are listed in the
libSceNet technical debt file, and the tests cover the invalid id, live
pool and destroyed pool cases.
#9838 read sceAudioOut2SetSystemDebugState in PS5 firmware 3.20 and 4.03:
it returns 0x80268006 (not initialized) before sceAudioOut2Initialize,
ahead of its pointer, id and size checks. The debt entry for
sceAudioOut2EnableChat and sceAudioOut2DisableChat records the same
0x80268006 before AudioOut2 initialization. Both were left out while
AudioOut2 initialization was not tracked; AudioOut2IsInitialized_nid_no_patch
now tracks it, so all three return 0x80268006 first and change no state.
The two debt entries drop the closed gap.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
FreeBSD re-evaluates a kqueue's EVFILT_READ note from kqueue_wakeup,
which runs whenever the watched kqueue queues a note, so an EV_CLEAR
note fires again only after such an activation. The equeue now counts
activations, and the EV_CLEAR note fires when the count moves while
notes are queued.
PS4 color and depth targets, PS4 graphics EOP events, and the PS4 tile
modes (1D/2D thin and display, depth with tile split, PRT, linear
general) on the AGC executor, with a GPU detiler for every mode.
Textures sampled over the padded corner of a render target are GPU block
copies, and the PS4 SDK pattern-fill compute kernel runs as a GPU fill
when it repeats one dword, so render targets and HTILE are cleared
without a CPU drain. Two-dword patterns keep running the kernel: as
fills, Limbo's clears of its 64-bit target made its gameplay advance
about half as far per frame.
Tests cover the tiling equations against addrlib formulas, the GPU
detiler for every mode and element size, and the fill ranges.
The PS5 3.20 export lists have ksem_* in libkernel as well as
libkernel_sys, and on Windows a libkernel import never reaches
libkernel_sys, so titles importing them from libkernel did not find
them. Following pipe1os's review on #9284, also: ENOSPC from
ksem_init when no descriptor is left, the SEM_MAX limit of 30 with
ENOSPC, and dup/dup2 from a ksem id throwing as for a kqueue.
Horizontal writing steps advanced the pen by the glyph's vertical advance on
every character, so text drifted down diagonally (steepest for CJK fonts,
whose vertical advance is roughly the em size). The step's GlyphMetrics
width/height were also overwritten with the pen position, leaving the first
glyph of each run invisible at pen (0, 0).
Every supported writing form (0x10/0x11/0x12) is horizontal, so the pen must
advance only along X and the step reports the real glyph width/height.