FreeBSD 11 fopen opens the path with _open, and vn_open_vnode refuses a
directory only for FWRITE or O_TRUNC, so fopen of a directory in a read
mode succeeds; Linux hosts already open it. On Windows CreateFileW
without FILE_FLAG_BACKUP_SEMANTICS refused it with EACCES.
fopen now opens such a path as a libkernel directory descriptor, which
libkernel registers in libc when it loads, and fclose and freopen remove
it from libkernel's table. Reads on the stream fail with EISDIR and set
the error indicator, as on a Linux host and FreeBSD's tmpfs: the Windows
CRT fails them already but reports EINVAL. Writes fail with EBADF, and
fseek, ftell and ungetc work, as on any read-only stream.
After the argument checks, shadPS4 looks the request up and returns
REQUEST_NOT_FOUND for one that was never created or was deleted. The
library already tracks live requests for sceNpSetTimeout.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Implement sceNpWebApi2AddWebTraceTag with the (int64_t request_id, const char* value) signature from shadPS4. Validates that value is not null, accepts any request id, and acts as a silent stub matching the other offline request functions.
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]>