Resolved GuestPsml.cpp by dropping the extern block; the Mfsr2 placeholders in the libScePsml_debug header now carry the implemented signatures and the test uses the library header.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
DecodeColorBuffer dropped the DCC address of a color target with more than
one mip, so the target's resident image had no keys: it was uploaded from
guest memory under the game's fast-clear keys, and no draw into it marked
them uncompressed. The game's textures over the same chain name the keys,
so they kept sampling the clear (0000 reads as (0,0,0,0)) whatever was
drawn. MXGP 26, Borderlands 4 and Forspoken render such targets.
- ColorTarget.chainDccAddress keeps the keys of a 2D single-layer chain;
dccAddress stays 0, so the per-draw single-mip key handling is unchanged.
- SurfaceForTarget gives the resident surface those keys, and the image
then treats them as a multi-mip storage image does: a uniform clear is
cleared on the GPU at upload, and the first write marks every key
uncompressed.
- A draw recipe's key check uses the surface's keys.
- sizeof(State) is 840: the recipe codec and CanonicalPipelineState do not
copy the field.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Declare the NetCtlNatInfo structure layout (size, stun_status,
nat_type, mapped_addr) and implement sceNetCtlGetNatInfo.
When the host has an IPv4 interface, reports STUN status OK (2),
NAT type 2 (moderate), and the host's IPv4 address as the mapped
address. Returns SCE_NET_CTL_ERROR_NOT_CONNECTED when no interface
is found. Unblocks session creation in Aliens: Fireteam Elite (PPSA03393).
Resolved Export.cpp and GuestVrTracker2.cpp keeping main's header layout; the new sceHmd2Internal exports are declared in the libSceHmd2 header and the test uses the library headers.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Resolve a FreeBSD/ELF tls_index {module, offset} the way the relinker's
DTPMOD64 values are laid out: on Windows through the PE _tls_index the
module word points at and the thread's ThreadLocalStoragePointer, on
Linux through glibc's __tls_get_addr.
A string created from a text source in the default horizontal form (0x10)
reported 0x10. TEKKEN: DARK RESURRECTION (PPSA31371) passes the reported form
to sceFontCreateWritingLine, which only accepts 0x11 and 0x12, so the call
failed and the layout width was 0.
On firmware 13.42 sceFontCreateString decides the direction for a default-form
source and sceFontStringGetWritingForm returns the stored form. The string
gets 0x12 when its first strong character is left to right, 0x11 when it is
right to left, and 0x12 when it has none. Left-to-right and right-to-left marks
count as strong, embeddings and overrides do not, and text between an isolate
initiator and its PDI is skipped. Explicit 0x11 and 0x12 sources keep their
form.
The test follows the table reported on the pull request. Which characters are
strong is decided by Unicode block ranges here, not by the full bidi class
tables.
A traced run that ends without a crash or an abort never reports which
imports it called. With APS5_TRACE_CALLS_FILE set, the first traced import
starts a thread that rewrites that file every 10 seconds with every import
called so far, most called first.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
scePthreadMutexTimedlock on a mutex the caller holds, and
scePthreadRwlockTimedrdlock and scePthreadRwlockTimedwrlock on a rwlock
it holds for writing, returned EDEADLK at once. The console returns
ETIMEDOUT, as the prosper console oracle measured. They now sleep until
the timeout and return ETIMEDOUT, as FreeBSD libthr does. The POSIX
timed locks call these and change with them.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceLncUtilLoadExec takes the same path and null-terminated argument
list, which the SystemService call passes on to it on the console. It
returns sceSystemServiceLoadExec's result: the same parameter errors,
the same refusals for paths it cannot start, and "exit" ends the title
in the same way.
sceLncUtilIsAppSuspended, sceSystemServiceIsAppSuspended and
sceLncUtilIsSpeculativeLaunch write false for the running title's app
ID. The title that calls them is running and has no shell to suspend
it. It was started from the host rather than by sceLncUtilLaunchApp,
so no LncLaunchParam asked for a speculative launch. Another app ID
and a null output still throw.
sceLncUtilGetAppLaunchedUser, sceSystemServiceGetAppLaunchedUser and
sceShellCoreUtilGetUserFocus write the initial user for the running
title's app ID. That is the user sceUserServiceGetInitialUser and
sceUserServiceGetForegroundUser report. Another app ID and a null user
pointer still throw.
sceLncUtilGetAppId and sceLncUtilIsAppLaunched accept the running
title's ID as sceSystemServiceGetAppId does, and
sceLncUtilGetAppIdOfRunningBigApp returns what
sceSystemServiceGetAppIdOfRunningBigApp returns. Both big-app lists
write the running title's app ID as their only entry, because AnyPS5
runs one title. Another title ID, a null pointer and a list capacity of
0 still throw.
sceKernelWaitCommandBufferCompletion waits for an AMM submission as
libSceAmpr's sceAmprAmmWaitCommandBufferCompletion does: 0 once the
submission has run, SCE_KERNEL_ERROR_ESRCH for an id that was never
submitted. The signature follows ampr_emu's libkernel hook targets,
where the libSceAmpr wait forwards to it.
guest_kernel_sys submits a map written by sceKernelWriteMapCommand,
waits for it and uses the mapped page, and checks ids 0 and past the
last submission.
The twelve AMM kernel writers record into a caller buffer the command
their libSceAmpr command buffer sibling appends, built with the shared
encoder: sceKernelWriteMapCommand, sceKernelWriteMapWithGpuMaskIdCommand,
sceKernelWriteMapDirectCommand, sceKernelWriteMapDirectWithGpuMaskIdCommand,
sceKernelWriteUnmapCommand, sceKernelWriteRemapCommand,
sceKernelWriteRemapWithGpuMaskIdCommand, sceKernelWriteMultiMapCommand,
sceKernelWriteMultiMapWithGpuMaskIdCommand,
sceKernelWriteModifyProtectCommand,
sceKernelWriteModifyProtectWithGpuMaskIdCommand and
sceKernelWriteModifyMtypeProtectWithGpuMaskIdCommand.
The signatures follow ampr_emu's libkernel hook targets: the sibling's
arguments as 64-bit values between the destination and the size output.
A null destination only reports the size and a null size output only
writes, as for sceKernelWriteModifyMtypeProtectCommand. Invalid ranges,
offsets and protections return the sibling's SCE_KERNEL_ERROR_EINVAL and
write nothing; protection or mask bits above 32 are rejected too.
guest_kernel_sys compares each writer with its sibling on valid and
invalid arguments, in both modes.
The graphics pipeline store kept a fixed 1024 entries and the pipeline journal replayed at most
1024 records, and a replayed pipeline that found the store full was dropped. A title whose
working set is larger rebuilt the rest at the draw on every run, and evicted pipelines it kept
using were rebuilt again and again.
The bound now starts at 1024 and doubles up to 4096: a journal replay that does not fit grows it
instead of dropping the pipeline, and so does eviction churn (a ghost list of evicted keys, checked
every bound/32 evictions: more than half of them came back). It never shrinks during a run;
APS5_PIPELINE_STORE_ENTRIES still fixes it. The journal loads its last 4096 records by default
(APS5_PIPELINE_JOURNAL_ENTRIES). Resident pipelines are bounded by count, not bytes.
agc_driver_recorder_tests --benchmark-pipeline-store-memory [count] (opt-in, not registered)
builds count graphics pipelines with one fragment module each through CachedPipeline and prints
process private bytes and VK_EXT_memory_budget heap usage before and after: with the triangle
shaders about 59 KiB host and no device memory per pipeline on an RTX 4090, 100 KiB host and
8 KiB device-local on a UHD 770.
Tests: agc_pipeline_store_growth (fails on main), agc_pipeline_store_fixed_bound,
agc_pipeline_store_replay_growth (replays on one thread: the mock Vulkan is not thread-safe).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_017SNUYRd7sRKZrMYpquAsnU