USE_COVERAGE instruments the build with clang's -fprofile-instr-generate
-fcoverage-mapping, exposed as the clang-coverage preset (build-coverage/,
inheriting clang-devel so the dev asserts stay on, Qt off since nothing in
the test path needs it).
The instrumentation is tree-wide rather than scoped to pcsx2/arm64: much of
the JIT is inline code living in headers that get pulled into core and common
translation units, so narrowing at build time would drop counters for exactly
the code we care about. tools/coverage.sh narrows at report time instead,
where the filter is exact.
The script builds the five gtest binaries, runs them with per-process profile
files, merges, and reports scoped to pcsx2/arm64/ (--scope all widens to the
other ARM64-only sources). Two hazards it defends against:
- cmake --preset takes the source dir from the working directory and ignores
-S, so running this through the /home/bmd/ARMSX2 symlink bakes the
symlinked path into every coverage mapping. It cds first.
- llvm-cov does not error when --sources matches nothing; it reports every
file it has data for, which reads as a plausible whole-tree number. The
filter prefix is read back from CMAKE_HOME_DIRECTORY so it always matches
what the compiler recorded, and a row-count tripwire fails the run if the
report escapes its scope anyway.
Baseline for pcsx2/arm64/: 74.65% lines, 79.94% functions, 77.70% regions.
ARMSX2 is GPL-3.0+ and the Discord Social SDK is proprietary. Linking them into
one binary would make the emulator a combined work with a library whose
corresponding source cannot be supplied, so the SDK now runs as a separate
program in its own process and the two talk over a deliberately dumb message
interface: a title, a serial, an image URL, a list of names. No emulator type
crosses that line.
libemucore has no DT_NEEDED on the SDK and never loads it; the bridge builds
into its own libarmsx2_discord.so, loaded only in :discord. With the feature
switched off that process does not exist and the library is never mapped at all.
Verify with: llvm-readelf -d libemucore_4k.so | grep -i discord (must be empty)
The SDK itself is no longer in this repository. Discord's terms permit shipping
it inside a working application but not republishing the raw SDK, so it is an
optional private build input via DISCORD_SDK_DIR. Unset -- every public clone --
the feature compiles out and the UI reports itself unavailable. Deliberately not
a product flavour: one release variant, and the only difference is whether that
directory was present at build time.
Also here, from testing the feature into shape:
- Presence uses the game's own cover art, and our logo (an Art Asset key, not a
repo URL, so it tracks the current mark) when idle.
- Friends show their avatar AND the cover of what they are playing, never one
instead of the other -- swapping the face out for box art loses the identity
exactly when the row gets interesting.
- A count badge on the Friends entry point, in the drawer and in the in-game
header, because the point of it is to be seen by someone not looking at the
friends list.
- Friends moved off the in-game tab rail into a header button with its own
panel. It was last on a rail that scrolls, so reaching it meant knowing it was
there. The panel is composed, not a Dialog: a Dialog takes its own focused
window and swallows gamepad keys before our input plumbing sees them.
- "<friend> is now online" is one Compose banner at the Activity root, replacing
a split between an emulator OSD message in game and nothing at all in the
library. The OSD is text-only and could never show an avatar.
- Reconnect after a drop, with backoff. The SDK does not retry and its
connection does not survive being backgrounded, so a drop used to be terminal
until the app was restarted.
Crash and correctness
- Fix a crash when backgrounding the app mid-game: onPause flushed the Vulkan
pipeline cache from the UI thread while the GS thread was creating pipelines
into the same VkPipelineCache. Vulkan requires that handle to be externally
synchronised, so this was a driver-level data race and crashed on Adreno and
Xclipse alike. The flush now runs on the GS thread, posted via the CPU thread
so it does not race the EE-owned MTGS ring.
- Fix an unbounded out-of-bounds vertex read in the GSRendererHW sprite-merge
paving path: the inner loop advanced i instead of j, so j stayed loop-invariant
and the scan walked past m_vertex->tail.
- Fix per-game settings being silently ignored: gamesettings/<serial>_<CRC>.ini
loads into a higher-priority layer than anything the app writes, and saves made
from the library never regenerated it, so any key already in that file
overrode the user permanently. Only the category-Reset path rewrote it, which
is why Reset appeared to be the only thing that worked.
- Fix screen rotation: the BIOS followed the launcher rotation instead of the
renderer's (it has no GameInfo, and the tier was keyed on that), and the
launcher stayed locked in a game's orientation after exit because the cleanup
lived only inside stop()'s vmRunLoopActive-guarded branch, which loses a race
against the VM thread's own finally. Rotation tier is now an explicit flag and
the cleanup runs on every terminal path.
- Discard the Vulkan pipeline blob whenever the SPIR-V cache is discarded. It was
validated only against the device header (vendor/device/pipelineCacheUUID),
which is identical across an app update, so a SHADER_CACHE_VERSION bump kept
every pipeline built from the old shaders and nothing pruned it.
- Make eeRecExitRequested atomic: it was a plain bool written from the JNI thread
and read on the CPU thread.
- OpenGL: restore GL_PACK_ALIGNMENT after readback, add the missing memory
barrier after the CAS dispatch, and initialise GLState::depth_mask to GL's
actual default.
- DEV9: log the GetNetAdapter default: bail and the InitNet skip. Both returned
silently, so a settings mistake surfaced as missing hardware three layers away.
Local Link (new)
- New DEV9 backend bridging emulated PS2 Ethernet between devices over
authenticated local UDP, so games with a built-in LAN / System Link mode can
play together. Ported from EmuCoreX (sashkinbro) with the wire format
unchanged, so peers remain compatible across both forks.
- Network mode picker (Online / Host / Join), host address readout, auto-derived
peer ids, generated room codes, hostname support alongside numeric IPv4, and a
link to the supported-games list. Fully controller-navigable.
Performance
- Asynchronous hardware download mode (experimental, opt-in): non-blocking
GPU->CPU readback so the EE thread no longer waits on the GS thread. Ported
from EmuCoreX. Appending Asynchronous to GSHardwareDownloadMode makes the enum
non-ordered, so the relational comparisons on it are replaced with
IsHardwareDownloadReadbackEnabled / IsHardwareDownloadEEThreadRead.
- Affinity Control Mode (experimental, opt-in): EE/VU/GS priority orders plus a
Performance Cores mode. Android otherwise leaves these threads unpinned.
- Raise the texture-replacement cache ceiling from 6 to 16 GB; RAM/2 remains the
real limiter, so this only binds at 12 GB RAM and up.
- Low Latency frame pacing is no longer the default, with a one-time migration
for installs that took the earlier flip.
Features
- Auto renderer resolves to Vulkan HW on Adreno.
- Auto Progressive Scan (per-game): holds Triangle+Cross through boot.
- OLED black as a modifier over any accent colour, including Custom and RGB.
- Optional system keyboard instead of the built-in on-screen one.
Game compatibility
- Everybody's Golf 4 / Hot Shots Golf Fore! hwDownloadMode across all regions
(PR #421, XDarkFallenX).
- Delta Force: Black Hawk Down (PR #401, XDarkFallenX).
- Reduced input latency and input handling improvements (PR #403, Splaser).
RetroAchievements
- Inject the client version from a build-time secret kept out of public source,
with a stock-PCSX2 fallback for secret-less builds, so third parties cannot
copy the client identity. Covers the iOS token too.
Rendering
- Auto renderer now resolves to Vulkan HW on Adreno (OpenGL elsewhere).
- Mobile hardware ROV (Phase 0): tile-native depth feedback behind the ROV toggle.
Performance & input
- Low Latency frame pacing is the default on capable devices, with a one-time
migration for existing installs; low-end devices keep the queued pacing.
- Reduce Android input latency and improve input handling (PR #403, Splaser).
- Experimental CPU clock hint (ADPF) toggle in Performance settings (default off).
Audio & UI
- Pop-up open/close sound cues (info, hardcore confirm, patches & cheats).
- Alternating controller navigation / slider tick sounds.
RetroAchievements
- Inject the RA client version from a build-time secret kept out of public source,
with a stock-PCSX2 fallback (no hardcore) for secret-less builds. Applies to the
iOS client token too. Prevents third parties from copying our User-Agent.
Game compatibility
- Delta Force: Black Hawk Down (SLUS-21124 / SLES-53299) GameDB fixes
(PR #401, XDarkFallenX).
Merges yaps2/main (github.com/yaps2/yaps2, c16b88cb7) into ARMSX2,
replacing the arm64 recompiler family with the yaps2 JITs and importing
the yaps2 testing, perf, and libretro infrastructure. Common ancestor is
upstream PCSX2 342db5152 (2026-06-19); git auto-merged all but 38 files.
Replaced (deleted in this merge, recoverable from history):
- arm64/aR5900*, aR3000A*, aVU* -> arm64/iR5900*/iR3000A*/microVU*-arm64:
EE static-pin register file with lazy dirty tracking, dual-residence
allocator, IOP block linking, native COP2 macro ops, inline unaligned
fastmem, persisted VU program cache, call-ret shadow ring, VU0 spin
fast-forward.
- MVU_DIFF shadow-run hooks in shared VU interpreter TUs (superseded by
the offline vurunner JIT-vs-interp oracle).
Imported from yaps2:
- tests/ctest/core/recompilers: ~80 gtest suites (EE/IOP/VU differential
harnesses, fuzzers, ABI digest tripwire, capture format pins) plus the
gs_vertex_tests kernel oracle.
- pcsx2-vurunner / pcsx2-eerunner headless capture-replay runners.
- tools/perf counter-based A/B rigs, perf jitdump productionization,
PmuCounters, clang-perf/clang-handheld presets.
- pcsx2-libretro core (ENABLE_LIBRETRO, default OFF; rename pending).
- GS vertex-kick fast path (GV series): TBL-based packed parse,
register-resident kick, scalar-outcode cull, fused draw-rect/FindMinMax.
- Null renderer, VK_KHR_display direct WSI, swapchain PresentStats.
- SPU2 NEON mixer vectorization, EE timer read clamp (NFL 2K5 hang),
IOP ioman signed-compare fix, assorted UB fixes.
Kept from ARMSX2 in the both-touched files:
- iOS dual-map W^X and fastmem-unavailable resilience (Memory, HostSys,
vtlb). The split data/code area model is retained; both areas now take
fixed VA hints so cached VU JIT code stays deterministic on Linux.
- Android thread-affinity model, VMState shutdown early-outs, all
platform frontends, branding, CI, RetroAchievements identity/policy.
- GSDeviceVK: ARMSX2's push-descriptor decision logic (Mali crash gate,
proprietary-vs-turnip Adreno split) merged with yaps2's descriptor-pool
exhaustion recovery (flush + render-pass restart instead of dropped
binds). Vendor feature policy is the union: Mali fbfetch policy with
MediaTek/G57/Xclipse gates from ARMSX2; Adreno stencil/ROV/
test-and-sample-depth hang avoidance and no_ps2_z_quantization from
yaps2.
Build-system notes:
- The Qt debugger is now gated behind ENABLE_QT_DEBUGGER (default off on
arm64) so handheld builds drop the KDDockWidgets dependency.
- GSDeviceNone and remaining yaps2 GS code were ported to the newer
upstream GSTexture Usage-flags API.
The replaced backend's interpreter-fallback glue (intExecuteOneInst,
AndroidEEOpHist) and the EEDiffVerify runtime differ are retained for
now; dead pieces will be removed in a follow-up commit.
The unlock / message / leaderboard-submit sounds were caught by the blanket
*.wav ignore, so the assets folder shipped empty from a clean clone even though
local builds had the files on disk. Add them and un-ignore that folder so future
sounds aren't dropped the same way.
CMake/preset wiring for the ARM64 target, the vixl C++20 enum-conversion warning
suppression, PmuCounters (cycle/instret PMU reads), and the Perf jitdump dir/enable
controls (EmuConfig.Profiler.EnablePerfDump, redirected out of /tmp into the cache
dir). Plus small platform/build fixes (ALSA thread naming, SmallString, X11 guards,
ARM MIDR CPU-name fallback, gcc lambda decay). The ARCH_ARM64 status banner now
reflects that EE/IOP/VU recompilers are all implemented.
Co-Authored-By: Ryan Walklin <ryan@testtoast.com>
Co-Authored-By: Brian Degenhardt <bmd@bmdhacks.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds `/inis/debuggersettings/` settings folder to contain settings specifically for the debugger. Adds functionality to manually save (to settings) Breakpoints/Saved addresses and automatically load them upon launching the debugger.
Adds Patches folder to git ignore so that changing branches/stashing/unstashing does not impact patches files in repository folder.
This matches how the cheats folder is handled.