main() resolved the base before running --fetch, so an explicit base on a
remote that was never fetched failed with "no base ref found" and never
fetched. The fetch is now a local helper and runs first when --base is
given; the default base still resolves first, then fetches.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The Shader cache section says only that subdirectories of other versions are removed after 14 days. housekeeping() in ShaderDiskCache.cpp removes nothing from the current version, and no size or entry limit applies there.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
changed() diffed the working tree against the tip of the base, so files
changed only on upstream main since the branch point were reported and
compiled. It now diffs against the merge base of the base and HEAD.
A regression test covers a base-only change.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Axis labels and grid lines were drawn only at data points, so a Monday
without a commit lost its label. The label loop now walks every calendar
day between the first and last point. A test covers a series that skips
several Mondays.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
main() rejected --nid values carrying the #lib#mod suffix that load_db and
import_audit already strip and USAGE.md documents. The suffix is now removed
from each --nid value before validation, so lookup and output use the bare NID.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Reapplies #5791 (reverted by #6552). agc_driver_mesh_index_cache now skips
on llvmpipe like agc_driver_mesh does: llvmpipe aborts compiling these mesh
programs (LLVM ERROR: Cannot emit physreg copy), which is what turned main's
linux job red.
Co-Authored-By: Claude <[email protected]>
agc_pending_key_stores cleared only the first 256 bytes of its 64 KiB block and
then asked for the keys of 512 bytes. The other 256 were whatever the heap
held: when they were not all equal the range read as mixed (correctly) and
the check that it is unknown failed, so the test passed or failed with the
allocator's state (main builds after #5784).
Co-Authored-By: Claude <[email protected]>
The default bindings map the left and right mouse buttons to Square and
R2, and mouse mode maps motion to the right stick. A title that opens the
mouse with sceMouseOpen therefore gets every click twice: as a mouse
button and as a pad press. PPSA15388 treats the pad press as a switch to
gamepad input, re-centres its cursor and drops the click, so menu items
cannot be clicked.
While libSceMouse has a handle open, KeyboardMouse ignores mouse motion
and mouse-button presses. Releases still pass, so a button held before
the title opened the mouse is let go. Keys and the wheel are unchanged,
as with the IME guard next to it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A heap mirror is refreshed from the write watch. acquireMirror checked
the watch only when it made a mirror and reused an existing one as it
was. Once part of the range left the watch, the next address-based build
threw "a heap mirror's range is no longer write-watched" from the
refresh, and a build served from the address-space cache threw the same
from its heap runs. A range leaves the watch for good when a host import
that does not keep the watch covers it: on Windows a direct import of
private memory that is not settled (below the 1 MiB settle floor, or any
when imports cannot be settled), elsewhere any import while imports are
compared.
A heap mirror now records the unwatch serial at which its range was last
seen fully watched. Its reuse, and a cache hit over it, compare that
serial with GuestMemory::UnwatchSerial and look at the watch again only
when a range has left it since. A mirror whose range is no longer
watched is not reused, the cache is not taken (before its imports are
stamped), and the pass plans the range again: an import if the budget
allows, else a copy. A refused heap mirror also drops the registry's
stale one, whose buffer would stay allocated otherwise.
sceSysmoduleIsLoaded, sceSysmoduleLoadModule and sceSysmoduleUnloadModule
return success for an id missing from the module table, because titles that
load or unload such an id aborted otherwise (b4db9fdd6, a2520aa07). Nothing
tested or recorded it, and two commented-out throws were left in the code.
Remove the commented-out throws, list the three functions under Silent stubs
in the library's technical debt file, and test that unknown ids succeed
without changing state while the internal variants still throw.
Written with AI assistance (Claude).
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The committer built a recorded draw's resource key through two temporaries a shader, took the in-place and device read lists by value, and in PrepareDrawBindings built two layout-binding vectors only to test them for emptiness, a std::map of pool sizes a set, and copies of the descriptor buffer and write lists, all on every draw. The key is now built in place with its size reserved, the read lists fill a caller's vector, and the per-draw bookkeeping lives in the thread's scratch (ThreadOwned), as the selected-slot list already did. The queue worker's program list and memory snapshots reserve their size up front.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
The grid reference compared the exact path with a composite whose depth
the 3070 had read at the standard 2x locations, so its 3005 depth
mismatches said nothing about the exact path. It now places every
sloped depth sample of each render from the slopes' plane equations: at
the guest's sample location of its pixel and sample, or at the standard
2x location. When even the composite holds depth away from the guest's
locations, the device reads depth drawn at custom sample locations back
elsewhere despite the transitions that name them, no render can be
compared with it bit for bit, and the test skips with the counts.
A scene check that finds a wrong sample index now prints it, and where
the device draws depth at custom sample locations the bench also times
the swaps with the standard locations named at the depth copy's
transitions.
The 3070, whose vulkaninfo reports a maxSampleLocationGridSize of 1x1,
ran the grid reference's native 2x2 render. vulkaninfo prints
VkPhysicalDeviceSampleLocationsPropertiesEXT, the grid every supported
sample count allows; the device setup reads each count's own
VkMultisamplePropertiesEXT (VulkanDevice.cpp), which may be larger at
low counts, and found an even grid at 2 samples there. The setup now
logs each count's largest grid next to the one for every count and
keeps it in the context, and the grid reference prints the one at 2
samples.
The setup's test for a 2x2 grid also took a 0x0 grid, whose sides are
even, for one. HostsSampleLocationGrid requires both sides to be nonzero
and even, and the planning test checks it.
The backward lookup added with the region fix compared the address with a page it could not reach and never ran. The test now queries an ntdll address three pages in, then the first page, then the pages between, and compares each with VirtualQuery. The lookups after the first fail on the cache before the region fix.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
On the 3070 the grid reference read the composite's and the 2x2 grid's
depth at the standard 2x locations: sample 0 of pixel (14,0) held
0x3f00e5b5, the slope's depth at (14.75, 0.75), while the guest's sample
0 lies at (14.75, 0.5), whose depth 0x3f0153f8 the exact path held.
All 3005 samples the slopes cover differed. The depth surface stays in
the general layout for its life (DepthSurface.cpp, and the render
passes in Pipeline.cpp and SampleOrder.cpp), so no layout transition
ever names the sample locations it was drawn with, although the layout
of an image created with SAMPLE_LOCATIONS_COMPATIBLE_DEPTH depends on
them; the 3070 returned such depth at its standard locations when it
was sampled or copied. The exact path's even rows came out right
because its depth pass rewrites them at the stand-in's locations, but
its odd rows came from vkCmdCopyImage, read at the standard locations
and moved to the other sample; the 10 color mismatches, all in odd
rows, are the shade triangle's depth test against those values.
A pass that draws depth at custom sample locations now ends, after its
samples are back in the guest's order, with a transition of the target
to TRANSFER_SRC_OPTIMAL and back to the general layout that names the
locations it drew with, and the depth swap copies its target between
such transitions. The planning test checks both transition pairs, and
that a swap without sample locations still copies in the general layout.
agc_driver_mesh_index_cache aborts on the linux job (lavapipe, LLVM 20.1.2:
"LLVM ERROR: Cannot emit physreg copy instruction") on every main push build
since the merge (first red: 38777177302). The PR was merged on a
windows-only run after a linux-red batch was split.
Co-Authored-By: Claude <[email protected]>
The color swap (SampleOrder.comp) chose a pixel's order word with
order.map[(at.x & 1u) | ((at.y & 1u) << 1u)], a push-constant vector
indexed by a value that differs between the lanes of a wave, returned
early for the pixels the order keeps, and gathered the held samples
through a private array indexed per lane. On the AMD Windows driver
(Radeon 0x1638, wave64) the 2x R8_UNORM round trip found sample 1 of
pixel (0,0) in its sample 0, and the grid reference's exact path read
sample index 1 in sample 0 of the same pixel, although the order keeps
that pixel's samples. Only the invocation of pixel (0,0) stores to it,
so that invocation ran the swap with another class's word.
Each invocation now handles one 2x2 quad and takes every pixel class's
word through a constant index, so the kept classes return uniformly,
and picks the held samples through selects. The depth swap's fragment
shader selects its word the same way. The planning test checks that no
sample order shader indexes a vector or array through a value that
varies between invocations, and a failed swap round trip counts its
wrong samples per pixel class.
The CLZERO case that needs a 32-bit address found no mapping because a
64-bit Mach-O executable reserves 4 GiB as `__PAGEZERO`, not because
Rosetta withholds low memory: the same `mmap` succeeds once the
executable is linked with a smaller zero page. The Apple x86-64 build
links the test that way and the case runs with the other three, so the
skip it had is gone and the Linux mapping failure stays fatal. The arm64
build keeps the 4 GiB zero page, which it requires to start.
VirtualQuery describes the pages from the queried address to the end of the run of equal pages, so the reported seg0 begins at the queried page. The cached entry returned the first lookup's page for every later address in the run. It now returns the queried page and the bytes up to the end of the cached run, which is what VirtualQuery returns.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
sceSaveDataSetSaveDataMemory2 read the whole slot file, patched it and
replaced it through a temporary file on every call, so each call cost a
full rewrite of the slot (up to 32 MiB). The changed ranges now go to a
small journal that is staged through the slot's temporary file and
renamed into place, then written into the slot file in place, and the
journal is removed. A journal left by an interrupted call is replayed by
the next setup, get, set or sync of that slot.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Since ab3e92605 the entry stub gives each missing standard handle
anyps5.log beside the executable, and the crash report writes to the
standard error handle, so it reaches the log too. The entry now records
only what is still lost: the stub's errors about the executable path or
about waiting for the previous LoadExec process, written before the log
is opened, and output to the missing handles when the log cannot be
created.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0154rPujpieMaCnZ6WMobg7M
A geometry program with VGT_GS_OUT_PRIM_TYPE 1 was refused as an
unsupported output assembly. Each primitive export of an NGG line-strip
program is one line whose indices are packed like a triangle's, so the
mesh module now declares OutputLinesEXT with PrimitiveLineIndicesEXT for
it. A subgroup gets VGT_GS_MAX_VERT_OUT - 1 lines per input primitive and
at least GE_MAX_OUTPUT_PER_SUBGROUP line slots; fast launch keeps using
PRIM_AMP_FACTOR. The output size is part of the cache, draw, validation
and pipeline keys, and the request serialization version becomes 31.
Triangle-strip geometry is unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
When a decrypted SELF contains a non-PT_LOAD segment (such as PT_TLS for pure TBSS) with p_filesz == 0 whose virtual address lies outside any PT_LOAD memory range, unwrap_self previously refused the container with 'segment N vaddr 0x... is in no PT_LOAD'.
Allow zero-size segments without a matching PT_LOAD host to be placed with source offset 0 and new offset 0, preserving valid ELF headers for titles like Unity/IL2CPP PS5 builds.
Also allow file-empty PT_LOAD segments with stale out-of-file source offsets to skip the segment-extent bounds check, preserving memory sizes, addresses and alignments without reading container metadata.
Co-authored-by: simonbronk <[email protected]>
The OpenOrbis create-fself drops a DT_INIT_ARRAYSZ of 0, so a PS4
program without constructors, such as the ClassiCube PS4 port, has
DT_INIT_ARRAY and no size. Code analysis rejected it with "incomplete
initializer array". FreeBSD 11.4's rtld takes the number of
initializers only from DT_INIT_ARRAYSZ and starts it at 0, so such an
array calls nothing; code analysis now adds no roots for it. A size
without an array still fails.
Two defined ELF exports that are renamed to the same name, such as foo
and foo_nid_disambig1, were both written as one name and the patcher
exited 0, leaving a lookup that can reach only one of them. The PE and
Mach-O back ends already reject this.
The ELF patcher now remembers the address (st_value and st_shndx) of
each patched export name and throws "duplicate patched export name"
only when the name comes from a symbol at a different address. Aliases
of one address are kept: the Linux libc defines __cxa_throw and
__cxa_throw_nid_no_patch_cut as aliases of __cxa_throw_nid_postfix, so
both become __cxa_throw, and any lookup of that name resolves to the
same code.
The Linux libc also exported __gxx_personality_v0 twice at different
addresses: the forwarding function in Personality.cpp and the
__gxx_personality_v0_nid_no_patch_cut alias of the guest personality.
Drop that alias, so the name keeps only the forwarding function, as
in the PE build.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
With APS5_VERIFY_DRAW_ENTRIES=1 every hit is captured again, so drawHit is false and no relocated hit counted for its shader set's trial, which judged every set unproductive and turned the relocation off under the very mode meant to check it.
Co-Authored-By: Claude Fable 5.1 <[email protected]>