268 Commits
Author SHA1 Message Date
Brian Degenhardt c2ea1c1f24 SPU2: restore the full core state from AetherSX2-era savestates
The first cut reset the cores and brought back only RAM, registers and
the mixer scalars, and mapped the era's volume levels across raw. Both
halves were wrong. Volume levels are 31-bit in these eras and 15-bit
today, so a full-volume legacy level overflows the mixer's s32 volume
multiply and turns the whole mix into broadband static — loud enough to
amplify even a paused game's silence into noise, which is what made the
defect look independent of the SPU2 payload. And the dropped voice,
streaming and DMA state belongs to a transfer the restored IOP driver
still believes is in flight: left at reset, the driver waits forever
for a completion interrupt no counter will deliver.

Map everything instead: voices (envelope levels scaled 31->15 bits, the
era's Releasing flag folded into the phase exactly as its Calculate()
folded it, decode restarting at the current block), the ADMA/DMA
counters (host pointers left null for the engine's own savestate heal,
except the read-path pointer, which the heal misses — rebuilt from the
channel TADR register), and the SPDIF/ring-position/playmode tail.

Now that this is a field-by-field mapping rather than a memory copy, it
moves out of spu2freeze.cpp into its own translation unit, leaving that
file byte-identical to upstream's. The era layout tables are ours to
carry and upstream keeps editing that file, so the two are better apart.

Verified headless against graded audio captures: a mid-gameplay 0x9A2C
resume state (Dragon Quest VIII) comes back with its music grading
music-like (spectral flatness 0.007) where the partial restore graded
noise (0.38+), and pause-menu saves come back silent because their
sound driver parks every voice at zero pitch and volume until unpaused.
92 core and 1714 recompiler tests green.
2026-08-02 11:20:44 -07:00
Brian Degenhardt 078b5d661b SaveState: load AetherSX2/NetherSX2-format save states
Accept the two legacy majors at the version gate and route them to the legacy
reader, so states from AetherSX2 v1.5-era builds and NetherSX2 v2.1 load in
place. Re-saving one writes a current-format state, which is the whole of the
conversion story.

Three of the zip entries need era-specific handling, so entries now declare how
they survive a legacy load:

- GS carries its own version, which Defrost still reads back through these
  eras. Only its size has to come from the zip entry rather than from today's
  component, since the generic reader would otherwise demand a current-sized
  block and reject a short read.
- SPU2 shares only its head (registers and sample RAM) across eras; its tail
  was re-laid-out repeatedly while the block's self-version stayed at 0xe, so
  the self-version cannot arbitrate it and ThawIt must never see one. The new
  SPU2freezeLegacy restores the memory and resets the cores instead, which
  costs a note in flight and nothing else.
- PAD, USB and achievements predate the StateWrapper streams that read them
  today. They are skipped, and correspondingly not required to be present: the
  pads keep the type and mode they booted with.

The GS entry's existing overrides gain the `override` keyword, which adding one
to the class now requires.
2026-08-02 11:19:56 -07:00
Brian Degenhardt 43e3430b61 SPU2: remove the SVE2 reverb FIR and its MT6899 tuning header
spu2_sve2_fir.h offered SVE2 versions of the reverb FIR behind
SPU2_HAS_SVE2_COMPILER, which is off on every target we build. It has never
been compiled by anyone, and it would not compile if tried: the upsample
coefficient table declares 32768 in an int16_t initializer, which is a
narrowing error, not a warning. Clang rejects it outright.

The arithmetic is wrong too. ReverbDownsample_reference accumulates the
products and then does out >>= 15; the SSE, AVX and NEON paths get that scale
implicitly from mulhrs / vqrdmulhq_s16. The SVE2 version accumulates with
svmlalb/svmlalt and hands the raw sum to clamp_mix with no shift at all, so
every sample would saturate. The same coefficient the initializer rejects is
one the reference clamps to 32767 in make_up_coefs, so the table was wrong on
its own terms.

That leaves spu2_mt6899_tuning.h unreferenced: its only consumer anywhere was
GetFeatures() from inside the SVE2 block. It held Cortex-X925 cache geometry,
prefetch distances and thread-pinning helpers for a device that is not one of
our targets.

RegisterNEONBackend now installs the NEON FIR unconditionally, which is what
it already did in every build that exists.
2026-07-26 19:45:16 -07:00
Brian Degenhardt d1c483b2b3 SPU2: remove the unwired NEON mixer/reverb/DC-filter headers
These four headers came in with a contributor drop aimed at a MediaTek MT6899
(Cortex-X925). The useful part of that drop was kept: spu2_neon.cpp registers
the 39-tap NEON reverb FIR on every arm64 target. The helper headers were
never included by any translation unit, and spu2_neon.cpp carried a note
explaining why - they target mixer.cpp and a "ReaVerb.cpp" that does not exist
here, and they use the MSVC-only __forceinline unguarded, so they would not
compile as written.

They are also wrong where it counts. spu2_neon_mixer.h's GaussianInterpolate,
the one on the hot path at 24 voices x 48 kHz, disagrees with Mixer.cpp three
ways:

  - Truncation order. GetVoiceValues shifts each tap ((coef * sample) >> 15,
    four times, then sums). The helper sums the four products and shifts once.
    Arithmetic shift is floor division and does not distribute over addition;
    over 200k random tap sets the two forms differ 95.8% of the time. The
    hardware truncates per tap, so this is less accurate, not more. Its own
    scalar fallback has the same bug, so it does not match "original
    behavior" either.
  - Element type. It takes const int16_t* and does vld1_s16, but DecodeFifo is
    s32[32].
  - Addressing. It assumes four contiguous samples; the real index is
    (DecPosRead + n) % 32, which wraps.

spu2_neon_dcfilter.h is merely pointless rather than wrong: a two-lane f32
operation on a serial IIR chain with no ILP to exploit, whose batch entry
point just loops the per-sample one, and whose combined convert/clamp/filter
path round-trips through memory.

spu2_optimize.h only reached the build through spu2_neon_reverb_ex.h.

spu2_sve2_fir.h and spu2_mt6899_tuning.h stay: spu2_neon.cpp includes both.
2026-07-26 19:35:54 -07:00
jpolo1224 90daa091db Android: audio backend options, setting descriptions, RA/haptics polish, and ported GS fixes
Audio
- Optional OpenSL ES output backend for devices where the default AAudio path
  crackles, glitches or won't initialise (Settings -> Audio), plus a lightweight
  SPU2 mode that skips the reverb pipeline to free CPU on low-end devices.
- Keep the audio device alive across the in-game menu pause so Android no longer
  reclaims the idle stream and drops sound after the menu sits open (#333).

Settings
- Restored the per-setting descriptions under every GameDB Fix and Advanced
  Speedhack toggle (lost in the settings redesign).
- Per-game Reset now clears the native per-game INI, so it truly reverts to the
  global values instead of the game keeping stale overrides.
- On-screen display now defaults off; Custom stats appear on boot without a
  reset (#385).

Controls / RetroAchievements
- Vibration Strength slider scaling all rumble and touch haptics 0-200%.
- Achievement Sound Volume slider; points now show in the menu before a game
  loads; unlock sounds play with Do Not Disturb enabled.

Misc
- Drop the compiled GS shader/pipeline cache automatically on app update to
  avoid post-update graphical corruption.
- Animated XMB library-background fallback for GPUs without float-texture
  filtering.

GS correctness (ported from sashkinbro/EmuCoreX)
- Reset per-game hardware-hack HLE state on game change (Burnout bloom,
  IRem/GT channel-shuffle) so it no longer leaks across in-app game switches.
- Fix a non-strict-weak-ordering comparator in SortMultiStretchRects.
- Free the leaked m_expand_vao on the OpenGL device teardown path.
2026-07-21 20:42:35 -04: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
WizzardSK e775870c2c libretro core frontend (yaps2_libretro.so): Vulkan context sharing, pacing, input, audio (#4)
* Libretro: Scaffold yaps2_libretro core (M1: builds + dlopens)

New pcsx2-libretro/ target producing yaps2_libretro.so (ENABLE_LIBRETRO=ON,
or built on demand). Milestone 1 of the libretro port:

- Full libretro v1 entry-point surface, version-script-restricted to
  retro_* exports (PCSX2 internals must not collide with the frontend).
- Host:: implementations adapted from pcsx2-sdl: same CPU-thread state
  machine (VMManager::Execute on a dedicated thread, RunOnCPUThread queue),
  no windowing/clipboard/file-picker.
- retro_load_game boots the VM headlessly: GS renderer forced to Null,
  Surfaceless WindowInfo, null audio; config+data self-contained under
  <system dir>/pcsx2 (yaps2-libretro.ini).
- retro_run presents a placeholder XRGB8888 frame; no pacing yet.
- POSITION_INDEPENDENT_CODE forced ON (the pcsx2-sdl ET_EXEC persisted-JIT
  trick cannot apply to a shared core).

Verified: builds in org.kde.Sdk 6.10 (gcc), dlopen + retro_api_version +
retro_get_system_info OK.

Next: M2 Vulkan negotiation interface (wrap vkCreateInstance/Device so
GSDeviceVK inits against the frontend-shared device, set_image handoff),
M3 frame pacing + libretro input/audio, M4 savestates/disk control.

* Libretro: M2 Vulkan context sharing + frame handoff (first light)

The lrps2-libretro pattern ported to the modern GSDeviceVK:

- VKLibretro.{h,cpp}: the loader's global vkGetInstanceProcAddr is swapped
  for a wrapper that intercepts vkCreateDevice (merges the frontend's
  required extensions/layers/features into GS's create info and captures
  the shared VkDevice) and vkQueueSubmit (serialises against the frontend
  through the HW-render interface queue lock).
- GSDeviceVK: adopts the negotiation-provided VkInstance/VkPhysicalDevice
  instead of creating its own (and never destroys the frontend's instance);
  the surfaceless BeginPresent branch publishes the merged display texture
  (ShaderReadOnly + ExecuteCommandBuffer) into a mutex-guarded slot.
- Main.cpp: RETRO_HW_CONTEXT_VULKAN + context negotiation interface
  (create_device opens MTGS from the frontend thread, so GSDeviceVK is
  fully constructed before the context reply); the VM boot parks until
  context_reset delivers the retro_hw_render_interface_vulkan; retro_run
  consumes at most one published frame per call and forwards it via
  set_image + video_cb(RETRO_HW_FRAME_BUFFER_VALID), dupe otherwise.

First light verified on Turnip Adreno 618 (and llvmpipe): GT3 boots
(VMManager::Initialize StartupSuccess), frames arrive hw_valid with a
non-black 640x448 readback.

Known gaps for M3: no frame pacing (VM free-runs; YAPS2_RUN_SLEEP=1 paces
headless runs), no libretro input/audio, m_current is sampled by the
frontend while GS may already be rendering the next frame (single
buffered), no OSD.

* Libretro: M3 frame pacing, joypad input, audio

- Pacing: PublishFrame now blocks the GS thread until retro_run consumes
  the frame (one presented frame per retro_run; the frontend's cadence is
  the emulation's vsync). Enabled at context_reset, aborted before any
  path that could otherwise leave the GS thread parked (context_destroy,
  retro_unload_game, VKLibretro::Shutdown). Static screens still dupe
  thanks to yaps2's SkipDuplicateFrames -- the VM keeps 100% speed and the
  frontend gets video_cb(NULL) for unchanged frames.
- Input: retro_run forwards the libretro joypad + both analogs straight
  into the DualShock2 bind slots (Pad::GetPad(0)->Set), bypassing
  InputManager; SDL input source stays disabled.
- Audio: AudioStream grows a public PullFrames() (frontend-driven pull
  from the ring), SPU2 exposes GetOutputStream(), the config pins the
  Null backend (mix into the ring, no device thread), and retro_run
  drains the ring into audio_batch_cb with float->s16 conversion.
- Config: EmuFolders::Settings is now set explicitly (the libretro path
  bypasses SetDataDirectory, so the INI used to land in the cwd).

Verified on Adreno 618 with GT3: internal fps 59.9, speed 100%, frames
publish on change, INI persists under <system>/pcsx2/inis.

* Libretro: Stable backbuffer ring + dynamic PAL av_info

Fixes the RetroArch heap-corruption crash ~2 minutes in (GT3 FMV -> demo
race transition): the published frame was the pooled m_current texture,
which GSDeviceVK recycles while the frontend still samples the view for
cached-frame replays. Frames are now copied into a dedicated ring of
three backbuffer textures owned outside the pool; on a resolution change
the displaced buffer is retired (kept alive until device teardown)
instead of destroyed, because the frontend can replay the old image
indefinitely (e.g. while its menu is open). Verified: headless harness
clean over 4+ minutes at ~100% speed, RetroArch session stable past the
previous crash point.

Also: when the booted VM reports a vertical frequency different from the
NTSC default (PAL 50Hz, progressive), retro_run pushes an updated
retro_system_av_info to the frontend.

* Libretro: M4 save states (retro_serialize/retro_unserialize)

SaveState grows in-memory zip variants sharing the existing disk code:
SaveState_ZipToBuffer writes the ArchiveEntryList into a libzip
buffer source (zip_source_keep + read-back after close), and
SaveState_UnzipFromBuffer opens one over the incoming blob; the whole
entry/version/screenshot pipeline is reused via a shared
SaveState_UnzipFromZip body, so the on-disk and in-memory formats are
identical (a retro state is a valid .p2s payload).

retro_serialize runs SaveState_DownloadState + ZipToBuffer as a blocking
RunOnCPUThread job with frame pacing temporarily disabled -- while the
frontend is inside retro_serialize it is not calling retro_run, so a
parked PublishFrame would deadlock the GS freeze. The fixed
retro_serialize_size bound is 68 MiB (DownloadState's 64 MiB working
buffer + slack); the actual zip length travels as a leading u64 inside
the block.

Verified on GT3 (Adreno 618): serialize 587 ms, unserialize 131 ms,
emulation continues cleanly after the in-place load.

* Libretro: M4 core options + disk control (m3u multi-disc)

Core options (RETRO_ENVIRONMENT_SET_VARIABLES): GS renderer
(Vulkan/Software; the software renderer still presents through the
shared Vulkan context, so the negotiation path is unchanged), internal
resolution 1x-4x (EmuCore/GS upscale_multiplier, live), fast boot and
widescreen patches. Startup values apply before LoadStartupSettings;
later changes re-apply via VMManager::ApplySettings on the CPU thread.

Disk control (SET_DISK_CONTROL_EXT_INTERFACE): .m3u playlists parse
into a disc list (relative entries resolved against the playlist dir),
single-disc content registers as a one-entry list, and closing the tray
swaps via VMManager::ChangeDisc on the CPU thread. m3u added to
valid_extensions.

Regression-tested on GT3: boot, savestate roundtrip and rendering
unchanged.

* Libretro: OSD via real present path into the backbuffer

The surfaceless BeginPresent no longer copies m_current and skips the
frame -- with the libretro context active it begins an actual present
render pass targeting the dedicated backbuffer (clear + viewport/scissor,
same sequence as the swapchain path) and returns PresentResult::OK. The
whole standard presentation pipeline now runs unchanged: PresentRect
draws the display aspect-corrected with TV shaders/linear filtering,
FullscreenUI::Render and ImGuiManager::RenderOSD draw the overlay, and
EndPresent (libretro branch) finishes the backbuffer, submits without
swapchain semantics and publishes the image to the frontend. The old
copy-based publish is gone.

New core option: yaps2_show_fps (EmuCore/GS OsdShowFPS).

Verified on GT3/Adreno 618: readback shows the ImGui FPS counter drawn
over the aspect-corrected frame; boot/savestate regression clean.

* Libretro: Fix retro_serialize bounds check to include the u64 length header

The check compared buffer.size() against the caller's buffer size, but the
write is sizeof(u64) + buffer.size() — a state within 8 bytes of the
reported serialize size would overflow the frontend's buffer.

* Libretro: Size the output canvas to the internal resolution

The present backbuffer was sized from the fixed 640x448 window info, so
the upscale option rendered internally at 2x-4x and then got scaled back
down before the frontend ever saw the frame.

The present path now tracks the merged frame: expand it to the target
aspect ratio (the internal-resolution screenshot rule), clamp it to the
advertised max geometry (2732x2048, 4x PAL at 4:3), and resize the
surfaceless "window" before the draw rect is computed so the whole
frame stays consistent. ResizeWindow learns to adopt a new size with no
swap chain, and retro_run reports geometry changes with SET_GEOMETRY so
the frontend keeps scaling correctly. Resizes are rare in practice (boot,
FMV/interlace switches, option changes) and reuse the existing
retire-don't-destroy backbuffer ring.

* Libretro: Core options v2 + video/performance options

Registers options through SET_CORE_OPTIONS_V2 with Video/Performance/
System categories and per-option help text (legacy SET_VARIABLES kept as
the fallback), and adds:

- Aspect ratio (Auto 4:3/3:2, 4:3, 16:9, Stretch) — the canvas sizing
  follows it, and 16:9 pairs with the widescreen patches option
- Deinterlacing mode (Automatic/Off/Weave/Bob/Blend/Adaptive)
- No-interlacing patches (progressive output for supported games)
- Blending accuracy (Minimum-Maximum)
- EE cycle rate (50%-300%) and EE cycle skip speed hacks

* Libretro: Don't double-load the Vulkan library in EnumerateGPUs

The frontend preloads libvulkan for the context negotiation, and
EnumerateGPUs asserted (and would have unloaded the host's library) when
called with no device open — which is exactly the Software renderer
path, via D3D::GetPreferredRenderer. Use the already-loaded library and
leave it loaded.

* Libretro: Second wave of core options

Video: texture filtering, anisotropic filtering, software renderer
threads. Performance: hardware download mode (readbacks are expensive
on tile-based mobile GPUs), MTVU and Instant VU1 toggles. System: BIOS
selection (scanned from <system>/pcsx2/bios at option registration,
auto = first valid image) and cheats (.pnach loading).

* Libretro: Fix crash on content close

Two shutdown bugs, both hit on every quit-from-menu:

- GSDeviceVK::Destroy destroyed the negotiated VkDevice, but that device
  belongs to the frontend (it made the vkCreateDevice call) and the
  frontend tears it down after context_destroy — RetroArch was left
  waiting on and destroying a dead device (freeze, then segfault).
  Guard it like the adopted VkInstance already was.

- The frontend replays the last set_image indefinitely (menu background,
  duped frames), so retro_unload_game now retracts the image and waits
  for the GPU before VM teardown destroys the textures it points at.

Verified: 6/6 clean RetroArch exits after a full Vulkan content run
(was a reliable SIGSEGV on close before).

* Libretro: Reclaim retired presentation backbuffers

A resolution change retires the displaced backbuffer instead of freeing
it, because the frontend may still be replaying its image for a few
cached/duped frames. But the retired list was only cleared at device
teardown, so every interlace<->progressive switch (frequent in FMV-heavy
games) leaked a full-resolution render target for the rest of the
session.

Each retired backbuffer is now tagged with a monotonic present count and
reclaimed once kLibretroRetireFrames (6) presents have gone by --
comfortably beyond any libretro frontend's swapchain depth (2-3), and
GSTextureVK destruction is itself fence-deferred, so the underlying
Vulkan objects aren't freed until the GPU is done with them either.

Verified: GT3 boots/renders through its 640x448<->640x480 interlace
switches with no crash (harness + real RetroArch, clean exit).

* Libretro: Move libretro headers to 3rdparty/libretro

The libretro Vulkan HW-render interface header was pulled in by adding
pcsx2-libretro/ to PCSX2_FLAGS's INTERFACE include path, which leaked
onto every target that consumes PCSX2_FLAGS (and had the GS backend
reaching into the frontend's source dir).

Move libretro.h + libretro_vulkan.h into 3rdparty/libretro/ behind a
header-only INTERFACE library (libretro-headers), and link it PRIVATE
to the two targets that actually need it: PCSX2 (for VKLibretro.cpp) and
the pcsx2-libretro frontend. No other target sees the headers now.
2026-07-13 10:56:30 -07:00
Brian DegenhardtandClaude Opus 4.8 5cbcadaa1e Fix desktop/Android build breaks from the ios/pr-ready merge
The ios/pr-ready merge (04ea993e99) introduced two independent
regressions in the shared core:

1. DEV9/AdapterUtils.cpp included Apple-only <TargetConditionals.h>
   unconditionally under __POSIX__, so every non-Apple POSIX target
   (Linux, Android, FreeBSD) failed to compile. Guard the include with
   __APPLE__; TARGET_OS_IPHONE is only consulted to keep iOS out of the
   BSD-socket block, and on non-Apple it correctly evaluates to 0.

2. SPU2::RegisterNEONBackend() is called from spu2.cpp on every arm64
   target (guarded by __aarch64__ / _M_ARM64), but spu2_neon.cpp was
   only added to the build for Android/iOS -- so desktop arm64
   (macOS/Linux/Windows) failed to link with an undefined symbol.
   Compile spu2_neon.cpp on all ARCH_ARM64 targets. The NEON reverb
   backend stays opt-in (SPU2/NeonReverbSIMD, default off).

   While wiring it up for desktop:
   - Drop the unused spu2_neon_mixer/_reverb_ex/_dcfilter includes from
     spu2_neon.cpp. They hold helpers for a mixer.cpp/ReaVerb.cpp
     integration that hasn't happened, and use the MSVC-only
     __forceinline keyword unguarded (breaks clang). The TU only needs
     the reverb FIR plus the SVE2 hook.
   - Guard spu2_optimize.h's x86-only <xmmintrin.h>/_mm_prefetch off
     MSVC-on-ARM64 (falls back to the no-op prefetch).

Verified locally: clean Release build + link on Linux arm64
(RegisterNEONBackend now defined in the binary).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 16:32:50 -07:00
Jeen 3467e72dba iOS: bump version to 2.4.1, activate NEON SPU2 mixing, and port EE recompiler zero-register folds
Bump the iOS app version to 2.4.1 with build number 241 across CMakeLists.txt, Info.plist, and the SwiftUI about screen. Activate the dormant NEON SPU2 voice mixing and reverb backend by wiring up RegisterNEONBackend in InternalReset, which vectorizes volume application, voice accumulation, and clamping using int32x4_t NEON intrinsics with scalar fallbacks preserved. Port five zero-register fold fast paths in the ARM64 EE recompiler shift handlers (SLL, SRL, SRA, their variable-shift variants, and the 64-bit DSLLV, DSRLV, DSRAV) that emit a Mov to zero or a plain register move when the source operand is the zero register, avoiding unnecessary shift instructions.
2026-07-12 16:39:42 +02:00
jpolo1224 11e9289454 Android: bring the platform up on the unified monorepo core
Wire platforms/android to build against the shared core and reconcile the
pieces the Android native lib needs, so the Android target compiles and
links on this repo (produces libemucore_4k.so). Per-platform builds stay
independent; the PC and iOS targets are unchanged.

Build/CMake:
- Android-aware cmake modules under platforms/android/.../cmake with
  CMAKE_MODULE_PATH repointed at them (root desktop modules untouched)
- ryml::ryml alias, TOP_CMAKE_WAS_SOURCED, drop the fatal 3rdparty
  add_subdirectory; pcsx2 PCAP guard elseif(NOT ANDROID)
- git-sync-deps step for shaderc third_party (fetch-on-demand, not
  submodules); android .gitignore for keystores/artifacts/shaderc deps
- dual-core rotation-signed build scripts (release APK + Play AAB)

Core reconciliation (APIs the native lib expects):
- GS present-cap/frameskip, Adreno framebuffer-fetch GSOption round-trip
- SPU2 channel swap + output-pause suppression
- Achievements JSON, VMManager autosave slot, WindowInfo::Android
- FileSystem SAF hooks, custom Vulkan driver path, BIOS-from-fd
- Oboe audio stream, EGL native-window, Linux/Android source guards

refresh-experimental fixes layered onto the shared recompiler/GS:
- IOP direct block chaining (aR3000A, gated s_iopBlockLinkEnabled,
  default off so behaviour is byte-identical until enabled)
- COP2 CO-bit macro-mode gate (aVU_Macro)
- EE mixed-operand constant folding
- Adreno GL coherent depth feedback via gl_LastFragDepthARM, gated to the
  Adreno GPU profile (inert on every other GPU)
- Android GPU gates: GPU-profile shader-header keystone, FIFO_RELAXED
  present mode, Mali coherent readback, Adreno-650 boot-crash gates,
  ROAA VK_ARM alias
2026-07-08 21:46:23 -04:00
David IsztlandClaude Opus 4.8 2eb9ec659c refactor: move Android frontend to platforms/android on single shared core
Snapshot the refresh-experimental Android app (Gradle + JNI + Android-only
3rdparty) into platforms/android/. Delete its vendored PCSX2 core copy and
relocate the ~24 genuinely Android-specific core additions (Oboe audio, Android
stubs, EGL-Android GL context, NEON SPU2, GSGPUProfile, VU1Fingerprint, Android
HTTP downloader) into the root core, guarded by if(ANDROID) in
pcsx2/CMakeLists.txt and common/CMakeLists.txt.

The superseded arm64 JIT experiment (arm64/mac/* IR-VU backend, split
aVU0/aDMAC/aVTLB/aR5900COP*) is dropped: the root macOS arm64 JIT (127 unique
commits, newer) is the canonical recompiler.

Rewire the Android native build to a thin CMakeLists that sources the root
{common,pcsx2,3rdparty} instead of the deleted vendored copy.

NOT yet compiled against a real NDK -- build validation is CI's job.
See REFACTOR_STATUS.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 20:29:23 +02:00
ecff9140a5 arm64: SPU2 mixer NEON paths
ARM64 NEON implementations for the SPU2 mixer hot paths.

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>
2026-06-20 20:27:55 -07:00
KamFretoZ 9f67f72d3c Qt: Revamp the status bar 2026-06-13 15:34:46 -04:00
Ziemas 2c0bb98cac SPU: Speed up DMA 2026-03-11 15:56:49 +01:00
Ziemas 58a4f1e5e9 SPU: Do DC filtering with float samples 2026-03-10 10:39:02 +01:00
Ziemas b0a7d6994b AudioStream/GSCapture: Use float output 2026-03-10 10:39:02 +01:00
Ziemas 9a2561d9cf IOP: Switch to 64bit cycle counter
[SAVEVERSION+]
2026-03-07 09:31:05 -05:00
Ziemas a39a0fd268 SPU: Move the isa selection for reverb resampling
Collect them all in SPU2::InternalReset.
2026-02-12 12:12:07 -05:00
Ziemas f14e061438 SPU: Multi-isa mixer 2026-02-12 12:12:07 -05:00
Ziemas 0356b8a73e SPU: Convert V_Core::Mix to free function 2026-02-12 12:12:07 -05:00
Ziemas 1d9b7c0387 SPU: Remove old comment 2026-02-12 12:12:07 -05:00
Ziemas 2164078b2d SPU: Moved mixer definitions to top of file 2026-02-12 12:12:07 -05:00
Ziemas 9437e1ac41 SPU: Fix and simplify SPU IRQ's
The IRQ handling was bugged due to not resetting has_to_call_irq when
toggling the IRQ enable bit. But I don't see why we need that anyway, we
can just use the IRQ bit in SPDIF info to track that state.
2026-02-08 09:07:31 -05:00
Ziemas 45490d903a SPU: Slow down DMA 2026-01-29 22:26:28 -05:00
Ziemas 10fc9a790d SPU: Emulate voice decode buffers
This makes the timing of NAX advancing more similar to console since it
emulates the decode buffer behaviour of it rushing ahead of playback
until the buffer is full.

It also makes interpolation of the first four samples more correct by
using real data instead of the zero filled previous values.

[SAVEVERSION+]
2026-01-28 12:18:43 -05:00