Commit Graph
29 Commits
Author SHA1 Message Date
J1coding 80feae5f31 iOS: route RetroAchievements through native UI instead of ImGui FullscreenUI
The iOS app renders its own SwiftUI UI, so the shared core's ImGui
FullscreenUI overlay never appears on screen. Before this change every
RetroAchievements event still initialized FullscreenUI and posted the
notification through it, adding per-frame render work for an overlay that
is invisible on iOS, and the native toast layer never saw the events at all.

Add two Host callbacks so a platform can take over notification rendering:

  bool Host::HasNativeAchievementNotifications()
  void Host::OnAchievementNotification(key, duration, title, message, badge_path)

When HasNativeAchievementNotifications() is true the shared core hands each
RA event (unlocks, mastery, leaderboard start/submit/scoreboard,
login, connect/disconnect, summary) to OnAchievementNotification and skips
ImGuiManager::InitializeFullscreenUI() entirely — in BeginLoadingScreen,
ClientLoadGameCallback, DisplayHardcoreDeferredMessage, and
SetHardcoreMode — so the invisible overlay and its render loop stay down.
The existing ImGui path is unchanged for desktop/Android, which return
false from the new callback. Every frontend (eerunner, gsrunner, libretro,
sdl, qt, android, test stub, macOS stubs) gets a no-op implementation; iOS
provides the real one, posting the notification to its SwiftUI toast layer
through ARMSX2_PostRetroAchievementsNotification. The notification now also
carries the configured display duration.

Also flesh out Achievements::GetCurrentUserStats / GetCurrentGameStats /
GetCurrentAchievementList, which were previously unimplemented stubs
returning false. The iOS bridge already wired these up to the
RetroAchievements panel; they now return the logged-in user's score, the
active game's unlock progress, and a bucket-ordered achievement list so the
native panel has real data instead of an empty state.

Stray RetroAchievements debug fprintf spam in the iOS bridge and overlay
defaults is dropped.
2026-07-24 12:15:28 +02:00
J1coding 2e50c8bfbc iOS: gate MetalFX upscaler out of simulator builds
MetalFX.framework is not part of the iphonesimulator SDK, so building the
iOS app for the simulator failed at compile time on every MetalFX reference
(`<MetalFX/MetalFX.h>`, `MTLFXSpatialScalerDescriptor`, the cached scaler
members) even though the upscaler is correctly runtime-gated on real
hardware.

Introduce a compile-time switch that follows the SDK target:

- GSDeviceMTL.h defines PCSX2_HAS_METALFX (1 on device, 0 on sim) and
  wraps the MetalFX include, the m_mfx_spatial cache members, and the
  scaler function declarations behind it. The sim build gets a stub
  EnsureMetalFXSpatial that returns false, and DoMetalFXSpatial short-
  circuits the same way; m_features.metalfx_spatial keeps its default
  false so the UI reports the upscaler as unavailable.
- ARMSX2Bridge.mm gates its MetalFX import the same way (ARMSX2_HAS_METALFX)
  and isMetalFXSupported returns NO on sim without touching the descriptor.
- pcsx2/CMakeLists.txt only emits -weak_framework MetalFX for device or
  non-iOS builds; on sim there is nothing to link against.

Adds generate-ios-sim-xcode.sh, a simulator counterpart to the existing
generate-ios-xcode.sh, so the CMake-generated Xcode project can target
iphonesimulator (ARMSX2_REAL_DEVICE=OFF) for simulator debug and test
workflows. Device IPA builds keep using the existing scripts unchanged.
2026-07-24 12:15:28 +02:00
J1coding 6e5569a794 ci(nightly): add iOS IPA 2026-07-24 07:46:56 +02:00
J1coding 1cf72321ed iOS: Ignore unrelated UIKit text fields in SDL text input
SDL_uikitviewcontroller registers its UITextFieldTextDidChangeNotification
observer with object:nil, so textFieldTextDidChange: fires for every
UITextField in the app, not just SDL's own hidden field. The handler
unconditionally calls SDL_StartTextInput(window) (and the marked-text
path later calls SDL_StopTextInput), so any app-level text input --
notably SwiftUI-hosted login forms -- was stealing first responder on
every keystroke: the user typed one character, the keyboard was
dismissed and re-presented, and they had to tap the field again before
the next character.

Filter the notification at the top of the handler: if notification.object
is not this controller's textField, return early. SDL's own field still
goes through the existing password-manager workaround unchanged.

The SDL3 sources in this repo are vendored, not a submodule, so this
patch lives in tree until the next SDL sync.

Verified by typing into the RetroAchievements login sheet: each
keystroke now keeps first responder and the keyboard stays up for the
whole credential entry.
2026-07-18 17:46:15 +02:00
J1coding 6621011409 iOS: Restore fullscreen SDL window frame at landscape launch
At cold launch the app's root surface rendered as a left-aligned square
inside a landscape screen. The window was sized for portrait because
SDL 3.5.0's UIKit_CreateWindow creates the UIWindow via
[[UIWindow alloc] initWithWindowScene:scene], which inherits the
scene's bounds at a moment when iOS has not yet autorotated out of the
first plist orientation (portrait). SDL 3.3.0 used
initWithFrame:screen.bounds, which filled the screen regardless of the
scene's initial orientation. SDL_SetWindowSize is a no-op for this
path on iOS (only visionOS implements UIKit_SetWindowSize).

The SDL3 sources in this repo are vendored, not a submodule, so patch
UIKit_CreateWindow's scene branch with an #else companion to the
existing visionOS frame-setting block that assigns
uiwindow.frame = data.uiscreen.bounds. This restores the fullscreen
condition that UIKit_ComputeViewFrame's orientation-swap gate checks.

Under host containers that resolve orientation after the
rootViewController is created in willConnectTo:, rootVC.view can stay
pinned to portrait bounds. Add a one-shot re-sync in
sceneDidBecomeActive: that snaps rootVC.view to the window's bounds
when their orientations disagree, then lets Auto Layout propagate to
the SwiftUI child. It is a no-op on the normal launch path where
orientations already agree.

Verified by launching in held-landscape orientation on native sideload
and host-container hosts: the menu fills the screen instead of
rendering in a portrait-width square.
2026-07-18 17:46:04 +02:00
J1coding 818a513e95 iOS: Skip RetroAchievements re-initialization when already active
VMManager::Internal::CPUThreadInitialize() can run more than once in
a process lifetime on mobile hosts that tear down and rebuild the CPU
thread across game launches. Achievements::Initialize() asserts
`!s_client && !s_http_downloader` at the top, so a second call with
RetroAchievements enabled fired pxFailRel("No client and downloader")
and aborted the process. The crash only manifested on hosts that
re-enter CPUThreadInitialize without an intervening Achievements
shutdown, which is why desktop builds never hit it.

Gate the call with !Achievements::IsActive(), which checks the same
s_client pointer the assertion reasons about. The normal cold-start
path (s_client == nullptr) still calls Initialize(); a second entry
with the client already constructed is now a no-op, matching the
expectation the rest of the file already has.

Verified by repeated launch/exit/relaunch cycles on iOS with
RetroAchievements enabled: no abort, and the client initialises
exactly once per process.
2026-07-18 17:45:52 +02:00
J1coding 9b569a6fc5 iOS: Keep keyboard focus while typing RetroAchievements credentials
Each keystroke in the RetroAchievements login sheet dismissed the
keyboard and forced the user to tap the field again before the next
character, which made password entry effectively unusable.

Two SwiftUI mistakes caused it. The sheet's username and password
fields were @Bindings back to @State in the presenting parent, and
the parent's body is what builds the .sheet content closure. Every
keystroke mutated the parent's @State, the parent body re-evaluated,
the sheet content closure re-ran, and SwiftUI rebuilt the sheet.
.presentationDetents([.medium, .large]) re-snapped to .medium on
each rebuild, dismissing and re-presenting the keyboard.

Separately, the parent's .onReceive handler for
ARMSX2RetroAchievementsStateChanged called refresh(), which mutates
more @State on a background cadence. With the parent already
re-evaluating on each keystroke, those notifications forced the same
sheet rebuild from a second source.

Make username and password sheet-local @State, initialised from the
parent's value at presentation so "Log In Again" pre-fill still
works, and pass credentials back through an onLogin(NSString, String)
closure. The parent's body is no longer invalidated by typing, so
the sheet is never rebuilt mid-input. Also guard refresh() with
`guard !showingLogin else { return }` so background notifications
are ignored while the login sheet is up. Switch to a single .medium
detent so the initial keyboard-appearance cannot trigger a one-time
re-snap either.

Verified by entering a multi-character password in the login sheet
without losing keyboard focus between keystrokes.
2026-07-18 17:45:52 +02:00
J1coding 445d7aee1b iOS: Use sandbox-safe shared memory for GS
GSAllocateWrappedMemory's POSIX branch called shm_open("/GS.mem",
O_RDWR | O_CREAT | O_EXCL, 0600) directly. The iOS application
sandbox rejects named POSIX shared memory in the system-wide
namespace, so shm_open returned -1, the function returned nullptr,
and GSLocalMemory::GSLocalMemory() aborted via
pxFailRel("Failed to allocate GS memory storage."). On hosts that
re-enter the CPU thread across launches, this surfaced as a game-
launch abort on the GS thread.

The rest of the codebase already routes shared-memory creation
through HostSys::CreateSharedMemory (pcsx2/Memory.cpp uses it for
EE/IOP RAM), whose Linux/Apple branch selects memfd_create on
Android, shm_open on desktop POSIX, and a file-backed TMPDIR
fallback on iOS so the same call works under the sandbox.
GSAllocateWrappedMemory was the only production caller bypassing
the helper.

Delegate fd creation to HostSys::CreateSharedMemory, drop the
Android-only memfd_create special-case and the redundant ftruncate
(both are handled inside the helper), and use
HostSys::GetFileMappingName so the name is PID-qualified instead of
the fixed "/GS.mem". The MAP_SHARED repeat-mirroring mmap loop is
preserved unchanged so the 4 MB GS VRAM still appears `repeat` times
at contiguous virtual addresses for the PS2 GS address-wrap
behaviour. GSFreeWrappedMemory is updated symmetrically to call
HostSys::DestroySharedMemory.

The Windows branch is untouched, and the caller contract (return
nullptr on failure; the caller's pxFailRel handles the abort) is
preserved.

Verified with the iOS build and repeated game launch/exit/relaunch
cycles: GSLocalMemory construction no longer aborts and the wrapped
memory layout is unchanged.
2026-07-18 17:45:36 +02:00
J1coding 7675402127 iOS: fix post-merge build (AppKit/IOKit/Darwin CDVD gating + MetalFX link)
Upstream's if(APPLE) blocks assumed macOS and broke the iOS build:
- AppKit/IOKit find_library + Darwin CDVD sources use macOS-only frameworks
  absent from the iOS SDK; gate them off iOS (iOS links its frameworks at
  the app target)
- Keep -weak_framework MetalFX for both platforms (iOS uses MetalFX)
- Stub the Achievements::GetCurrent* queries declared upstream but not yet
  implemented, so the iOS bridge links; return false (no data)
2026-07-16 23:39:54 +02:00
Jeen c9072d4f86 CI: remove push trigger from Nightly workflow
Nightly should only run on its daily schedule (08:00 UTC) and manual
dispatch, not on every push to master. The push trigger was added in
e2889838ab under the assumption nightly should run per-push; that
duplicates build-all.yml (which already runs on every push) and wastes
~2h of CI plus an unwanted nightly release on every commit.

Surgical edit only -- e2889838ab also added the changelog generator,
dual-core Android build, and PGO profile, which are correct and stay.
build-all.yml is unchanged (still fires on push to master + PR +
workflow_dispatch).
2026-07-13 18:14:10 +02:00
Jeen 8eada3b11a iOS: add opt-in dSYM CMake option
Add ARMSX2_IOS_DSYM (default OFF) to inject -g into Release builds so a
.dSYM can be extracted for crash symbolication. Off by default to avoid
the link-time and artifact-size overhead on every build; enable with
-DARMSX2_IOS_DSYM=ON when producing tester or debug builds.

The flag must go through add_compile_options (CMake's own flag model) so
the Xcode generator serializes it into each target's compile command.
Four alternatives were tried and all silently failed due to CMake bug
#15224 (the Xcode generator writes per-target OTHER_CFLAGS without
$(inherited), shadowing project/command-line values):
  - XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT on the target
  - CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT project-wide
  - CMAKE_C_FLAGS_RELEASE / CMAKE_CXX_FLAGS_RELEASE
  - OTHER_CFLAGS='$(inherited) -g' on the xcodebuild passthrough

Mirrors the existing if(LINUX) -g1 path at BuildParameters.cmake:225.
No CI change -- the option is purely for manual opt-in.
2026-07-13 17:22:24 +02:00
Jeen 8315f97a50 vtlb: guard fastmem mapping against missing reservation
On low-memory iOS devices (iPhone SE 2, 4 GB RAM, under LiveContainer)
the 4 GB fastmem virtual-address reservation fails at boot. The iOS
boot path correctly disables fastmem and leaves s_fastmem_virtual_mapping
empty. But mid-game, a configuration change (CheckForCPUConfigChanges ->
vtlb_ResetFastmem) can flip EnableFastmem back on, and
vtlb_CreateFastmemMapping then indexes the empty vector -- a NULL deref
that crashes the CPU thread at 0x200 (page 128 * 4 bytes). This was the
long-standing 'NULL+0x200' iPhone SE 2 crash, confirmed by symbolication
against the matching dSYM.

Add two defence-in-depth guards, both mirroring the existing empty-vector
guard in vtlb_RemoveFastmemMappings (commit eb18e0f188):

  1. vtlb_CreateFastmemMapping: early-return when
     s_fastmem_virtual_mapping is empty.
  2. vtlb_ResetFastmem: early-return when s_fastmem_area_unavailable,
     so a config change cannot repopulate mappings into a null area and
     the pointless VTLB_VMAP_ITEMS scan is avoided.

Cross-platform safety: both guards are dead code on non-iOS.
s_fastmem_area_unavailable is only ever set true inside
`#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR` at vtlb.cpp:1379; every
other platform takes the #else branch that aborts boot on reservation
failure (Host::ReportErrorAsync + return false), leaving the flag false.
On platforms where the reservation succeeds, the vector is non-empty so
the .empty() guard never triggers. Verified safe on macOS, Linux,
Windows, Android.
2026-07-13 17:20:57 +02:00
Jeen 4bf3be1f69 GS: write JIT code through RW alias on iOS dual-map
The GS software renderer's ARM64 code generators (DrawScanline and
SetupPrim) handed the raw RX pointer to their vixl MacroAssembler. On
iOS 26+ devices using the LuckTXM JIT mode, executable memory is
dual-mapped: a read-execute alias for the CPU and a separate read-write
alias for the emitter, offset by g_code_rw_offset. Writing to the RX
page faults instantly (KERN_PROTECTION_FAILURE) -- the GS-thread SIGBUS
crash seen on iPhone 16 / iOS 27 beta.

The EE and VU recompilers already handle this via armGetWritableCodePtr
(pcsx2/arm64/AsmHelpers.cpp). Mirror that pattern in the GS path: a
file-local gsGetWritableCodePtr() helper adds the offset on real iOS
devices and is an identity no-op everywhere else (macOS, iOS Simulator,
Android, Legacy-iOS). The original RX pointer is kept as m_code_rx so
GetCode() still returns the executable entry point the rasterizer calls
into -- vixl's GetStartAddress echoes the constructor argument, so
without this override GetCode() would return the non-executable RW
pointer.

Cross-platform safety: the guard (#if __APPLE__ && TARGET_OS_IPHONE &&
!TARGET_OS_SIMULATOR) is byte-identical to the already-shipped EE/VU
helper. On every non-iOS path the helper returns the pointer unchanged,
and g_code_rw_offset is 0, so behaviour is identical to before. The x86
GS path (.all.cpp, selected by CMakeLists.txt:480-490 under ARCH_X86)
shares no code with these arm64 files and is not compiled on any arm64
target.
2026-07-13 17:19:50 +02:00
Jeen 04ea993e99 Merge remote-tracking branch 'armsx2/master' into ios/pr-ready 2026-07-13 00:41:14 +02:00
Jeen 805c161aaf iOS: merge ARMSX2/master into ios/pr-ready 2026-07-13 00:27:07 +02:00
Jeen ecd198419b iOS: fix Games navigation title truncating to Ga...
The inline navigation title 'Games' was being squeezed between the leading
'BIOS Only' button and four trailing toolbar items (import, layout menu,
covers menu, refresh), causing it to truncate to 'Ga...' on the nav bar.

Fix: remove the .navigationBarTitleDisplayMode(.inline) modifier so SwiftUI
uses the default large title mode, which renders on its own row and is not
affected by toolbar item crowding.
2026-07-12 19:14:13 +02:00
Jeen c6b7049664 iOS: disable EE block chaining to fix recompiler crashes
The direct-B block chaining system (s_eeBlockLinkEnabled) is a newer
recompiler optimization that patches direct branch instructions between
JIT-compiled blocks. The proven fork does not use this system and never
crashes, while the monorepo with block chaining enabled crashes on three
different devices (iPhone SE 2, iPhone 17, iPad Pro M1) with signatures
pointing to corrupt JIT-generated code:

  iPhone SE 2: CPU thread data-read translation fault at 0x200 (NULL+0x200)
  iPhone 17: CPU thread instruction-fetch translation fault at 0x100000000
  iPad Pro M1: GS thread write permission fault inside JIT RX code region

All three had JIT-generated recompiled code on the faulting thread's call
stack, one level above the crash site. The common factor is the recompiler
producing or consuming a bad pointer value through the new block-chaining
code path.

Fix: gate s_eeBlockLinkEnabled to false on iOS, falling back to the proven
LUT-indirect dispatch path (adrp+add+ldr+br). This is the same path the
fork uses and has been stable across thousands of gameplay hours. The
performance impact is minimal (one LUT lookup per block exit instead of
a direct branch). Non-Apple platforms keep block chaining enabled.

Root cause traced via systematic debugging:
  Phase 1: 3 crash logs analyzed across 3 devices/iOS versions
  Phase 2: full fork-vs-monorepo diff of aR5900.cpp/AsmHelpers.cpp
  Phase 3: block chaining identified as the only new JIT codegen path
2026-07-12 18:51:33 +02:00
Jeen 922772faf8 Revert "iOS: fix JIT keepalive timer running during gameplay"
This reverts commit b8e94ea84f.
2026-07-12 18:30:51 +02:00
Jeen b8e94ea84f iOS: fix JIT keepalive timer running during gameplay
The keepalive timer was stopped before VMManager::Initialize and skipped
validation while s_vmThreadActive was true. This was wrong: iOS can revoke
CS_DEBUGGED at any time, including mid-frame during active gameplay. When
revocation happened during gameplay, the protection on code and data pages
was silently flipped, crashing the CPU thread (instruction abort), GS thread
(data abort write fault on shared memory), and MTVU thread (translation
fault at null) simultaneously.

Fix: keep the timer running continuously at its 12-second interval during
all app states, including active gameplay. The validation cost is trivial
(one csops syscall plus one byte canary write). When revocation is detected
during gameplay, the timer posts a JITExpired notification and stops — the
next boot attempt will fall back to interpreter mode.

Root cause traced from crash log analysis on iPad Pro M1 (iPad13,8, iOS
26.5): God of War II crashed at frame 71, ~12 seconds after JIT acquisition,
with SIGBUS KERN_PROTECTION_FAILURE on shared memory writes from the GS
thread. Three threads faulted simultaneously, confirming a grant revocation
rather than a single-thread bug.
2026-07-12 18:06:15 +02:00
Jeen d57633224d iOS: merge upstream/master into ios/pr-ready
Resolve two conflicts:
  Threading.h: keep upstream's doc comment for SetNicePriority
  VMManager.cpp: keep our iOS-aware guard that suppresses the controller
  warning on both Android and iOS, replacing upstream's Android-only
  comment-out hack
2026-07-12 17:17:16 +02:00
Jeen ecf0e5c44a iOS: remove fork-only docs and merge device IPA build into build-all.yml
Remove the design specs, troubleshooting guide, changelog, and bringup brief that were fork-local planning artifacts not intended for the upstream monorepo. Merge the confirmed-working real-device IPA build from the fork-local ios_build.yml into the existing build-all.yml iOS job, replacing the simulator-only .app build with the iphoneos SDK device build that produces an unsigned .ipa named with the commit SHA. Remove the now-redundant ios_build.yml.
2026-07-12 17:06:54 +02:00
Jeen fb2c07eb6e iOS: add JIT resilience layer with keepalive, interpreter fallback, and boot watchdog
Build a comprehensive JIT resilience layer that prevents silent black screens when iOS revokes the CS_DEBUGGED grant after approximately 30 to 60 seconds of app inactivity. Add a ValidateJITAlive helper to DarwinMisc that re-probes CS_DEBUGGED via csops and writes a canary byte to the JIT RW alias to detect whether the mapping is still writable, covering the case where the flag lingers but the underlying grant is already dead. Add a 12-second dispatch timer in SceneDelegate that calls ValidateJITAlive while the VM is idle, skipping during active gameplay since the recompiler keeps JIT in constant use, and posts a JITExpired notification on detection. Add interpreter fallback to the boot gate so that when JIT is dead the app falls back to the pure EE, IOP, VU0, and VU1 interpreter instead of blocking boot, wiring up the previously dormant iPSX2_FORCE_EE_INTERP flag and fixing applyFullInterpreterPreset to actually write EnableEE equals false since CoreType was an iOS-UI-only concept the C++ core ignored. Skip executable code-memory allocation in Memory.cpp when in interpreter mode since the interpreter does not generate native code, and null-guard SetJitRange to prevent recording bogus JIT ranges. Add a 15-second VM init watchdog that catches TXM prepare hangs and shows an error dialog instead of leaving a permanent black screen. Add an 8-second timeout to the Universal TXM prepare path by running the brk number 0xf00d cycle on a detached worker thread with thread_local sigjmp_buf, falling back to the Legacy brk number 0x69 protocol on timeout. Add re-boot JIT revalidation so the persistent VM thread validates JIT before signaling, resetting to interpreter mode with s_vmThreadShouldExit to cleanly tear down and recreate the thread with paired CPUThreadShutdown. Restore recompiler settings and fastmem when JIT returns on next app launch. Add the design spec and a user-facing JIT troubleshooting guide documenting black screen causes, interpreter fallback expectations, diagnostic log markers, and workarounds.
2026-07-12 16:41:17 +02:00
Jeen eb18e0f188 iOS: fix fastmem NULL deref crash on low-memory devices and rotation layout break
Fix a NULL dereference crash in vtlb_RemoveFastmemMappings that occurred when the 4 GB fastmem virtual-address reservation failed on low-memory iOS devices such as the iPhone SE 2 under LiveContainer. The s_fastmem_virtual_mapping vector was never resized but was still indexed unconditionally by vtlb_Init through vtlb_VMapUnmap on every boot, dereferencing NULL. Add the same empty-vector early-return guard that the zero-arg overload already has, protecting both the boot path and the COP0 TLB-write runtime path. Fix the portrait and landscape rotation layout break by overriding viewWillTransition in ARMSX2HostingController to re-assign rootView inside the transition coordinator animation block, forcing UIHostingController to invalidate its internal sizing cache and re-measure for the new container size. Without this nudge, SwiftUI kept stale geometry after rotation, producing black bars, cropped viewports, and misplaced touch controls because the GeometryReader never updated and the Metal drawableSize stayed at the pre-rotation value. Revert the two-column pause menu layout in portrait for iPhones since the screen is too narrow even on Plus and Max devices, restoring single-column scroll while keeping two-column in landscape and on iPad.
2026-07-12 16:40:51 +02:00
Jeen 351479e7af iOS: add MetalFX spatial upscaler setting to global and per-game graphics settings
Wire up the MetalFX spatial upscaler as a user-facing setting across the iOS frontend. Add an isMetalFXSupported probe to the ObjC++ bridge that queries MTLCreateSystemDefaultDevice and MTLFXSpatialScalerDescriptor supportsDevice at runtime, using MRCOwned to avoid leaking the device handle under the codebase's manual reference counting. Add isMetalFXAvailable as a computed property and the upscaler Int property with an EmuCore/GS Upscaler INI config to SettingsStore, loaded in init and reload and reset in resetGraphicsDefaults, following the exact tvShader pattern. Add a new Upscaler section to the global Graphics settings view between Upscaling and Filtering, gated on isMetalFXAvailable so the entire section is hidden on unsupported devices. Add per-game Upscaler override to the per-game Graphics tab with the standard Use Global, Off, and MetalFX Spatial options using the minus-one sentinel convention, threaded through PerGameSettingsPanel state, fingerprint, save, and the GraphicsTab binding. Add the hasPerGameUpscaler and perGameUpscaler keys to the bridge dictionary builder so the preload path works without extra round trips. Add the design spec to docs/superpowers/specs.
2026-07-12 16:40:30 +02:00
Jeen 3c3915a70c iOS: enable MetalFX spatial upscaling on iOS 16+ and document in changelog
MetalFX Spatial (MTLFXSpatialScaler) has always been available on iOS 16+ at the Apple API level, but five compile and build gates were stripping the feature entirely on TARGET_OS_IPHONE, leaving iOS users with only plain bilinear stretching. Remove all five gates: hoist the MetalFX include out of the macOS-only branch in GSDeviceMTL.h so iOS gets it too, drop the PCSX2_MTL_USES_UIVIEW guard on the m_mfx_spatial member and widen API_AVAILABLE to macos 13.0 and ios 16.0, remove the TARGET_OS_IPHONE stubs for EnsureMetalFXSpatial and DoMetalFXSpatial so the real implementations compile on iOS and widen the availability check, unguard the supportsDevice feature probe, and add weak_framework MetalFX to the iOS CMake link branch mirroring the macOS pattern. The runtime supportsDevice probe is retained, so MetalFX cleanly no-ops on the iOS Simulator, pre-iOS-16 devices, and any GPU lacking the hardware, falling back to bilinear with a one-shot OSD notice. Update the OSD unsupported message and doc comments to mention iOS 16.
2026-07-12 16:40:01 +02: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
Jeen 431ca0c063 iOS: port JIT and W^X foundation, refresh SwiftUI frontend, fix critical boot and display bugs
Port the complete JIT and write-xor-execute infrastructure to DarwinMisc with four JitModes (Simulator, Legacy, LuckTXM, LuckNoTXM), dual-mapping via vm_remap for writable code aliases, the csops CS_DEBUGGED probe for JIT availability detection, brk assembly helpers for the TXM protocol, and the W^X toggle functions. Connect the JIT foundation to the code emitters through AsmHelpers dual-map bridge, Memory.cpp MmapCodeDualMap allocation, and the aR5900 LegacyEnsureExecutable path. Refresh the iOS SwiftUI frontend from the iOS-refresh branch, bringing in 11 missing and 20 drifted Swift files plus ios_main.mm integration. Switch the CI to a real device build using the iphoneos SDK. Fix the Achievements crash by gracefully degrading when no HTTPDownloader is available (no CURL on iOS). Fix the Metal surface to reuse the UIView's existing CAMetalLayer instead of an orphaned allocation that caused half-screen crops. Fix GS memory allocation by using mmap and vm_remap instead of shm_open which is blocked by the iOS sandbox. Suppress the false positive Graphics not Automatic OSD warning. Merge upstream master and resolve all resulting compile errors.
2026-07-12 16:39:22 +02:00
Jeen 14fc29c0cd iOS: gate macOS-only APIs behind TARGET_OS_IPHONE and add frontend link stubs
Gate all macOS-only system APIs behind TARGET_OS_IPHONE checks across the shared core: ApplicationServices, IOKit, mouse APIs, AppKit, MetalFX, CDVD Darwin sources, USB, discord-rpc, cubeb CoreAudio HAL, and BSD networking headers in DEV9. Port TARGET_OS_IPHONE guards for DEV9 AdapterUtils with iOS fallbacks for sockaddr_dl, rt_msghdr, and sysctl. Add ARMSX2_ROOT to the include path for the frontend's common include style. Drop the global _M_ARM64 define that triggered fast_float MSVC intrin.h inclusion since __aarch64__ covers the core paths. Gate MTLFeatureSet_macOS_GPUFamily1_v1 behind !TARGET_OS_IPHONE. Fix missing unistd.h and gate pthread_jit_write_protect_np which is unavailable on iOS. Add stubs for DarwinMisc JIT diagnostics, Achievements stats and info APIs, Discord_Register, Host capture callbacks, and the host hotkeys map so the frontend links cleanly. Merge upstream master.
2026-07-12 16:38:59 +02:00
Jeen b5e581b1f3 iOS: remove Android and React Native source, wire CMake build system, and add self-contained build workflow
Strip the legacy Android, React Native, Java, Gradle, and res/ directories from platforms/ios that were inherited from the original port. Configure the CMake build for the iOS target with local module discovery, PCAP and CURL guards, rapidyaml source path fixes, Vulkan disabled, lz4 build flags scoped, libjpeg-turbo skipped on iOS, and the Qt UI and test runners turned off. Set CMAKE_SYSTEM_PROCESSOR to arm64 for cross-compilation. Add a self-contained GitHub Actions workflow that builds an unsigned IPA for real devices using the iphoneos SDK, named with the commit SHA. Merge upstream master to stay current.
2026-07-12 16:38:18 +02:00