On a device that cannot sample two-sample depth, as lavapipe, the DB
depth copy case now also creates a two-sample surface and expects the
copy's sampling refusal, so that refusal is covered where it applies.
Devices that sample two-sample depth skip it.
Co-authored-by: simonbbby <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceAjmDecWVorbisCreateHeaderPacket checks its 0x48-byte parameter as the
PS5 module does and writes a five-entry length table, a Vorbis
identification header from the parameters, an empty comment header and
the setup packet.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RbLgECLQ2bpDM7oe2urGZK
main never called it, so the _Vacopy checks were dropped from the
Release build and never ran.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
ImportWatched kept a copy of every non-zero page of the range being imported, so that a page the
write watch reported during the import could be told from one that still held its bytes. The copy
had the range's footprint: a first import of a 0.5-3 GiB guest heap held that much host memory
while it ran.
The window now keeps a 64-bit digest per 4 KiB page (four xxHash64 lanes) and compares digests:
8 bytes per page, 1/512 of the range. Same decision for every page, same reads of guest memory.
CheckImportWindowFootprint imports a 64 MiB watched range and requires the heap held during the
import to stay under 1 MiB. It failed with "held 64 MiB" before this change.
The idle flush (VulkanDevice::StoreIdleResults) publishes the unit shadows over guest memory into
the host import and only submits the copies. publishUnits picks the units to store on the CPU,
and the slab -> import copy lands when the GPU runs it, so a guest store made between the two is
overwritten with the older shadow bytes. The memory-access hook waits through SyncThrough right
after its flush; the idle flush has no reader that waits.
FlushPending and PublishShadowsOnly now sync the recorder under the GPU mutex after an idle
publish that stored units. Other flush reasons are unchanged.
Test: agc_idle_publish_wait (a CPU store made after the idle flush returns survives; a label
flush's publish stays recorded).
The PS5 module's sceAudioOut2LoTerminate stops the low-latency service
and returns 0 whether or not it runs; sceAudioOut2LoInit starts no
service here. sceAudioOut2InitializeEx stores its argument and runs
sceAudioOut2Initialize.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RbLgECLQ2bpDM7oe2urGZK
The declarations now live in libSceSaveData.native/Export.cpp, which both
save data libraries are built from, so their entry belongs in that
library's debt file.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The PS5 module returns 0x80A00002 for a null pointer and otherwise
clears the 0x134C-byte program info before filling it from the system
service. Nothing is broadcast here, so the info stays zero.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RbLgECLQ2bpDM7oe2urGZK
The PS5 module keeps one mastering-initialized flag. A repeated
initialization returns 0 before the flags are checked; otherwise
sceAudioOut2MasteringInit accepts only 0 and sceAudioOut2MasteringInitEx
also bit 31, and other flags return 0x80268201. Term, GetState and
SetParam return 0x80268203 before initialization, GetState returns
0x8026800C for a null state and SetParam 0x80268205 for flags above 1.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RbLgECLQ2bpDM7oe2urGZK
DepthPlanePartialStore draws depth 0.5 into a 384x200 D32 Z_X plane (3x2
64 KiB tiles, the last row 72 texels high) over memory filled with 1.0 and
checks the plane's memory unit by unit:
- a read ending 3 KiB into the plane stores unit 0 alone (one store, one
unit, 64 KiB counted) and leaves the plane stale; the same read again
stores nothing;
- a read of the whole plane stores the other five units, the edge tiles
holding 128x72 depth values with their padding left as it was;
- a guest write into unit 4 after unit 0 was stored wins in unit 4 only:
a later whole read stores the four other stale units over 1.0, and a
LESS draw at 0.6 passes exactly over unit 4 (the plane-wide generation
synced every unit from memory instead);
- the retire of a surface the guest wrote into, through a view with two
levels, stores its stale units the guest did not write;
- a color target over unit 5 retires the surface after storing units 1-4;
- over unwatched memory a partial store leaves the other units on the GPU,
so a LESS draw at 0.6 passes nowhere.
TextureTiling checks that the 64KB Z_X equation of 4-byte elements reads
only x and y bits below 7, so each 64 KiB unit of a 3840x2160 D32 plane is
exactly one 128x128 tile.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A read of memory inside a stale D32 Z_X depth plane (FlushDepthPlanes) stored
the whole plane: a copy of the depth image into the mirror, MarkWholeWritten
and a write-back of every byte. In Super Meat Boy 3D (#8840) a read-only
buffer ending about 3 KiB inside a stale 3840x2160 plane makes
ShaderResources::Revalidate flush ~1000 times per 5 s, each one moving
31.9 MiB, bound by transfer bandwidth.
A depth surface now tracks its plane as 64 KiB units, each one 128x128 tile
of the mirror's block units: a stale bit and a write generation per unit
replace memoryStale and the plane-wide syncedGeneration.
- FlushDepthPlanes stores only the stale units the range overlaps: the depth
to mirror copy takes one region per unit rectangle (UnitRects, from the
mirror's slice windows), the mirror marks just those units written
(MarkUnitsWritten) and the write-back covers their hull. The other units
stay stale and the plane stays registered. Stale bits are cleared only
after the copy was recorded, and the stored units' generations advance
only when FlushPending stored them. A depth fast clear still pending at
the store rewrites the whole image, so it makes every unit stale first.
- SyncFromMemory copies from the mirror only the units the guest wrote since
their own generation (one ChangedBlocks scan; untracked memory counts as
unwritten, as WrittenSince did), so a guest write into one unit no longer
replaces GPU depth that is still unstored in the others.
- Flushes followed by a retire keep the whole-plane store: the color target
flush in Draw and a written storage view (DepthPlaneScope::Whole). The
retire of an overwritten surface in DepthSurfaceTexture first stores its
remaining stale units the guest did not write.
- A mirror without block units (APS5_NO_BLOCK_TRACKING, unaligned base)
falls back to the whole-plane copy, and APS5_DEPTH_PLANE_WHOLE_STORE=1
tracks the plane as one unit, the previous behaviour.
- DepthPlaneStoreCounts reports stores, units and bytes stored.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The detached thread of the abort-race case reads a flag that is a local
of the enclosing block, which ends before main calls std::abort(). Under
AddressSanitizer that read is reported as stack-use-after-scope. Make the
flag static.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
MD4, MD5, SHA1, SHA224, SHA256, SHA384 and SHA512 Init/Update/Final and
the SHA256 one-shot threw. They now hash as LibreSSL does, on the
caller's MD4_CTX, MD5_CTX, SHA_CTX, SHA256_CTX and SHA512_CTX laid out as
in LibreSSL's md4.h, md5.h and sha.h, so a context copied or inspected
by the title stays valid: the bit count in Nl/Nh, the partial block in
data with its length in num, and md_len selecting the truncated digest.
Final pads and clears the buffer as LibreSSL's sources do.
Cases that differ between LibreSSL versions throw: SHA256 with a null
digest buffer and SHA512_Final with the SHA-512/224 or SHA-512/256
length. The test checks the RFC 1320, RFC 1321 and FIPS 180 vectors over
several chunk sizes, the context fields, copied contexts and those
cases.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
sceFontOpenFontFile resolves guest paths, so a host-absolute temporary
path resolved beneath the run directory on Linux.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The console error_code and error_condition keep the value in the second
dword: the shared error_category::equivalent reads it at +4, the
default_error_condition overrides return it shifted into the high half,
and title code built against the SDK headers stores 0 at +0 and reads
value() at +4. The generic category returned and compared the value at
+0.
system_category returns a static _System_error_category named "system"
that shares the generic message table and maps a value with a message
to the generic category in default_error_condition. The equivalent
overloads are shared by both categories and go through the object's own
default_error_condition, as the console's base implementation does.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RbLgECLQ2bpDM7oe2urGZK
The DB depth copy case drew a two-sample depth surface, which lavapipe
cannot sample (it samples depth at 1 and 4 samples only). The copy then
threw outside the expected-failure checks and the test crashed on exit.
Pick 2 samples when the device samples them, else 4, else skip the
multisample half, and copy every sample of that count.
Co-Authored-By: Claude Opus 5.5 <[email protected]>