Commit Graph
93 Commits
Author SHA1 Message Date
jpolo1224 069f8a44f3 Android 2.6.5.1: Local Link LAN play, async GS readback, pause/rotation/settings fixes
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.
2026-07-25 00:48:56 -04:00
jpolo1224 8e23439b26 Android 2.6.5: Adreno Vulkan default, low-latency default, UI sounds, RA client hardening, GameDB
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).
2026-07-24 02:40:17 -04:00
jpolo1224 d856d404e8 Android (github flavor): opt-in auto-check for updates on launch
Adds a "Check on launch" toggle to the App-tab updater panel, default OFF. When
enabled, a silent GitHub check runs once at boot (AutoUpdateGate, mounted at the app
root in setContent, gated on IN_APP_UPDATER) and pops the update prompt only if a
newer release exists -- no "up to date" popup on every launch, and nightly builds are
skipped via checkForUpdate's versionCode guard. Reuses the manual button's exact
check/download/install path.

Github flavor only, like the rest of the updater: AutoUpdateGate is real in src/github
and a no-op stub in src/play, so the boot-check + network code never enters the Play
AAB (build-play-aab.sh still fails closed on REQUEST_INSTALL_PACKAGES).

Requested by takanome9104.
2026-07-23 03:00:02 -04:00
jpolo1224 8f60f14e43 Android (github flavor): in-app GitHub-release updater
Adds a "Check for updates" panel to the top of the App settings tab, github
sideload flavor only. It queries the GitHub releases/latest API, semver-compares
the latest stable tag against the installed build, and offers to download the APK
and hand it to the system installer (progress bar + FileProvider). Nightly builds
(versionCode = Unix seconds, so > 1e6) are always ahead of any stable release, so
they short-circuit to "on the nightly channel" and are never prompted to a stable.

Kept entirely out of the Play build, the same way all-files access is:
- IN_APP_UPDATER BuildConfig flag (true github / false play) gates the App-tab hook.
- The real updater + REQUEST_INSTALL_PACKAGES + the FileProvider live in src/github;
  src/play ships a no-op UpdaterEntry stub so shared code still compiles for play.
- build-play-aab.sh now FAILS CLOSED if REQUEST_INSTALL_PACKAGES appears in the AAB
  (a self-updating app is a hard Play-policy violation).

Verified: the github APK ships the permission + FileProvider + updater code; the play
AAB has neither the permission, the FileProvider, nor the network/install code.
2026-07-23 02:04:46 -04:00
jpolo1224 9ee2b71d7c Android build: adapt the GameDB-from-bin generation to AGP 9.2.1
The generateSharedResources wiring failed the Android build on our pinned
AGP 9.2.1 / Gradle 9.4.1:

- assets.srcDir was passed a Provider (generateSharedResources.map { it... }),
  which AGP 9.2.1 rejects at configuration time ("cannot add Provider instances
  to the Android SourceSet API") -- so the whole Android build was red. Use a
  concrete build-dir path and wire the task dependency explicitly instead.
- the dx11 exclude ("dx11/**") is relative to bin/resources and never matched
  shaders/dx11/, so 8 Windows-only DX11 shaders leaked into the APK. Fixed to
  "**/dx11/**".
- declared generateSharedResources as a dependency of the asset-merge AND lint
  model/analyze tasks (they consume the generated assets dir), so Gradle 9's
  strict implicit-dependency validation passes.

Verified: dual-core release APK builds clean (vc1301); the generated tree carries
bin GameIndex.yaml + the overlay, Dirge hwDownloadMode:2 intact, dx11 trimmed.
2026-07-23 01:44:15 -04:00
jpolo1224 1fde0e4467 Android: achievement filter + RA notification/indicator settings, touch-editor grid snap + movable panel, Back-opens-menu
- RetroAchievements: an All/Unlocked/Locked filter over the achievement list,
  plus DuckStation-style notification settings -- notification and leaderboard
  duration sliders and on-screen position pickers (a 3x3 grid) for both the
  toast notifications and the challenge/progress indicators. Backed by a new
  setAchievementsOptionInt JNI bridge over the existing [Achievements] config.
- Touch layout editor: snap-to-grid (widgets snap by their centre so they line
  up cleanly), and a movable + resizable settings panel -- drag the grip to
  move it, -/+ to resize, double-tap to reset -- with per-orientation placement
  so it stops covering the buttons being edited.
- The Android system Back button / gesture opens the in-game menu (#384),
  toggle in Settings > Hotkeys (default on). Only the system back is routed;
  controller Circle stays the PS2 button.

Requested in #384 by resurrectdev1 and Leunamme30.
2026-07-23 00:15:02 -04:00
jpolo1224 6ce3d9ad7d GS: work around Mali r44p1 device loss on the feedback-loop blend path
The Mali-G615 r44p1 blob loses the rendering context under the in-tile
feedback-loop blend path used for accurate blending: VK_ERROR_DEVICE_LOST on
Vulkan (attachment-feedback-loop) and an equivalent context loss on OpenGL ES
(ARM framebuffer-fetch), crashing effectively every game at any resolution.
It is specific to this driver build -- other Mali blobs, including other
Mali-G615 units on different drivers, run the fast path fine, and NetherSX2's
older renderer is unaffected.

Gate only r44p1 off that path, narrowing by driver version rather than
re-blocking the vendor -- exactly what the extension-select comment above the
Vulkan site anticipated. Vulkan falls back to the per-primitive barrier path
(verified on hardware: no measurable slowdown, God of War holds 60fps);
GLES has no texture-barrier extension so it falls to the framebuffer-copy
path (stable, marginally slower) rather than crashing.

Reported and confirmed on-device by Aryan3472.
2026-07-22 21:50:37 -04:00
jpolo1224 0a017612af Android: library opacity, remove-from-recents, recents export, patches notice
- Library opacity slider (Settings -> App) fades the game rows and cards so the
  wallpaper shows through the list.
- Long-press -> Remove from Recently Played drops a single game from the shelf;
  the game menu now scrolls so no action is clipped in landscape.
- The recently-played list is mirrored to recent_games.json in the data root for
  companion apps, reworked from misantronic's PR #391 to run off the UI thread
  and to update on removal too.
- A notice on the Patches & cheats screen warns that outdated cheats/patches are
  the most common cause of false bug reports.
2026-07-22 15:39:39 -04: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
jpolo1224 2bca7f91b9 Android: Nintendo Joy-Con d-pad now binds and works in-game
Android ships no key layout for the Joy-Con (vendor 0x057E), so every button
arrives as KEYCODE_UNKNOWN and the d-pad could never be mapped or dispatched.
Synthesise a stable, distinct keycode from each button's scanCode at the entry
of dispatchKeyEvent and re-dispatch once, so bind-capture, menu nav and the
in-game lookup all see the same real, matchable key. Gated to 0x057E so no
other controller is affected; scanCode added to the @@JOYCON@@ diagnostic.
2026-07-22 15:39:39 -04:00
jpolo1224 c0351e3105 Android: fast-forward speed slider, and fix the game staying paused after the in-game menu
- Fast-Forward Speed slider in the pause menu (On-Screen tab, under Frame Limit):
  2x-10x, or Unlimited (the default, unchanged behaviour). Below the top it runs
  Turbo at the chosen multiplier via a new setTurboScalar JNI; at the top it uses
  the uncapped path. Every fast-forward entry point (toggle, hold, hotkey,
  settings re-apply) now routes through one ffLimiterMode() helper.
- Fixed the game sometimes staying paused after backing out of the in-game menu.
  Reverts the brief menu-pause audio-keepalive added earlier — its purpose (the
  fast-forward-from-menu hitch) turned out to be a GLES shader-compile stall, not
  audio — restoring the previous pause/resume behaviour. closeAndResume also now
  resumes on RUNNING as well as PAUSED, covering the open-then-close race where the
  asynchronous pause hasn't flipped the state yet.
2026-07-22 00:22:11 -04:00
jpolo1224 d56bff1010 Android: RetroAchievements profile picture and both score totals, plus in-game vibration
- The RetroAchievements menus now show the user's profile picture (RA UserPic) and
  both point totals — hardcore and softcore — on the full RA screen and in the
  in-game pause panel. Hardcore reads "HC" in red, softcore "SC" in blue. The
  avatar URL is emitted in the achievements JSON: from the live client while a game
  is loaded, or rebuilt from the saved account username so the library RA menu can
  show it with no game running.
- The Vibration Strength slider (the global 0-200% haptic multiplier over both
  controller rumble and on-screen touch feedback) is now reachable in-game from the
  pause menu's Controls pane, not only from All Settings.
2026-07-21 21:31:27 -04: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
jpolo1224 1637c1e76a Android: OSD cycle, library music controls, display zoom, skin polish
- OSD hotkey now cycles Full / Minimal / Custom / Off instead of a plain
  on/off, mirrored by a selector in the in-game On-Screen menu; the mode
  persists and every mode drives the GPU-stats line so "Off" is truly off (the
  VSI/PSI leak). (Cotcho)
- Library music: a volume slider (default 15%), a user-chosen custom track with
  reset-to-default, and device-volume support. (KamFretoZ)
- Display Zoom: one AetherSX2-style slider that trims every edge by the same
  fraction to zoom in without distortion, in place of juggling the four manual
  crops. (#383)
- Drop the iOS-layout note from the skin downloader.
2026-07-20 23:25:27 -04:00
jpolo1224 30355e4b62 Android: honour PGO_MODE in the Play AAB build script
build-play-aab.sh hardcoded pgo=optimize, so a caller asking for a profile-free
build silently got one built against the profile anyway. Take PGO_MODE like the
sibling build-release-apk.sh does.
2026-07-20 23:25:26 -04:00
jpolo1224 3666dcea8c Android: animated PS3-XMB library background
Ports linkev's PlayStation-3-XMB (the same wave iOS renders in Metal): a flat
grid displaced in a GLES 3.0 vertex shader by a base spline curve plus flow /
tension / FFD terms, shaded with a fresnel-edged translucent white. Runs on a
TextureView so it composites under the Compose library, capped at ~30 fps to
stay fan-friendly, with the bundled still as a fallback if GL init fails. It is
only the default: a user-picked image (still / GIF / WebP) still overrides it
and clearing that returns to the wave. The readability scrim is dropped to a
whisper over the wave so its blue reads vivid.
2026-07-20 23:25:26 -04:00
jpolo1224 a72ad0eb52 GS: raise the texture-replacement cache budget to RAM/2, 6 GB ceiling
RAM/4 gave a 7 GB phone only 1.75 GB, so the 2.97 GB God of War 1 pack evicted
mid-preload ("cache budget reached") and thrashed, felt as a sustained FPS drop
(#376). RAM/2 gives 3.5 GB and holds that pack whole; the 6 GB ceiling lets a
big tablet keep the 5 GB Persona 3 FES pack resident. Still bounded so low-RAM
devices stay clear of the OOM killer. 6 GB is safe here: Android is arm64-only,
so size_t is 64-bit and cannot wrap.
2026-07-20 23:24:59 -04:00
jpolo1224 40f0cc9910 GS/Vulkan: drop the swap chain when a lost-surface recreate fails
On VK_ERROR_SURFACE_LOST_KHR the recreate can hit NATIVE_WINDOW_IN_USE on the
stale Android window; the old code kept the half-dead swap chain and retried
the same inline recreate every frame, so a game relaunch stayed black forever
on stock Qualcomm Adreno (#380 / #374 — Turnip tolerates it and recovers).
Fully drop the swap chain on that failure so the next onNativeSurfaceChanged
rebuilds from a fresh surface instead of hammering the in-use one.
2026-07-20 23:24:59 -04:00
jpolo1224 4d67c416ad DEV9: keep Android DNS empty so fast-forward networking works
Android's Auto DNS returned an empty list before 2.6.4; 2.6.4 started falling
back to public resolvers (1.1.1.1 / 8.8.8.8), which the console reaches over a
real UDP round-trip through the sockets forward path. Fast-forward outruns that
round-trip's wall-clock timing and DNS fails (#379). Restore the pre-2.6.4
behaviour by leaving Android out of the public-resolver fallback; iOS is
unchanged, and the separate GetAdapterAuto gateway-probe skip stays.
2026-07-20 23:24:59 -04:00
jpolo1224 e2aa896bd4 Android: ambient music on the game library screen
Plays a looping ambient track on the library, like a console dashboard, and
stops the moment a game boots. Toggle in App settings, on by default.

Library-only is deliberate. SPU2 output goes through Oboe and Android has
been seen reclaiming that stream when the VM pauses, so a second long-lived
stream over gameplay would land on top of an existing problem. Gating on the
VM state also matches what the hardware dashboards do.

Defers to whatever is already playing rather than starting a second stream
over a podcast, and handles audio focus: permanent loss releases the player,
transient loss pauses and resumes.

Starting is retried on a timer because the boot splash video carries its own
audio track and MainActivity is launched from its completion callback, so the
first attempt races the splash stream tearing down. A single attempt lost
that race and never retried, leaving music working only after a game had been
launched and exited.

The player is built by hand instead of MediaPlayer.create, which prepares
internally and would leave the media audio attributes ignored.

Track: Calm Ambient 1 (Synthwave 4k) by The Cynic Project, released CC0.
Attribution is not required by that licence but the author asks for it, so it
is credited in the About screen.
2026-07-20 18:22:04 -04:00
jpolo1224 ff537acc80 Android: browse and download controller skins in-app
Adds SkinRepo, following the same shape as the driver and patch browsers:
read an index from the skins repository, download the archive, and hand it to
the existing skin installer so extraction and validation stay in one place.

Skins are listed with a preview image, name and size. The manifest is
preferred and the git tree is a fallback, so the browser still works if the
index is missing. Archives under 1 KB are skipped — the repository briefly
carried two-byte placeholders that downloaded fine and installed nothing.

Every path segment is percent-encoded because almost every skin filename
contains spaces. Downloaded archives import through a new entry point that
takes an explicit name: the picker path resolves names through a document
URI, which yields nothing for a downloaded file, so every download would
otherwise have installed as "skin", "skin_1", "skin_2".

The list notes that these packs carry iOS-only layouts, so a downloaded skin
changes how the buttons look and not where they sit.
2026-07-20 18:21:51 -04:00
jpolo1224 5c2e93904f Android: add an on-screen keyboard hotkey for the emulated USB keyboard
Android soft keyboards commit text through an InputConnection rather than
sending KeyEvents, so the on-screen keyboard did nothing for games that read a
USB keyboard while a physical or Bluetooth one worked. Host an invisible text
editor view, convert the committed text back into key events with
KeyCharacterMap (which also emits the shift presses that make capitals and
symbols come out right), and feed the existing usbKeyboardKey path.

Bound to a hotkey rather than a setting so chat can be opened without pausing
the game. The close path lives in onKeyPreIme because soft keyboards claim
gamepad buttons for their own navigation and would otherwise swallow the
hotkey, leaving no way to dismiss the keyboard. TOGGLE_KEYBOARD is appended
last in SysHotkey because bindings resolve by ordinal.

Key states are paced on a worker thread: usbKeyboardKey only sets a bind value
that the VM samples on its own schedule, so a press released immediately can
fall between two samples and never register.
2026-07-20 16:55:16 -04:00
jpolo1224 5843b5da11 Android: replace the compatibility row with play time in the game info tab
Compatibility only has a value where the GameDB carries one, so the row read
"—" for most of the library. Play time is populated for anything actually
played, and the per-serial totals were already being recorded.
2026-07-20 16:55:16 -04:00
jpolo1224 f964d89c84 Android: show play time and last played in the game info tab
The per-serial tracking never stopped - PlayTime.startSession and
endSession still bracket the running VM, and PlayTime's own comment says
it is shown in the info tab. Only the two rows that displayed it were
lost in the interface rebuild, so existing users already have totals
recorded and will see them as soon as they open the tab.
2026-07-20 15:17:32 -04:00
jpolo1224 613f384fc0 Android: add Material You, an RGB cycle and a custom accent theme
Material You uses the wallpaper-derived dynamic palette. It needs Android
12 while minSdk is 26, so the option is hidden below that rather than
falling back silently - picking a theme and getting a different one reads
as a bug. It also follows the system light/dark setting, so it joins
System in the two places that decide system-bar contrast; left in the
dark-theme branch it would have put dark status-bar icons on a light
palette.

RGB cycles the hue continuously the way peripheral lighting does, accent
and surfaces together. The hue is quantised before the scheme is rebuilt:
a ColorScheme change re-runs MaterialTheme and recomposes the whole tree,
so animating it per frame would repaint every screen at display rate for
a decorative effect.

Custom derives a scheme from a colour picked with RGB sliders. The hue is
kept exactly while saturation and brightness are clamped into a legible
band - a raw accent lets you choose near-black or a muddy brown and get
unreadable chips, which comes back as a bug report rather than as a bad
choice. Surfaces take the same hue, as the fixed palettes do.
2026-07-20 15:17:32 -04:00
jpolo1224 611066a47c Android: add a Cyan UI theme
Bluer and brighter than Teal, which leans green - the two sit next to
each other in the picker and need to be tellable apart at a glance.
2026-07-20 14:55:39 -04:00
jpolo1224 47b917b251 Android: patch manager, memory card and library fixes
Patch manager: the install action rendered below the full cheat list, so
with fifty-odd cheats it sat off the bottom of the screen and a ticked
patch was never installed - the tick is only a selection. It now sits
above the lists. Installed files are listed for the running game rather
than every game at once, failing open when there is no serial to scope
by, since hiding a file the user just installed is worse than listing a
few extra. An install with no known CRC now reports that instead of
writing a filename the core will never load.

Memory cards: with a game in context the slot buttons write a per-game
card and can be cleared back to the global one. Previously both slots
were always global and a separate button covered slot 1 only, so "this
card in slot 2 for this game" could not be expressed at all. Folder
cards are created through the Java file API, and are shown as folders
rather than as zero-byte files.

Also: achievements in progress sort above the rest, and the library
keyboard gains a shift key.
2026-07-20 14:06:43 -04:00
jpolo1224 b9ab52241c Android: controller input fixes and shoulder-button tab navigation
The right stick's directions could not be bound on a Joy-Con while R3
bound normally, because R3 is a keycode and the directions are axes: a
Joy-Con reports its right stick on AXIS_RX/RY and every right-stick path
read AXIS_Z/RZ, so the axes were simply invisible. Resolve the pair per
device (cached - getDevice is a binder call and motion events are far
too frequent to query per event) and use it for bind capture, dispatch,
stick hotkeys and both D-pad folds. Pads that report Z/RZ are untouched.

Adds a per-stick response curve, a left-stick-as-D-pad mode, and routes
both halves of a Joy-Con pair to one port so a game sees one controller.

L1/R1 now flick between settings tabs. It is handled in the key
dispatcher rather than in Compose because shoulder buttons never reach a
Composable, and the hook is registered only while the settings screen is
showing, so in-game shoulder presses still reach the pad.

Launching a .cue from a frontend resolves the sheet's first track and
boots that instead; the core has no cue parser and .cue is not in its
disc whitelist, so the file could never boot directly.
2026-07-20 14:06:43 -04:00
jpolo1224 6d527bc89d Android: per-tab settings reset, UI colour themes, and renderer options
Reset restored the entire scope - Settings() globally, or the whole
per-game override blob - so pressing it on the Renderer page also wiped
Audio, Network, Performance and Fixes. It now resets only the tab being
shown, the confirm dialog names that tab, and it is hidden on tabs that
own no settings at all. Per-game scope prunes just that tab's override
keys instead of deleting every override the game had.

Themes: "Dark" was always the blue-tinted dark theme, which only became
confusing once other hues existed, so it is renamed to Blue and joined
by Purple, Pink, Red, Orange, Green and Teal. Each is built from the
night scheme the way Black and OLED already were, so surfaces carry the
accent's tint rather than leaving blue chrome under a different accent.
The stored preference is the enum name, so an existing "Dark" simply
falls through to the Blue default - same colours, nothing to migrate.
The picker is now a wrapping chip group driven off the enum; a segmented
row is fixed-width and would squeeze eleven options into slivers.

Also: a GS multi-threading toggle, a portrait top/centre option, an
honest 59.94 Hz NTSC framerate stop (an integer slider could neither
display nor re-select the true default once dragged), and round action
buttons centre their glyph rather than its padded layout box.
2026-07-20 14:06:43 -04:00
jpolo1224 558ad4699b Android: commit the bundled ANGLE libraries
libEGL_angle.so and libGLESv2_angle.so were never tracked, so a fresh
clone built without them. applyAngleEnv silently unsets its environment
variables when the libraries are absent and the OpenGL renderer falls
back to the system GLES driver with no error, which meant the ANGLE
option quietly did nothing from the first build made in a clean checkout
onward - on precisely the devices whose native GLES stack it exists to
work around.

These are prebuilt vendor binaries, not build output, so the usual rule
of keeping jniLibs out of the tree does not apply to them.
2026-07-20 14:05:51 -04:00
jpolo1224 07d03a5eac Android: route native file creation through Java, and scope patch state per game
Two fixes that both live in the JNI layer.

Folder memory cards on a user-chosen data folder crashed on the first
new save. FUSE-backed shared storage denies libc file CREATION even
though mkdir is already routed through Java, so SaveYAMLToFile opened a
not-yet-existing _pcsx2_index with an unchecked OpenCFile and then
dereferenced null. Existing saves reuse that file, which is exactly why
only new saves crashed. Null-check the write, and add a
CreateFileViaJava fallback in OpenCFile so a denied create is retried
through the Java file API - the same libc/Java asymmetry that
CreateDirectoryPath already relies on.

Patch and cheat enable-state was written to the base settings layer,
keyed only by patch name, so enabling e.g. "Widescreen 16:9" for one
game switched on the identically named patch in every other game.
LayeredSettingsInterface returns the first non-empty layer with the game
layer ahead of the base one, so upstream keys this per serial and CRC;
do the same, and strip the migrated names from the base list so an empty
per-game list cannot fall back through to it.

The per-game INI exporter also rebuilt the file from scratch, dropping
every key it does not own - the patch lists above, and per-game
MemoryCards and Gamefixes overrides. Load the existing file and clear
only the sections the exporter actually writes.
2026-07-20 14:05:51 -04:00
jpolo1224 9232a10663 Achievements: expose whether an achievement is an active challenge
So the frontend can sort challenges in progress to the top of the list
instead of leaving them buried among the locked ones.
2026-07-20 14:05:32 -04:00
jpolo1224 c581ca0926 GS: add a portrait top-align option for the display rect
In portrait the image was always centred vertically, leaving the game
floating in the middle of a tall screen. Allow pinning it to the top,
which is what a phone held upright generally wants.
2026-07-20 14:05:32 -04:00
jpolo1224 3291334652 GS: bound the texture replacement cache and pace its uploads
The replacement cache had no size limit and no eviction. It was only
ever cleared wholesale on shutdown or game change, so every replacement
a game touched stayed resident until the process was killed: a 5 GB
uncompressed DDS pack OOM-killed the emulator mid-load, and turning
precache off only changed how quickly memory filled.

Track bytes and evict least-recently-used entries past a budget derived
from physical memory - a quarter of RAM, capped at 3 GB so a pack that
would otherwise fit is not evicted needlessly. A texture larger than the
whole budget is uploaded once without being cached, rather than evicting
everything to make room for something that cannot help.

Also pace the uploads. ProcessAsyncLoadedTextures uploaded every pending
replacement in a single VSync while holding the cache lock. Entering a
new area streams a batch in at once and an uncompressed 2048x2048
replacement is 16 MB, so ten arriving together meant roughly 160 MB of
GPU upload inside one frame. Spread them across frames instead; the cost
is a frame or two of pop-in rather than a dropped frame.
2026-07-20 14:05:32 -04:00
jpolo1224 e43707d64c DEV9: use the Android sockets path for adapter selection and DNS
The mobile fallbacks were gated on TARGET_OS_IPHONE only. On Android
GetAdapterAuto still required a host default gateway, which the app
sandbox cannot read out of /proc/net/route, so auto-selection failed and
InitNet force-disabled Ethernet for the session - reported as
"connection device not found" with the interface plainly visible in the
picker. GetDNS likewise returned an empty list because there is no
/etc/resolv.conf.

Extend both gates to __ANDROID__: select on a usable IPv4 interface and
fall back to public resolvers. iOS and desktop behaviour is unchanged.
2026-07-20 14:05:32 -04:00
jpolo1224 e8234e0ddf Android: expose GS Multi-threading (GV7 back-thread) in settings + in-game menu
Off/On toggle (On = Pipelined, enum 3) for GSBackThreadMode, default Off:
- Renderer settings tab, under the graphics-API/driver picker
- In-game quick menu (Graphics), grouped with renderer + Apply & Restart
  (MenuSwitchRow gains an optional inline description)
- Settings model with per-game override, i18n strings, search index entry
- native-lib snapshots the field across a live settings apply so the
  restart-required option can't trigger a mid-game device recreate
2026-07-19 21:04:34 -04:00
jpolo1224 22f900e6cb Achievements: emit Encore / Spectator / Unofficial-test mode state
The Android achievements UI already reads encoreMode, spectatorMode and
unofficialTestMode out of the options JSON and offers toggles for them, but the
native emitter never wrote those fields, so all three always read false
regardless of the underlying setting. The rc_client wiring behind them already
exists; this only exposes their state.

Applied as a hunk rather than a file copy so the iOS UserStats/GameStats/
AchievementList stubs in this file are preserved.

(cherry picked from commit a0bdcbe917)
2026-07-19 21:04:34 -04:00
jpolo1224 adeab9c430 Android UI: pause redesign, custom game names, in-game keyboard, GameDB
Pause button: one clean top-right glyph, single tap opens the menu, and the
on/off toggle is replaced by a tap-to-reveal option that cannot lock the user
out. OSD defaults to 65%, migrating anyone still on the old 100 default, and the
mislabelled On-Screen slider is renamed with the two UI-size sliders moved up
beside it. Widescreen patches relabelled to state that they auto-apply.

Custom game names, editable per title from the Info tab.

The in-game keyboard is hosted once at the top level. It was mounted inside the
in-game screen, but Settings is a separate nav destination that unmounts it, so
the keyboard only appeared after backing out of per-game settings.

Removes the duplicate All Settings shortcut from the in-game menu rail (the
Options tab already has a labelled one) and centres the remaining tabs, which
were left top-aligned with dead space beneath them.

GameDB: Everybody's Golf 4, Magna Carta, Rumble Racing and others from the merged
android-v24 batch, plus four repairs to it - a misspelled gsHWFixes key and a
value missing its '#' comment marker, each of which silently dropped that game's
entire fixes block. Ratchet: Deadlocked / Gladiator get FullVU0SyncHack across
all six SKUs, which is what clears the in-game lockup.

(cherry picked from commit 42baebb860)
2026-07-19 21:04:34 -04:00
jpolo1224 41e91adf0b Android: hardcore patches, overscan crop, OSD colour, fast-forward, frontend launch
Patches under RetroAchievements hardcore: the gate dropped every on-disk pnach,
which is asymmetric with the fallback below it - the bundled patches.zip stays
enabled in hardcore, so a widescreen or bug-fix patch worked from the archive and
silently did nothing from disk, killing everything the in-app Patch Manager
writes. Gate cheats only; they remain blocked at enumeration and in
ReloadEnabledLists, and the two feed separate stores.

Overscan crop (issue #293): the core has always honoured GSConfig.Crop but
Android never exposed it. Four sliders in native PS2 pixels, so a value means the
same thing at any upscale multiplier.

Custom OSD colour: new GSOptions::OsdColor, with the ImGui overlay drawing from
it instead of a hardcoded white.

Fast-forward now uses Unlimited rather than Turbo. Turbo caps at
EmulationSpeed.TurboScalar (2.0x) and produced no visible speed-up on these
devices while "frame limit off" - the same Unlimited mode - demonstrably did.
Settings.applyTo() also forced the limiter back to 0/3 on every apply, cancelling
an active fast-forward while the UI still reported it on; it now preserves the
latch like the in-game overlay path already did.

Per-game settings when launching from a frontend: an external launch passed a
null GameInfo, so settingsKey was null and launchGame resolved global settings -
per-game settings, per-game memory cards and per-game orientation all ignored,
while the same title from our own library applied them. Build a GameInfo for the
incoming URI, probing the serial off the image the way the library scan does.

(cherry picked from commit 7c16cbfa13)
2026-07-19 21:04:34 -04:00
jpolo1224 20d5daf95d Android GS: CPU-decode BC textures, and make pack state visible
Mobile GPUs frequently expose no block-compression support at all (Vulkan
textureCompressionBC false on Adreno 650 / Snapdragon 865, and on Mesa Turnip
for any Adreno; OpenGL gates S3TC and BPTC on separate extensions). The DDS
loader rejected those files outright, so an entire pack silently did nothing.

Worse for packs that also ship game-side data: the P3P Slim Font mod pairs new
FONT0.FNT glyph metrics with 1467 BC7 replacement glyphs, so with the textures
dropped the game indexes new narrow metrics into the old wide atlas and renders
letters sliced in half. Decode BC1/2/3/BC7 on the CPU when the GPU cannot sample
them; the decoders were already built (common/TextureDecompress.cpp, previously
used only for alpha min/max).

Every failure path out of ReloadReplacementMap was silent and they all look
identical from outside - feature off, wrong serial, empty folder, unparseable
names - so pack problems were unanswerable without an instrumented build. Log
the indexed count and the exact directory scanned ("indexed", not "loaded": the
number only proves filename discovery and parsing).

The Texture Manager now shows the serial the CORE will scan, read live from
VMManager::GetDiscSerial(), and warns when no installed pack matches it. Booting
a raw .ELF takes the elf-override branch where the serial becomes the ELF's
filename, so packs installed under the disc serial were never found. Import now
uses that runtime serial too. Texture Packs is reachable from the in-game menu
with a restart button, since the replacement map is only built at boot.

(cherry picked from commit 566ef031d8)
2026-07-19 21:04:34 -04:00
jpolo1224 30b778e9ec Android storage: fix folder memory cards on a custom data folder
libc mkdir() is denied on the FUSE-backed emulated storage Android hands out for
a user-chosen data folder, while java.io.File.mkdirs() on the same path succeeds.
FileSystem::CreateDirectoryPath went straight to mkdir() and returned failure, so
every folder-memory-card save-data creation failed: "Format failed", and a crash
on first save in Soul Calibur 2 / Ratchet & Clank / GT4. Reproduced only with a
custom data folder, never with internal app storage.

A Java bridge for exactly this existed (NativeApp.createDirectoryPath plus the
FileSystem::CreateDirectoryViaJava JNI) but nothing called it after the monorepo
migration - the linker was dropping it as dead code. Wire it in as a fallback on
EPERM/EACCES, in both the flat and per-segment recursive paths.

Also adds folder-card import, which had no working route at all: a folder card is
a directory plus a _pcsx2_superblock marker, but the picker was OpenDocument()
(files only), so people zipped them and the importer appended ".ps2" to the
archive and copied it verbatim - producing a card the core read as unformatted.
Directories can now be imported directly, zips are unpacked, and both validate
the superblock instead of silently producing a broken card.

(cherry picked from commit 265ddb7657)
2026-07-19 21:04:34 -04:00
jpolo1224 3080080226 GS/Vulkan: restore the plain null-texture usage
The ROV-conditional null_usage rode along on a file copy from the development
tree; it is unrelated to this batch and was not meant to land.
2026-07-18 08:37:41 -04:00
jpolo1224 2948db9edf Android: ship the achievement sounds
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.
2026-07-18 08:34:16 -04:00
jpolo1224 7422eb350e Android: pause button redesign, OSD defaults, patch manager fixes, display-resolution shaders
- Replace the in-game settings cog with a single top-right pause button (#357).
  Single tap opens the menu; it renders outside the auto-hide/"Never" gate so
  hiding the on-screen pad can no longer strand you without a way in.
- "Tap to reveal pause" replaces the old show/hide toggle, which could lock the
  menu away entirely. Migrates old layouts, including per-game and per-orientation.
- Run the RetroArch shader chain at the frame's on-screen size instead of the
  internal one, so CRT scanlines land at display pixel density. Sized to the
  aspect-corrected draw rect, since librashader maps input to the whole viewport.
- Patch manager: stop one game's patches showing under another, de-duplicate
  repeated cheats, split patches/cheats into collapsible sections, and drop the
  lag on large lists. Rename the widescreen toggle to say it auto-applies.
- On-Screen settings: the top slider drove OSD scale while labelled "UI Size" and
  shared a label key with the real UI slider. Renamed to "OSD Size" and grouped
  the three size controls together. OSD now defaults to 65%.
- Per-game graphics API, rotation and GPU driver.
- Gate the Adreno push-descriptor disable on driverID so 8 Elite keeps them.
- Load/save state slots no longer squash on the Load screen.
- Sync GameDB and fix two entries that parsed as no-ops: Genji's vu0ClampMode
  casing and DOA2's mis-indented minimumBlendingLevel.
2026-07-18 08:32:45 -04:00
jpolo1224 c2ee554b56 GS/Vulkan: gate the V3D feedback carry per-target, keep the draw-local note
Follow-up to #334. The carry sits inside a condition that only requires ONE of rt/ds to match the current target, so a draw that kept the RT but swapped the depth target could still inherit a stale depth feedback layout - the exact flicker mode the previous draw-local comment warned about. Gate each carry on its own target instead.

Also restore the non-Broadcom flicker warning, including the note that a vendor-scoped carry was tried and reverted once, so the global draw-local behaviour does not get removed again by mistake.

IsDeviceBroadcom now records which build actually reaches it (Linux arm64 / Raspberry Pi V3DV), since this is otherwise surprising in an Android-focused tree.
2026-07-16 05:50:04 -04:00
jpolo1224 7b033e7280 Android 2.6.7: gyro+stick combine, per-game BIOS, library online patches, ANGLE driver picker
- Gyro aim/steer now sums with the physical stick (coarse stick + fine gyro) instead of clobbering it

- Per-game stick invert/swap and D-pad-as-left-stick now scope per game (were global-only)

- Online patch browser reads the serial from the disc image, so it works from the library, not only in-game

- Per-game BIOS override, assignable from the library long-press, applied at boot with a global fallback

- ANGLE for OpenGL moved into the graphics-API driver picker, shown when OpenGL is selected (Render tab + in-game)

- Add WearyConcern1165/ExynosTools as a GPU driver download source
2026-07-15 17:04:58 -04:00
jpolo1224 f1d6360bc3 Android 2.6.4: Fast-Forward menu button, GPU driver recommendation, gyro aim-stick, cheats CRLF fix
- In-game menu: one-tap Fast-Forward in the Session tab (enables max speed + resumes; shows On state)
- Driver picker: show the detected GPU model + recommended driver source (Adreno 8xx/7xx/6xx map to a tuned Turnip pack, other GPUs to the built-in system driver) — appears in both the in-game menu and full Settings
- Gyro: Aim mode can now drive the Right or Left analog stick (per-game aware), for games that aim with the left stick such as Resident Evil 4
- Cheats: fix the per-cheat on/off toggle on PNACH files saved with CRLF/CR line endings (was failing with "unusual formatting")
2026-07-15 14:38:26 -04:00
jpolo1224 97d8c34fc5 Android 2.6.3: OSD reliability, hide games, custom RA sound, green Play button, Mali Vulkan speedup, ANGLE G77 fixes
- OSD: reload-immune visibility snapshot (fixes won't-turn-off); on/off hotkey now keeps the user's chosen stats
- Library: hide/unhide games; optional titles under shelf covers; Clear cached data in the App tab; refreshed drawer icons
- Per-game settings: fix scope stickiness after closing a game + open correctly from the shelf layout; green Play button that actually launches
- RetroAchievements: custom achievement-unlock sound picker
- Vulkan: re-enable attachment_feedback_loop_layout on Mali so accurate blending runs in-tile instead of the per-primitive barrier fallback (big speedup)
- ANGLE (GLES 3.1): emit GL_EXT_shader_io_blocks for interface blocks + alias glColorMaski to OES/EXT — fixes Mali-G77 black screen and mid-render crash
- In-game menu: Performance tab is now a yellow lightning icon
2026-07-14 23:17:40 -04:00
jpolo1224 add32e764c Android: fix ANGLE boot crash (null glDrawElementsBaseVertex on GLES 3.1 → alias to OES/EXT) + Jak 3 GameDB fixes (all regions) 2026-07-14 12:35:02 -04:00
jpolo1224 e833ef88c3 Android: re-add Setup / Change Folders to the library overflow menu (re-opens the setup wizard to change storage/disc folders) 2026-07-14 10:49:34 -04:00
jpolo1224 c305a647eb Android 2.6.1: fix controller remap regression, Black/OLED themes, Boot BIOS, menu scroll memory, RA file-type badge, sub-native resolution fix, achievement-sound reliability, GameDB (Tekken 4/5/Tag, Ar Tonelico 1&2, Aeon Flux, Musashi) 2026-07-14 10:40:16 -04:00
jpolo1224 9e0dc436f7 Android 2.6.0: ANGLE toggle, gyroscope, cheats/disc-swap, GameDB + fixes
- OpenGL-via-ANGLE renderer toggle for broken native GLES drivers, with a
  driver-keyed GL shader cache so switching drivers recompiles instead of
  feeding foreign program binaries to glProgramBinary (fixes Mali-G77 crash)
- Gyroscope input (aim/steering modes, sensitivity, smoothing, invert) shared
  between the Pad settings tab and the in-game Controls tab
- Re-add disc swap without closing the game, and per-cheat PNACH enable
- Xclipse GPU profile + Mali-G615 freeze gate; MediaTek Tekken 5 override
- GameDB: KH2, Tekken 5, Rumble Racing, MK Shaolin, Avatar
- Folder-reuse settings recovery (reverse-map INI + config mirror)
- In-game pause menu rail icons; make new settings searchable
- Resume/auto-load: wait for the renderer to present before restoring state
  and force a present after load (reduces black screen on resume)
- Boot crash guards (pad state before VM); FXAA + CAS sharpening
2026-07-14 02:34:14 -04:00
jpolo1224 917bc67865 CI: nightly rotation-signs + Discord changelog + timestamp versionCode
- ci-nightly-dualcore.sh signs nightlies with the release rotation lineage
  (debug<=API32 -> release>=API33) from repo secrets, so a nightly installs over
  the existing com.armsx2 build; falls back to a throwaway key (with a warning)
- versionCode = Unix seconds since 2023-11, monotonic and always above the manual
  10xx codes, so each nightly out-versions the last installed build
- versionName default 2.5.9 -> 2.6.0
- Discord announcement now includes the changelog (trimmed to Discord's limit)
2026-07-13 02:25:58 -04:00
jpolo1224 e2889838ab CI: dual-core (4k + 16k) + PGO nightly, push trigger, plain changelog
- tools/ci-nightly-dualcore.sh builds the core at both host page sizes and
  merges both .so into one APK so 16k-page devices load their native core
- nightly builds with PGO=optimize (committed pgo/armsx2.profdata)
- trigger the nightly on push to master (was schedule + dispatch only)
- plain-language changelog in the release body from filtered commit subjects
2026-07-13 00:42:11 -04:00
jpolo1224 6cfd8ee00b Android: settings scope toggle + search, BIOS scroll fix, UI polish
- Global/per-game settings scope toggle at the top of the settings rail,
  plus an All Settings shortcut at the bottom
- Settings search overlay + index
- BIOS manager: scrollable list so controller navigation reaches every entry
- Close-app entry with a confirm dialog
- i18n updates
2026-07-13 00:42:11 -04:00
jpolo1224 cfd50df201 GS: Mali/EmuCoreX renderer fixes + per-vendor mobile GPU profiles
- Mali Vulkan: drop the old blend-clamp band-aid; rely on dual_source_blend
  feature detection so only SRC1/blend-mix draws take the SW-blend path
  (no more forced Blending=Max on Mali)
- Fix intermittent stale-tile reads: input-attachment descriptor type for the
  texture-barrier feedback path, vendor-scoped to Mali
- broken_mad_deinterlace weave fallback for Mali-G57 FastMAD
- Add per-vendor mobile GPU profile system (Mali/Adreno/PowerVR)
- Tie test_and_sample_depth to texture_barrier (was forced on)
- Richer Vulkan device telemetry for field diagnosis
2026-07-13 00:42:11 -04:00
jpolo1224 a5d604e8b3 Android: feedback batch 1 — cheats settings tab, HostFS toggle, RA rich presence, in-game macros, in-game upscale list, Force-32 dithering, FXAA + CAS sharpening, freedreno driver source 2026-07-12 13:06:00 -04:00
jpolo1224 4a52347407 Android: library background = static XMB still, drop the MP4 (perf)
The looping MP4 wallpaper hurt in-library performance (sbro review). Replace it with a bundled static XMB-wave still (R.drawable.library_bg_xmb, drawn edge-to-edge via ArmsBackdrop's backgroundLayer). Remove VideoBackground.kt, res/raw/xmb_wave.mp4, and the video option from the background picker.
2026-07-12 08:34:35 -04:00
jpolo1224 98c90a2124 Android 2.5.8: OSD off-by-default + rumble + MP4 wallpaper + controller keyboard/nav
OSD now hides via RenderOverlays mirror of EmuConfig.GS->GSConfig + seed-false on first launch. Rumble: forward SetPadVibrationIntensity to Native::onPadRumble on Android (mono core had no call site). Library: bundled PS3 XMB-wave MP4 as default background, drawn edge-to-edge via ArmsBackdrop backgroundLayer (fixes landscape strip). In-app on-screen keyboard for library search; Recently Played shelf selection highlight; settings category tabs reachable via Row+horizontalScroll. Persian (fa) translation; gold RetroAchievements trophy.
2026-07-11 18:08:27 -04:00
jpolo1224 d12462c43f Android UI: match bottom library toolbar width to the top
The pinned bottom toolbar rendered edge-to-edge (full width) while the top one is
inset by the grid's 8dp + cutout content padding, so it read wider. Apply the same
side inset to the bottom bar's Box so both placements are identical width (vivi).
2026-07-11 11:30:39 -04:00
jpolo1224 6c1a138256 Android UI: toolbar top/bottom toggle (unified shape) + robust shelf recents nav
- Add a Library-toolbar position setting (App tab, Top/Bottom). Both placements
  render the SAME ArmsTopBar rounded-pill (bottomEdge just swaps the status-bar
  inset for the navigation-bar inset), so top and bottom look identical — the old
  bottom bar's top-only-rounded shape was the mismatch vivi flagged.
- At the bottom, the controller reaches the toolbar by pressing Down off the grid's
  last row; the grid reserves the matching top/bottom content inset per position.
- Fix Recently Played being skipped in shelf view for real: replace the
  selectedIndex<columns 'top row' guess (fragile when the per-row count is off) with
  a move-then-check — attempt moveSelection, and if the selection didn't move we're
  on the edge row, so step into the chrome zone. Works regardless of shelf/grid
  column count in either direction (up->chrome, down->bottom toolbar).
2026-07-11 11:24:35 -04:00
jpolo1224 ce46558113 Android UI: library camera-follow, search + language nav, revert bottom toolbar
- Revert the library toolbar back to the top (bottom bar looked worse).
- Camera-follow: the grid only scrolled to the selection while searching, so
  normal controller browsing never followed the selector. Now it follows always,
  targeting the selected cover's real lazy-grid index (accounts for the leading
  toolbar/search/recents/header items and shelf rows) and only scrolls when the
  cover is off-screen. This also lets the selector visibly climb to the top row
  and into the Recently Played shelf in shelf view.
- Make the search field a controller Search zone (Toolbar -> Search -> Recents ->
  Grid): highlights when focused, A focuses it and opens the keyboard.
- Language screen: LazyColumn -> scrolling Column so every language row composes
  and registers in the nav registry — controller nav no longer sticks on the last
  on-screen language (Italian) and scrolls to follow the selection.
2026-07-11 11:09:02 -04:00
jpolo1224 97e83393b4 Android UI: in-game Fixes pane, bottom toolbar, bluer theme
- Add a Fixes tab to the in-game pause overlay rendering the full FixesTab,
  live-applying via InGameOverlay's shared Settings; its controls are
  SettingsControllerNav items so the overlay's content-pane nav drives them.
- Move the library view toolbar (menu/refresh/sort/layout/2D-3D/background) to a
  pinned bottom bar (vivi's mockup). Controller reaches it by pressing Down off
  the grid's last row; grid reserves bottom padding + owns the status-bar inset.
- Shift the night palette toward the OG ARMSX2 blue (deep navy backdrop/surfaces).
2026-07-11 10:54:09 -04:00
jpolo1224 e6a6477fee Android UI: boot video + toggle, shelf/nav controller reach, uk/ku translations
- BootSplashActivity plays the refresh intro video (res/raw/boot_intro.mp4)
  once per process with tap/back/timeout/error fallthrough; new App-settings
  toggle (ui.bootLogo, default on) skips it straight to Main when off.
- Shelf view: report per-shelf column count so D-pad up/down move between
  rows and the top row can reach the Recently Played zone (was left/right only).
- Controller-nav skip fixes: Language row, split GPU-driver source groups,
  UI-size + in-game framerate sliders now register/adjust.
- Add Ukrainian + Kurdish languages; re-translate Russian for accuracy.
- Drop a duplicate EN i18n key (games.toolbar.background).
2026-07-11 10:31:30 -04:00
jpolo1224 01e4f07fbf Library recents zone (Up from grid -> Recently Played -> toolbar, highlight + launch); settings snap-to-top when a category chip regains focus 2026-07-11 09:54:44 -04:00
jpolo1224 bb69b97965 Pause menu two-zone nav (Up/Down tabs, Right into registry-driven content); shelf-view selection highlight; restore GPU driver source groups 2026-07-11 09:46:21 -04:00
jpolo1224 86ce34caad Controller nav rebuilt on manual registry model (settings/save-load/managers/RA/drawer/memcard + library toolbar zone); shelf left-edge alignment 2026-07-11 09:21:50 -04:00
jpolo1224 cdf2a4cf10 Recovery fixes: pre-resolve DriverManagerSection strings, restore shelf_frosted + savetowerforeground, use prebuilt native .so 2026-07-11 08:42:34 -04:00
jpolo1224 d01b94d055 Recover mono ui-overhaul (PR#3 base + session UI edits) + prebuilt native .so from vc1063 2026-07-11 08:35:55 -04:00
jpolo1224 cc6fade4f8 Merge branch 'pr3-ui' 2026-07-11 08:32:45 -04:00
jpolo1224 ed3cd1eed8 Android: re-apply mobile GS (VK push-descriptor fallback + GLES) onto canonical, guarded
Re-apply the Android-specific GS deltas on top of the canonical GS as guarded hunks so
PC/mac/Linux/Windows stay byte-for-canonical:

- VK: restore the push-descriptor fallback (Adreno/Mali stall inside
  vkCmdPushDescriptorSetKHR -> textures never bind -> black screen) as a capability-gated
  path; desktop keeps push descriptors unchanged. Mobile vendor gates
  (Mali/Adreno/PowerVR/Xclipse), dyn_shaderc, FIFO_RELAXED present mode, PowerVR swapchain
  width-align. depth_feedback forced off only under #if __ANDROID__ (desktop keeps
  feedback_loops()).
- OGL: re-apply GLES support (EGL context, is_gles shader branches, GLES query objects),
  runtime-gated by is_gles; guard 3 desktop-reachable riders (present-path
  glInvalidateFramebuffer -> is_gles, EGL SetDisplay body -> #if __ANDROID__, restore the
  negative-swap-interval probe).
- RA toast: guard the AddRect call on IMGUI_VERSION_NUM (desktop imgui 1.92.8 swapped the
  thickness/flags args; Android vendors 1.92.6) so the toast border renders on both.
- Suppress the 'Graphics API is not set to Automatic' OSD warning on Android
  (#if !__ANDROID__); desktop keeps the canonical warning.
- REFACTOR_STATUS: mark the GS re-apply resolved; note the imgui two-copies version skew.
2026-07-10 16:52:26 -04:00
jpolo1224 662c2c42ad docs: record EE fork drop + Android ryml shim in REFACTOR_STATUS 2026-07-10 14:14:32 -04:00
jpolo1224 a6aa75bff2 Android: unify EE JIT on canonical (drop mac-port fork) + fix vendored ryml build
Drop the aR5900*.android.cpp EE fork; Android now builds the canonical Phase-7 aR5900* like every other arm64 target. Device A/B (canonical EE+VU + force-float, PGO tuned for the mac-port so rigged against canonical) showed canonical EE at refresh parity on Android: GoW2 combat EE ~12.8ms, 100% speed / 60fps. The real Android perf lever is the force-float in VMManager::SetEmuThreadAffinities, not the backend. Restores the single shared-core goal.

Back-port the set_user_data() setter onto the Android-vendored rapidyaml 0.10.0 so common/YAML.cpp (from the pcsx2master merge) compiles; the PC/mac build resolves a newer system ryml via find_package. Minimal shim pending the 3rdparty rapidyaml de-duplication (REFACTOR_STATUS #4).
2026-07-10 14:12:43 -04:00
jpolo1224 ecfebfd6b2 Android: bring unified core to refresh-experimental parity
Vulkan render fixes (GS device backends), Oboe audio backend, GameDB armsx2_overrides.yaml override loader, EE+VU mac-port recompiler graft, PGO=optimize, and the VU-slam fix: an Android-only force-float in VMManager::SetEmuThreadAffinities (the slam was thread pinning locking the VU1 worker off the prime core, not the VU codegen). Also: CPU-name SoC-property fallback, Mali VK attachment-feedback-loop crash gate, MediaTek fbfetch disable, and on-device thread-placement diagnostic helpers.

The recompiler grafts and GS deltas are unguarded and land in the shared core (they reach the mac/Linux arm64 builds) - see REFACTOR_STATUS.md items 2 and 3 for the reconciliation this still needs; the VU graft is reducible to just the force-float fix.
2026-07-10 11:16:31 -04:00
jpolo1224 8beadadd9e Android UI/RA polish: User-Agent, toast border, controller warning
- Host::GetHTTPUserAgent: report ARMSX2/2.7.407.0 (the RA-registered client)
  instead of 'PCSX2 <gitrev>', which RA rejects as an outdated emulator and so
  disables hardcore unlocks.
- ImGuiFullscreen: fix ImGui 1.92 AddRect arg order (flags/thickness swapped)
  that drew a ~240px border on the RetroAchievements toast.
- VMManager: suppress the false 'Controller 1 has no input bindings' warning
  (Android injects pad state directly, bypassing InputManager bindings).
2026-07-09 10:23:59 -04:00
jpolo1224 774afbd9eb ImGui: seed s_font_info from Roboto on Android + default-font fallback
SetFonts() is never called on Android (no Qt/language layer) so s_font_info
stayed empty and AddTextFont() returned null -> blocky/blank OSD. Seed it from
the bundled Roboto-Regular.ttf, and fall back to the built-in font if the atlas
still fails so the GS device can initialise regardless.
2026-07-09 10:23:59 -04:00
jpolo1224 2512027e9a Android VM lifecycle: prompt EE stop + fix 2nd-launch kick-back
- R5900 _cpuEventTest_Shared: bail out early on VMState::Stopping/Shutdown and
  on IsExecutionInterrupted() so the EE leaves Execute() promptly on stop
  (previously hit the ~5s shutdown timeout).
- native-lib Host::RequestVMShutdown: no-op if already Shutdown. The queued
  task could re-set Stopping after the run loop already reached Shutdown,
  sticking s_state at Stopping so the next Initialize failed 'already running'
  -- kick back to library on the 2nd game boot.
2026-07-09 10:23:58 -04:00
jpolo1224 1a62f62d2a arm64/aR3000A: restore per-block IOP recompiler reset guard
The IOP dispatch loop lost its 'if (iopRecNeedsReset)' guard, leaving a bare
recResetRaw() that ran a full IOP recompiler reset on EVERY block (~800/s).
recClearLUT zeroing the LUT then dominated ~97% of EE-thread CPU in memset, so
every game crawled ~10-50x too slow (black screen / Speed 0%). Also drops a
duplicated recPtr/const_pool.Reset/recClearLUT block in the same function.
2026-07-09 10:23:58 -04:00
jpolo1224 e9b22ece5c Android: Vulkan surface + GS device bring-up on the unified core
- VKLoader.h define VK_USE_PLATFORM_ANDROID_KHR; VKEntryPoints.inl load
  vkCreateAndroidSurfaceKHR (VK_NO_PROTOTYPES); VKSwapChain create the
  ANativeWindow surface; GSDeviceVK Android surface-ext select + surface-lost
  re-acquire + non-fatal CAS on turnip.
- VKShaderCache: unversioned shaderc_shared name on Android (no .so.1).
- LnxHostSys: idempotent PageFaultHandler::Install (process reused per launch).
- imgui: enable FreeType PLUTOSVG + bundle plutosvg/plutovg for color emoji.
2026-07-09 10:23:58 -04:00
jpolo1224 baa9454c1b Android: don't compile DEV9/pcap_io.cpp (no libpcap); use the stub
The unconditional pcsx2DEV9Sources list compiled the real pcap_io.cpp on
Android, which references pcap_findalldevs / pcap_open_live / ... with no
libpcap present -> undefined symbols at link. A debug build hid this via
--gc-sections dead-stripping the unreferenced calls; the LTO release build
surfaced all 12. Android already ships Android/AndroidPcapStubs.cpp (the stub
PCAPAdapter), so gate the real pcap_io.cpp to non-Android platforms.
2026-07-08 22:25:25 -04: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
jpolo1224 80d4df9d7e Restore macOS signing action args 2026-06-10 00:33:17 -04:00
jpolo1224 30eec9dbe9 Use rcodesign 0.29 for macOS entitlement config 2026-06-10 00:27:17 -04:00
jpolo1224 c7d8a07308 Verify macOS notarized JIT entitlements 2026-06-10 00:20:33 -04:00
jpolo1224 7671a71590 Fix macOS memory mapping and signing entitlements 2026-06-09 23:59:28 -04:00
jpolo1224 d97f025276 Restore macOS UI icon in CI builds 2026-06-09 16:04:18 -04:00
jpolo1224 a48e7ae8d8 Notarize macOS UI release bundle 2026-06-09 15:50:32 -04:00
jpolo1224 30e6c975e4 Fix macOS backend bundle signing 2026-06-09 15:30:32 -04:00
jpolo1224 39421d6bc8 Fix macOS setup bootstrap and duplicate games 2026-06-09 10:14:54 -04:00
jpolo1224 4ecf5e2107 macOS: update OSD branding to 2.1 2026-06-08 19:22:54 -04:00
jpolo1224 ff02d57aec macOS: enable GameDB defaults and bump 2.1 branding 2026-06-08 19:18:19 -04:00
jpolo1224 8c2461e905 macOS: port ARM64 EE improvements 2026-06-08 19:18:10 -04:00
jpolo1224 dc536ef016 Add ARMSX2 macOS UI shell 2026-06-08 01:14:16 -04:00