Titles report a progressive trophy's progress with _UpdateTrophyProgress
events. Their udsNN.ucp rules feed $._trophy_progress into an int32
statistic with the max aggregation, filtered on $._trophy_id, and the
trophy's unlockCondition names that statistic. Those statistics and
rules were skipped and the events were dropped, so such trophies never
reported progress or unlocked (21 of Borderlands 4's 64).
- Read max statistics (largest value posted, from initialValue) and
int32 statistics (0 to 2147483647).
- Read a rule condition with one == property equal to an unsigned
integer, and apply the rule only to events whose property matches.
- Post _UpdateTrophyProgress through the statistic rules.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
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]>
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
- Track up to 4 pad slots in libScePad with per-slot inputs, outputs, sensor fusion, and deadbands
- Support dynamic user login/logout events and multi-user registration in libSceUserService
- Map SDL controllers 0-3 to Players 1-4 in libSceVideoOut while preserving Player 1 keyboard and mouse composition
- Add test coverage for multi-controller pads and multi-user services
XSAVEOPT raises an illegal instruction under Rosetta on an M5 running
macOS 27.0.1, as XSAVEC does, while XSAVE and XRSTOR save and restore
x87, SSE and AVX state in the standard format. The PS5's Zen 2 has
XSAVEOPT, so code built for it can use the instruction without a CPUID
check.
XSAVEOPT differs from XSAVE only in the init and modified optimizations:
it may skip writing state that is in its initial configuration or
unchanged since the last XRSTOR from the same area. XRSTOR restores the
same state from the area XSAVE writes, so --to-rosetta rewrites
XSAVEOPT (NP 0F AE /6, memory operand) to XSAVE (/4) in place, keeping
the prefixes and the operand, as RDSEED becomes RDRAND. CLWB (66 0F AE
/6), MFENCE, UMONITOR, UMWAIT and the Intel target are left alone.
XSAVEC is not converted: it writes the compacted format.
The converter tests check the rewrite for the plain, REX.W,
RSP-relative, extended-base, RIP-relative and FS-relative forms, check
that the neighbouring 0F AE encodings are not taken, and execute the
rewritten XSAVEOPT64 followed by XRSTOR on YMM3 in the x86-64 build.
The --to-rosetta integration test now covers XSAVEOPT as well.
The relinker stopped printing a 'Guest module:' line for each converted
module in 56c2a5318; it reports 'Converted modules: N' and lists the
.guest.prx files under app0/ in its runtime layout tree. GAME_TESTING.md
and USAGE.md still told readers to use the files printed as 'Guest module:'.
Forward new-image recovery permission through AllocateImageMemory while preserving host-memory fallback and allocated-type reporting. Reuse held cache locks only at safe construction points, retain caller-held sampled textures and pending storage results, and try resource-cache removal without waiting.
Count released Vulkan allocations and saturate the reclaim reserve. Cover sampled/storage allocation failures, host fallback after image recovery, bounded attempts and overflow. Remove stale conflict markers and unrelated debt, and refresh the recorded validation.
The debt entry no longer says that a leaf with an rsp operand that
cannot move in place is skipped. A new entry says that such an operand
moves to a stub, when the leaf is still skipped, and that a game patch
over a framed site or a moved displacement is refused. The USAGE row
says the same in short.
The second half of a pipelined draw (stage materialization, cache insert,
enqueue) runs on a finisher thread, overlapping the next draw's packet
work; draws whose stages could write memory are held back. Commits skip
work whose inputs did not change since the last commit, color metadata
passes are ordered through the pipeline, resource and storage-image proofs
are reused within one collect epoch until a write breaks them, and a shape
entry is refreshed in place at the second sight of the same read user words.
APS5_VERIFY_DRAW_PIPELINE checks reused proofs against a full check.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
On Windows, dlopen passed a module that was never relinked to LoadLibraryExW, which raised the
modal Bad Image hard-error dialog and blocked the calling thread until someone answered it. The
load now runs with SEM_FAILCRITICALERRORS set for that thread only, so it fails at once with the
same result as before. Every failed load is reported once per file on stderr with a [module]
prefix; a file that exists with no relinked .guest.prx names the relinker's --module-dir option.
On Linux sceKernelGetdirentries copied the host d_type, so a directory under app0 that is a host symlink was listed as a link, and a title that only descends into directory entries skipped it. Inside the app0 tree, report a symlink (or an entry of unknown type) as the type of its target; links elsewhere, and dangling links, stay links.
Some titles wait for a chord on their title screen: RollerCoaster Tycoon
Adventures Deluxe (PPSA17330) asks for L1 + R1. The command file already
carries a button bit field, but the helper accepted one name. Names joined
by '+' are now combined into one command; unknown names, duplicates and
release in a chord are rejected without touching the command file.
Co-Authored-By: Claude Opus 5.5 <[email protected]>