Move the AVCC collision to the second unit, add an AVCC unit opening
00 00 01 23 among Annex-B units, and an Annex-B stream with 3-byte start
codes whose SPS and PPS unit, padded with trailing zero bytes, also reads
as one length prefix.
A unit opening with 00 00 01 xx can also tile as AVCC when its first NAL
is 0x1xx bytes long, in either direction. Annex-B requires a zero_byte
before the first NAL of an access unit, so a unit opening with a 3-byte
start code is taken as AVCC unless the decoder has already seen
unambiguous Annex-B units that open that way. A unit opening with
00 00 00 01 that also tiles keeps the framing of the last unambiguous unit,
Annex-B when there is none.
Media Player Classic PS5 sends Annex-B units with 4-byte start codes and
leaves exactly the colliding samples in AVCC, so the decoder's last framing
alone would choose wrong there.
With DB_SHADER_CONTROL.STENCIL_OP_VAL_EXPORT_ENABLE the pixel shader
supplies the value that REPLACE_OP and the add and subtract operations
use in place of DB_STENCILREFMASK.STENCILOPVAL. The bit was refused as a
whole, which stopped Onimusha: Way of the Sword (PPSA27836) at a
DB_SHADER_CONTROL 0x45 draw with DB_STENCIL_CONTROL 0x40040 (REPLACE_OP
on depth pass, both faces), write mask 0xff and compare ALWAYS.
The export is accepted with the 32_GR and 32_ABGR Z formats. When no
reachable operation through a non-zero write mask reads the value, it
cannot change the result and is ignored. Without a test value export, a
reachable REPLACE_OP becomes REPLACE with the exported value as
FragStencilRefEXT (or the bounded replay on devices without the
extension), provided both faces compare without the test value and use
no ONES or REPLACE_TEST; early tests throw. The add and subtract
operations, and REPLACE_OP with a test value export, still throw.
The value is read from bits 8-15 of the second MRTZ channel: the
title's pixel shader shifts it left by 8 right before exp mrtz
(v_lshlrev_b32 v0, 8, v0). That is the only evidence for the layout and
it is listed as technical debt. The pixel stage info carries the new
flag into the cache key, the draw keys and request serialization
version 31.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceKernelFstat and fstat passed any descriptor to the UCRT's _fstat64, which
raises the invalid-parameter handler for one that is not open. The crash
report installs that handler as fatal, so the calling thread died where the
console returns EBADF. Dying Light 2 (PPSA02262) hits it on a loading thread
right after sign-in.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
guest_datagram_* failed with "bind loopback sockets" on hosts where the
kernel has IPv6 but ::1 is unusable (net.ipv6.conf.lo.disable_ipv6=1):
socket creation succeeds and bind fails with EADDRNOTAVAIL. Skip the
IPv6 case on EAFNOSUPPORT from socket or EADDRNOTAVAIL from bind, as
GuestUdp.cpp and GuestSocketPortZero.cpp already do.
sceUserServiceInitialize reads the thread priority from the first int
of its parameters, and sceUserServiceInitialize2 takes it as its
argument. A PS5 returns 0x80960005 for a priority outside 0x100 to
0x2FF, and 0x80960003 when Initialize2 is called on an initialized
service, where this returned success.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Following the PS5 3.20 module as read by prosper:
- a second sceGameUpdateInitialize returns 0x80412802, and
sceGameUpdateTerminate without initialization returns 0x80412801;
- sceGameUpdateCreateRequest returns 0x80412801 before initialization;
- sceGameUpdateCheck checks the id, the pointers, the 0x30 sizes and
the zero option and reserved words before initialization;
- sceGameUpdateAbortRequest and sceGameUpdateDeleteRequest return
0x80412805 for an id that was never created instead of success;
- sceGameUpdateGetAddcontLatestVersion checks its pointers before
initialization.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The PS5 module checks max_image_width - 1 > 999999 in
scePngDecQueryMemorySize and scePngDecCreate and returns
0x80690003 (INVALID_PARAM). This returned 0x80690002 (INVALID_SIZE)
and accepted a width of 1000001.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Add the concurrent flush case from #7757 to agc_driver_storage_file_write:
while one thread's FlushPending stores the surface under a held GPU
mutex, a second thread calls FlushPending and then GuestMemory::Read on
the same range, and the read must see the stored bytes. Only the test
from #7757 is taken here; agc_driver_storage_read_during_idle_store
keeps covering the flush hook path.
Co-authored-by: MarcZX10 <[email protected]>
The conversions in RuntimeSupport.cpp call the host's strtoimax,
strtoumax and strtoull directly, so they set EINVAL on macOS for a
subject without digits too. guest_math, once the strtol cases pass,
failed on strtoimax(""). They now go through ParseInteger.
macOS's strtoll and strtoull set errno to EINVAL when the subject has
no digits, as in "", "words" or " +". The guest's integer conversions
pass that to the title, while guest_atoi, guest_wide_conversion and
guest_math expect errno unchanged, as glibc leaves it. So atoi("")
returned 0 with errno 22 on macOS, and all three tests failed there.
A ParseInteger helper in SonyCrt.hpp calls the host's conversion and,
on macOS, restores the caller's errno when nothing was converted and
the base is valid. An overflow still sets ERANGE, and an invalid base
still sets EINVAL. strtol, strtoul, strtoll, strtoull, atoi, atol,
atoll, _Stoull and the wcsto* integer conversions in Strings.cpp use
it. On other hosts the helper calls the conversion unchanged.