85 Commits
Author SHA1 Message Date
Brian Degenhardt a6d1e35748 Settings: copying global settings into a game writes only the real decisions
"Copy Global Settings" does not copy the settings you can see. It runs the whole
configuration through a wrapper that writes every key unconditionally, so the file
it leaves behind holds roughly seven hundred of them — network adapters, the
debugger, trace logging, memory cards, sections no settings page ever shows.

That was untidy and no worse, until a key present in a per-game file started
meaning the player claimed it. Now one press of a button whose dialog promises only
that "the configuration for this game will be replaced by the current global
settings" turns off every automatic fix that game had, permanently and silently.

A value is worth writing down only if it decides something, and there are two ways
it can fail to. It can be the stock default, in which case the file carries it as
noise. Or it can be what the game database is going to set anyway, in which case
writing it can only become a claim that suppresses the fix it agrees with. So the
copy now excludes both, and what lands is what the player actually chose.

The comparison goes through the string form rather than the typed value, so a float
or an enum name compares the way it will be stored rather than the way it happens to
sit in memory. That is why the references are built with the same interface class:
same formatting on both sides, exact comparison, one path for every type.

The database reference is a default configuration with the entry applied, not this
one with the entry applied. The question is what the database wants, not where it
would leave the source. It matters for the handful of fixes that clamp rather than
assign, and it errs towards writing the player's value — never towards dropping a
fix, since a value is only skipped when it already equals what the fix would set.

Working the reference out means running the apply functions for an outcome nobody is
going to run with, so they take an apply mode. A hypothetical apply says nothing to
the log, raises none of the recommendation messages, and does not allocate the four
megabyte lookup table that the Goemon TLB fix asks for.

The tests cover the precedence rule and the filter, but the ones that matter are the
drift guards: they assert every gamefix, speedhack and clamp mode has a settings key,
and that the only graphics fixes without one are the six that genuinely have no
setting behind them — three renderer routine selectors and three that only raise a
recommendation. A knob nobody maps is a setting that goes quietly back to being
overridden, with no warning and no failure, and that is what these are here to catch.
2026-08-16 14:21:25 -07:00
Brian Degenhardt 96932405ce Settings: a setting the player set for one game outranks the game database
Change a setting in the per-game settings screen and it does not take. The widget
keeps the new value, the file on disk keeps it, and the emulator runs with
something else — for every game the database has an entry for, which is most of
the ones anyone plays.

The layered read is not the problem; it already puts the per-game file above the
global one. The inversion is that the database writes into EmuConfig afterwards,
from ApplyGameFixes, with no idea where any value came from. So the real order is
global < per-game < database, and the only ways out are two switches that are all
or nothing: EnableGameFixes for the CPU side, Manual Hardware Fixes for graphics.
Either one rescues the setting you wanted by throwing away every other fix the
game had, which usually just trades one glitch for a different one.

So tell the database which settings are not its to write. A key sitting in a
per-game file is a deliberate act: every settings screen represents "use the
global setting" by deleting the key, not by writing the global value. That makes
presence the record we need, with nothing new to store and no frontend to change,
and it works for files already on disk rather than only for edits made from here
on.

PerGameOverrides reads one per-game file — the game layer alone, since the layered
stack cannot tell a per-game choice from a global one and only the per-game one
wins — and reports what it claims. Both apply functions take it and leave those
settings alone, down the road they already had for the global switches, so each
one still gets named in the log and now also on screen.

This generalises the pin that already existed for graphics hacks and had no writer
outside iOS. That mask stays, because MaskUserHacks and any INI already carrying
one speak it, and the derived bits merge into it. But the claim itself is keyed by
hardware-fix id rather than by that mask: there are more fixes than its 32 bits can
name, its width is a persisted format, and the settings players actually change —
mipmapping, trilinear, deinterlacing, texture preloading, blend level, download
mode — were never user hacks and so had no bit at all. That is also why the pin
test moves out from under isUserHackHWFix: nested there, none of them could be
claimed.

The database keeps the last word where it should. The three renderer routine
selectors have no setting and no UI, so nothing can claim them. The BIOS path is
untouched — it forces instant DMA on for a hardware reason and strips hacks
deliberately, and its own comment already says claims get no say there.

The iOS bridge derived the same thing from its own copy of the key table; it now
calls the shared one, so the two cannot drift. Android's live GS apply re-derives
the claims after its reload, or masking would strip a hack the player set.

Drive-by: the division rounding mode logged eeRoundMode's value under its own name,
in both the applied and the skipped message.
2026-08-16 14:12:01 -07:00
pstef 94c4fa72ea EE/FPU: split iFPUd's multiplier deficit into a fourth clamp mode
Both iFPUd modes emitted the multiplier deficit in full: the Booth term,
the boundary predicate over it, and an out-of-line call to the multiply
array for what neither decides. eeClampMode 3 now emits the Booth term
alone, three instructions off ft's mantissa; a new eeClampMode 4 keeps
the other two.  Nothing else differs between them.

Mode 4 reaches the config through the GameDB and the INI and has no
picker entry, but the front ends still write the bit: ApplySanityCheck
rejects a config whose bits are not a whole mode, and a rejected config
falls back to the default rather than to the mode that was picked.

The harness's clamp-mode helpers set whole modes for the same reason.
2026-08-15 23:57:53 +02:00
Brian Degenhardt 44e950e7d5 GS: expose render-pass coalescing in the settings UI and GameDB
Coalescing has only been reachable by hand-editing the INI. It needs to be
switchable per game, because whether it is worth anything depends entirely on
the title: it pays off when a game alternates between two render targets, and
does nothing at all otherwise.

Add the GameDB key coalesceRenderPasses, so a game that benefits can turn it on
by itself, and a checkbox in Graphics > Advanced plus a Full Screen UI toggle
next to the other driver-level GS options, so it can be tried on anything.

It classifies as a user-hack fix, which means enabling Manual Hardware Renderer
Fixes turns it back off - the usual escape hatch, and worth having while this is
new. Note the consequence for A/B testing: GameDB is applied after settings are
loaded, so for a game carrying the key, -set cannot switch it off.
2026-07-25 18:17:16 -07:00
jpolo1224 6a1e12a3c3 GameDB: apply per-game hardware download mode; default Dirge to no-readbacks
hwDownloadMode was parsed as an invalid GS HW fix and dropped, silently
ignoring the entries that used it. Make it a real fix that sets HWDownloadMode,
applied as a default only so a player's own Hardware Download Mode still wins.
Dirge of Cerberus (all regions) now ships with no-readbacks, holding full speed
on GPU-bound devices.
2026-07-22 15:39:39 -04:00
Brian Degenhardt 5dd362bc94 Merge remote-tracking branch 'yaps2/main' into jit-transplant 2026-07-20 12:51:28 -07:00
Brian DegenhardtandClaude 37bc5e1646 ee/fpu: make add/sub guard-bit emulation unconditional
The fpuGuardedAddSub Recompiler option (and its GameDB
clampModes.guardedAddSub override) is gone; both JITs now always mask
the smaller-exponent operand's guard bits on the single-precision
ADD/SUB fast path, matching the Full-mode DOUBLE path's unconditional
guard. Games like True Crime NYC and Jak 3 misrender without the
masking, and per-game flagging proved impractical to maintain — the
failures take cross-build diffing to even attribute. The |exp diff|<=1
early-out keeps the common case at a plain op.

Test-side, EnableFpuGuarded() is removed (the masked behavior is now
the default the guard-bit suite pins directly) and the
DefaultOffEmitsPlainOpMatchingInterp test goes away with the option.
recompiler_tests: 1389/1389 green.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-20 00:22:24 -07:00
Brian Degenhardt 3e077eff9b Merge yaps2: arm64 JIT transplant + test/perf/libretro infrastructure
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.
2026-07-19 10:24:29 -07:00
Brian DegenhardtandClaude Opus 4.8 843a00c7ca EE FPU: gate add/sub guard-bit emulation behind an off-by-default option
The single-precision FPU add/sub guard-bit emulation (fpuEmitGuardedAddSub on
arm64, FPU_ADD/FPU_SUB on x86) was applied unconditionally, matching x86's
compile-time FPU_CORRECT_ADD_SUB=1. A SotC census measured it at ~4.4% of all
EE-emitted code — a per-op deviation vs AetherSX2 (PCSX2 v1.0 base), which emits
a plain fadd + result clamp and has no guard-bit path. The masking is a ~1 ULP
accuracy effect only observable on cancelling add/sub; most titles never need it.

Make it opt-in via a new Recompiler option, fpuGuardedAddSub, off by default:

- Config.h: new RecompilerOptions bit + CHECK_FPU_GUARDED macro.
- Pcsx2Config.cpp: INI load/save (EmuCore/CPU/Recompiler); default off.
- GameDatabase: per-game override via clampModes.guardedAddSub (std::optional).
- Both JITs gate the single-precision masking on CHECK_FPU_GUARDED so they stay
  behaviorally identical under one config (x86 stays the correctness oracle); the
  x86 plain path was already present as dead else-code. The Full-mode DOUBLE path
  keeps its own unconditional guard on both arches (iFPUd), so eeClampMode 3
  titles are unaffected. Decoupled from the Extra/Full clamp tiers by request.

Off by default means the common path now emits a plain fadd/fsub, which also
makes the JIT bit-identical to the single-precision interpreter there (interp
never masked) — one fewer JIT-vs-interp divergence at the default config.

Tests: harness EnableFpuGuarded() (mirrors EnableFpuFullMode); the guard-bit
tests and the two FCR31-clobber CompareSurvivesInterposedGuardedAdd tests opt in;
new DefaultOffEmitsPlainOpMatchingInterp pins the off-by-default plain path via
Run()'s JIT-vs-interp auto-diff. Full suite 1284/1284.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 14:51:27 -07:00
JordanTheToaster d09ce46700 GameDB: Add AA1 rec to the DB 2026-06-26 10:35:51 +02:00
JordanTheToaster 3afc1c2663 GameDB: Add AAT rec to the DB 2026-06-26 10:35:51 +02:00
refractionpcsx2 1fa3c6aa4a GS: Move new Draw Buffering to a UI option 2026-04-17 21:13:30 +02:00
JordanTheToaster 2be34a6938 ImGui/GameDB: Add accurate alpha test 2026-03-20 12:54:00 +01:00
JordanTheToaster 497dc14d11 GS/HW: Add Limit 24 Bit Depth fix to db 2026-03-17 16:13:08 +01:00
Mrlinkwii 9acadb21fe GameDB: remove left over schemea options 2026-01-30 18:06:02 +01:00
SternXD d983b2b066 Copyright: Change year from 2002-2025 to 2002-2026 2026-01-15 00:22:32 +01:00
TheTechnician27 23fd57f641 Copyright: Change year from 2002-2024 to 2002-2025 2025-01-20 05:07:26 +01:00
GovanifY 132431b7c8 headers: relicense to GPL-3.0+
also update to 2024 while i'm at it
2024-07-30 17:17:13 -04:00
refractionpcsx2 1d46ec2059 UI: Add new UI upscaling fix for Native Scaling 2024-06-17 22:25:33 +01:00
JordanTheToaster f3776fa886 UI: Rename Wild Arms hack 2024-06-14 21:01:13 +01:00
lightningterror 932474a7d6 GameDB: Adjust mipmap and trilinear behavior. 2024-05-21 10:45:02 +02:00
Stenzek 12a0644315 Misc: Pass most string_views by value instead of reference 2024-05-17 11:57:38 +10:00
Stenzek 413ba09ee0 Config: Replace FpuNegDivHack with eeDivRoundMode 2024-01-07 21:42:18 +10:00
Stenzek 59d29b3648 Common: Rename General to HostSys
Actually fits what it's doing.
2023-12-27 13:55:35 +10:00
Stenzek 308f8c5112 x86emitter: Abstract MXCSR into a general FPControlRegister type 2023-12-27 13:55:35 +10:00