Without playgo-chunkdefs.xml every chunk id was accepted, so a title
that probes chunk ids until SCE_PLAYGO_ERROR_BAD_CHUNK_ID never stops.
RIDE 4 (PPSA01599, Unreal Engine 4) grows its chunk list until it runs
out of memory. The package's chunk table header holds the chunk count
at offset 0x0A; ids below it are valid. Every id is still accepted only
when neither file exists.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
FreeBSD fchdir(2) changes the working directory to the directory referenced by a descriptor. The guest imports fchdir from libkernel_sys (PPSA99764, issue #1578) and the module did not export it.
The descriptor's directory is resolved from the path recorded when the directory was opened on Windows, and from the /proc/self/fd link target on Linux. The guest working directory is then set through the libc routine shared with chdir. A descriptor that is not open returns EBADF and one that is not a directory returns ENOTDIR.
AI-assisted: yes
(cherry picked from commit 76329cbb08781e13d757c3ff955acf71f8bd506f)
`truncate` (`ayrtszI7GBg`) is an absent import of PS5MC (PPSA99420),
XPSemu (PPSA97358) and Porpoise (PPSA99764) on `main`. It resolves
through `sceKernelTruncate`, which now returns `EISDIR` for a directory
and the host errno for other failures instead of `EIO`, as FreeBSD 11
`kern_truncate` does. The guest-relative test `guest_truncate` covers
shrinking, growing with zero fill, a negative length, a missing path,
an empty path, a null path, a directory and a read-only file.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
hypot(inf, NaN) returned a NaN on main. C Annex F returns +inf when
either operand is infinite, even if the other is a NaN, and FreeBSD
msun (lib/msun/src/e_hypot.c) does so for a signalling NaN too. The
infinite case is now checked before std::hypot; other inputs do not
change.
Co-Authored-By: Claude Haiku 5.5 <[email protected]>
C17 7.21.6.2p16 returns EOF only if input fails before the first conversion completes, and a suppressed conversion completes. FreeBSD counts it in nconversions (vfscanf.c, releng/11.4, lines 799-805). The host scanf returned EOF there, so sscanf("12", "%*d%d", &v) reported EOF instead of 0. Each suppressed conversion now records its end with a %n and a result of EOF becomes 0 when one was recorded.
QueueState held the 48 KiB constant RAM inline, so every QueueState
cleared 48 KiB when constructed and copied it when copied.
ResolveShaderAbi and ResolveGraphicsStagesAbi construct one on each call
(sceAgcLinkShaders, sceAgcCreatePrimState, interpolant mapping),
resolveGroupAhead copies the live state, and a queue reset builds a new
one, although few command buffers write the constant RAM.
The constant RAM is now a vector allocated when WRITE_CONST_RAM first
writes it. ConstantRam returns a shared all-zero view until then, so
DUMP_CONST_RAM of unwritten words still stores zeros, and the bounds use
QueueState::ConstantRamWords. The store view ResolveStore returns is
copied by the recorder within the packet, as before.
testMemory dumps unwritten constant RAM and checks for zeros, and checks
that a copied queue state keeps the words written before the copy.
A QueueState is 336 bytes instead of 49464; constructing one takes 0.3
to 0.8 us instead of 1.5 to 2.1 us, and copying one 0.4 to 0.6 us
instead of 1.9 to 3.8 us (GCC 13 -O3). On the title screen of PPSA21402
(Balatro) the clears from the two resolvers took 30 to 129 of 3459 to
7838 CPU samples per 10 s.
PSXS5, SwanStationPS5 and Nuvio stop at start-up on setcontext on main,
and EVO Player and ProsperoStore do on Windows. The three are imported
by the statically linked OpenSSL's ASYNC code.
The three use FreeBSD 11's amd64 ucontext_t (mcontext at 0x10, mc_len
800, uc_link at 0x330, 0x370 bytes), which the titles are built
against: EVO Player's ASYNC_is_capable captures into a 0x370-byte stack
buffer, and async_fibre_makecontext sets uc_link at 0x330 and uc_stack
at 0x338. getcontext saves every register at its call in assembly and
stores the context as FreeBSD's sys_getcontext does: rax and rdx as 0,
the carry flag clear, the FXSAVE image and the signal mask, and nothing
from uc_link on. setcontext checks mc_len and mc_flags as set_mcontext
does, installs the signal mask, masks MXCSR with the host's MXCSR_MASK
and returns through iretq, so every general register and the flags are
restored and nothing is written below the target stack pointer.
makecontext follows FreeBSD 11's amd64 libc.
Windows checks guard-page growth and exception unwinding against the
stack bounds in the TEB. setcontext and longjmp now set them to the
stack they switch to, which makecontext registers and pins writable as
libSceFiber does for fiber stacks. OpenSSL enters a context with
setcontext and then switches with _setjmp and _longjmp.
Iterating a Registers advances with nextPresent, which recomputes the
word, mask and next bit from the index on every step, about 3.5 ns per
register. BuildRegisteredAbiKey walks all of a state's registers, about
300 with the context, and ResolveGraphicsStagesAbi walks each stage's
registered state to merge it, on every sceAgcLinkShaders,
sceAgcCreatePrimState and interpolant mapping call.
Registers::ForEach visits the set registers in ascending order straight
from the presence words, and both paths use it. The key and the merged
state are unchanged.
testRegisterFile checks that ForEach visits what iteration visits, in
order, and skips an erased register.
Building the key for 297 registers takes 200 ns instead of 1030 ns (GCC
13 -O3). On the title screen of PPSA21402 (Balatro) the two functions
took 0.18 to 0.29 CPU samples per sample of the title's own code, and
0.06 to 0.12 with this change.
sleep_for can return up to a scheduler tick early against the
performance counter the guest clock reads, so the first reading could be
just under 50 ms on a loaded machine.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Titles that import it now load; calling it throws until push event
handles have operations that can be aborted.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
(cherry picked from commit f50cb08c988736d645f0cc1c329f911f732fa935)
(cherry picked from commit ae3227dbfa2c972b36242056df5971d858ac65c3)
(cherry picked from commit 3df66a6a5dd9f0cd73daaee1342c22742c1915e4)
A T# picked per lane with SelectU32 and made uniform with
v_readfirstlane, as in a waterfall loop, left a descriptor web without
Phis that the web walk could not split. CollectDescriptorPhis now steps
through ReadFirstLane, and a Phi-free tuple containing SelectU32 or
ReadFirstLane is split on the shared condition (SelectU32) or wrapped in
a matching ReadFirstLane. The new nodes are placed after the last
original node of the tuple in its block and inserted only when the web
is split; otherwise they are invalidated like the web's Phis.
PPSA26344 compute shader 0x800037f200 selects its T# per lane between
SRT reads or zero and reads the first lane of the result.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
s_buffer_load returns zero for dwords outside the V#'s range. The SRT
evaluator refused such a read instead, so evaluating a descriptor failed
as soon as one arm of a split T# read through a null or short V#, even
when that arm is never taken. The evaluator now returns zero for those
reads, as the hardware does.
PPSA26344 compute shader 0x800037f200 reads one arm's T# through a null
V# and stopped at "SrtWalker::EvaluateRuntimeSources failed to evaluate
runtime sources".
Co-Authored-By: Claude Opus 5.5 <[email protected]>