Commit Graph
6478 Commits
Author SHA1 Message Date
Henrik Rydgård 61e60ee6ff Merge pull request #22560 from eraycep/add-fading-chat-button
UI: Fade chat button with touch controls
2026-10-14 14:13:48 +02:00
Henrik Rydgård bac8668204 Merge branch 'master' into add-fading-chat-button 2026-10-14 13:28:20 +02:00
Eray Cepni d970cf74f2 UI: Fade chat button with touch controls
Apply touch-control opacity to the chat button so it fades after
inactivity and reappears on touch. Keep it visible when touch controls
are disabled.
2026-10-14 14:20:33 +03:00
Henrik RydgårdandClaude Opus 5.5 753e869ca1 Search: Drop the focus from a view the filter hides
When a search stopped matching the focused game, it stayed focused while
hidden, so its background and music kept going.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 11:17:44 +02:00
Henrik RydgårdandClaude Opus 5.5 ce8f48980a Game browser: Default to the large list for Games and Homebrew, bigger folders
The old GridView keys are now read as ints, so a missing key can be told
apart from false. Configs without them get the new defaults, while
existing ones still migrate their choice.

Folders get taller lines in the large list too, though not as tall as
the games.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 11:00:00 +02:00
Henrik RydgårdandClaude Opus 5.5 ef72f27fea Game browser: Keep the search and focus when returning from a game
FocusGame cleared the path to focus right after setting it, so since
the refresh became deferred nothing got refocused. The refresh also
showed every game again while the search bar still showed the filter.

Now an existing button is focused directly, without a refresh, and a
refresh reapplies an active search filter.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 11:00:00 +02:00
Henrik RydgårdandClaude Opus 5.5 43704b215c Game browser: Keyboard focus for the info button, more left padding
In the large list, right and left move between a game and its info
button, so up and down still step from game to game.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 10:45:12 +02:00
Henrik RydgårdandClaude Opus 5.5 7d273e178f Game browser: Info button in the large list, long press with buttons
Each line in the large list gets an info button, doing the same as a long
press or right click.

Holding the accept button now works as a long press in all view modes,
so it can be done from a gamepad.

Rename "Grid icon size" to "Icon size", since it now also applies to the
large list.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 10:33:04 +02:00
Henrik RydgårdandClaude Opus 5.5 0066599f9a Game browser: Add an XMB-style large list mode
- Fixes #22202

A third view mode next to grid and list: a list with full size icons,
scaled by the grid icon size setting. Like the XMB, the selected (or
hovered) game plays its ICON1.PMF in place of the icon.

The per-tab grid bools become GameBrowserView1-4 ints. The old GridView
keys are still read, to pick the default, but no longer saved.

The PMF decoding moved out of GameScreen's PMFView into a shared
PMFVideoTexture.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 10:24:32 +02:00
Henrik RydgårdandClaude Opus 5.5 a361dfc490 Drop unused Config.h and SmallDataConvert.h includes
Config.h is edited about 100 times a year and each edit recompiled 198
files; now 172. SmallDataConvert.h pulls in arm_neon.h and was included by
headers that don't use it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 12:13:42 +02:00
Henrik RydgårdandClaude Opus 5.5 7315c0392c Games tab: Hide the browse button where there's no folder browser (tvOS)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:03:37 +02:00
Henrik RydgårdandClaude Opus 5.5 671b6ce397 Type-to-search: Backspace removes a whole UTF-8 character, ignore § and other Latin-1 symbols
Backspace popped a single byte, leaving half of a multi-byte character behind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:30:32 +02:00
Henrik RydgårdandClaude Opus 5.5 866cf89b65 Make the resized flag atomic
On Android it's set on the Java UI thread right after writing g_display,
and read on the render thread, which then copies the dp size into the UI
bounds just once. With a plain bool the render thread could see the flag
before the new size.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 17:22:41 +02:00
Henrik RydgårdandClaude Opus 5.5 82ae32d985 GameScreen: Return to the main screen properly after removing a game
"Remove From Recent" and "Delete Game" called switchScreen(new MainScreen)
from a popup, which only replaces the top screen, so the old MainScreen
and the GameScreen of the removed game stayed in the stack underneath.

Close the GameScreen instead once the popups above it are gone, and have
MainScreen refresh its browsers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:16:11 +02:00
Henrik RydgårdandClaude Opus 5.5 bd992e2f17 SoundEffectMixer: Hold the lock while mixing
UpdateSample() can replace and free a sample that Mix() is reading on the
audio thread, such as when changing the achievement sound while
previewing it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:32:59 +02:00
Henrik RydgårdandClaude Opus 5.5 12ec7478b2 Memstick: Ignore the back key while moving data
The Back choice is hidden during the move, but the key still closed the
screen. The destructor then blocked the UI thread until the move was
done, and FinishFolderMove() never ran, leaving the config pointing at
the old, now emptied folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:32:59 +02:00
Henrik RydgårdandClaude Opus 5.5 8a4d53996f UI: Fix stale and null search view pointers in tabbed screens
noSearchResults_ and clearSearchChoice_ only exist with the search tab,
which depends on orientation, and were never reset. Rotating with a
filter set wrote into the deleted views, and GAMESETTINGS_SEARCH, which
goes to every screen in the stack, hit null ones on screens without
search controls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:32:49 +02:00
Henrik RydgårdandClaude Opus 5.5 27899cc875 UI: Give views in lazily created tabs the views requester token
GetRequesterToken() only returns the views token inside CreateViews(),
but tabbed screens create every tab other than the first on demand, and
the persist restore after CreateViews() can create one too. So text
inputs and file choosers there (Networking tab nickname, search filter,
RemoteISO and achievement settings) registered their [this] callbacks
under the screen token, which a recreate doesn't forget. Open the native
input box, rotate, press OK, and the callback wrote through the deleted
view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:32:49 +02:00
Henrik RydgårdandClaude Opus 5.5 88018255c2 Android: Don't read the screen stack from the UI thread on Back
NativeIsAtTopLevel() made a virtual call on the top screen from the Java
UI thread, while the render thread could be deleting it. Two quick Back
presses could hit that. Cache the flag in ScreenManager::Update()
instead, like passInputToMapper_ (now atomic too).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:32:29 +02:00
Henrik Rydgård 6b203f050d Merge pull request #22521 from hrydgard/savedata-zip-root
Install savedata zips that contain a single save folder's files in the root
2026-10-12 13:58:02 +02:00
Henrik Rydgård 8d8009840e Merge pull request #22511 from hrydgard/android-inputbox-fixes
Claude code review: Android inputbox fixes
2026-10-12 13:20:25 +02:00
Henrik RydgårdandClaude Opus 5.5 abeb890d0f Install savedata zips that contain a single save folder's files in the root
Some shared saves are zipped without their folder, with the zip named after it
instead (ULUS10019000.zip). Detect these by a root PARAM.SFO with a
SAVEDATA_DIRECTORY, which holds the folder name (game ID + save name), and
extract into that folder.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 12:27:24 +02:00
Henrik Rydgård 53047f7cab Merge pull request #22510 from hrydgard/misc-improvements
Misc compat flag updates
2026-10-12 10:25:35 +02:00
Henrik RydgårdandClaude Opus 5.5 0d032fa2ee Windows: Implement System_ShareFile as a Save As dialog
Win32 has no share sheet hookup yet, so sharing a file offers to save a
copy of it. ShareFilesAsZip no longer needs an app cache directory, which
Windows doesn't set; it falls back to the memstick cache folder through
DIRECTORY_APP_CACHE. The save dialog now asks before overwriting.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-11 21:52:38 +02:00
Henrik RydgårdandClaude Opus 5.5 78f389bd80 Close the file used to detect a background image's format
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:37:20 +02:00
Henrik Rydgård ed48dd53fa Merge pull request #22504 from hrydgard/sdl-wayland-text-input-fallback
Fix text input in the ImDebugger on Linux SDL
2026-10-11 18:51:33 +02:00
Henrik RydgårdandClaude Opus 5.5 297acd3026 ImDebugger: Let the toggle key through while imgui has the keyboard
Only EmuScreen and PauseScreen let it past imgui's keyboard capture, so on
other screens the debugger couldn't be closed by key while a field had focus.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-11 18:14:59 +02:00
Henrik RydgårdandClaude Opus 5.5 b4d5d53b8a ImDebugger: Enable text input while an imgui text field is active
Since db8ff43, a leftover local shadowed lastImguiEnabled_ in runImDebugger,
so TEXT_GOTFOCUS was never sent and SDL never started text input for imgui.
Drive it from io.WantTextInput instead, so it's only on while editing.

The regular UI and the debugger now say independently whether they want text
input, and the platform only gets TEXT_LOSTFOCUS once neither does, so leaving
an imgui field doesn't break type-to-search on the screen underneath.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-11 18:08:00 +02:00
Henrik RydgårdandClaude Opus 5.5 9741bcacd9 iOS: Apply size changes between frames, fixing a glitch when rotating
UIKit lays out at the new size from the main thread, often while a frame
is being drawn, and the swapchain was only resized after presenting. So
the first frame of a rotation was laid out for one size and drawn at the
other. The view controller now hands the new size to the render thread,
and NativeFrame resizes before drawing instead of after presenting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 17:40:01 +02:00
Henrik RydgårdandClaude Opus 5.5 5704b972e7 iOS: Remove OpenGL support from the app
The app now always uses the Metal view controller with Vulkan (MoltenVK),
for both the App Store and sideload builds. The GL view controller is gone,
and Common/GPU/OpenGL (except GLFeatures, used by the shader generators) and
GPU/GLES are no longer compiled for it. PPSSPP_API_ANY_GL is now off for
all of iOS except the libretro core, which still uses GLES.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 16:13:28 +02:00
Henrik Rydgård f70df399ab Merge pull request #22494 from hrydgard/jit-shadow-block-map
JIT shadow block map: Keep JIT block entries and replacement hooks out of PSP memory
2026-10-11 12:46:42 +02:00
Henrik Rydgård 7572ac05ca Screenshot code cleanup, fix issue where the notification would be in a second fast screenshot
Fixes #22497
2026-10-11 10:56:43 +02:00
Henrik RydgårdandClaude Opus 5.5 0a8ec4d8f1 Invalidate code that HLE and the debugger write over
Helper thread stubs, fake syscall stubs and the module start trampoline go into memory that may
have held code (freed kernel memory, a reused thread stack), and the debugger memory views can
edit code. Invalidate what they write, which so far only happened by accident when the write hit
the first instruction of a JIT block.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-11 10:33:30 +02:00
Henrik RydgårdandClaude Opus 5.5 3656fb46e2 Windows: Capture the microphone through WASAPI instead of Media Foundation
Windows now uses the same host interface as SDL and iOS: sceUsbMic sends
startRecording/stopRecording/deviceChanged, and drains buffered input on
the CPU thread with pollRecording. A capture thread asks WASAPI for mono
16-bit at the game's rate (it converts from the mix format, so no more
ffmpeg resampling), and copies packets into a lock-free ring buffer.
It reopens the device when the selection changes, and retries once a
second if the device is missing or gets unplugged.

The device list comes from the active capture endpoints. Their friendly
names are the ones Media Foundation reported, so existing MicDevice
settings still match. An empty setting, now selectable as Auto like on
SDL, means the default capture device.

The Media Foundation audio capture code is removed; the camera still
uses it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 18:28:33 +02:00
Henrik Rydgård 7b716e6f33 Merge pull request #22459 from chriopter/sdl-microphone
SDL: Add microphone capture and device selection
2026-10-10 17:01:04 +02:00
Henrik RydgårdandClaude Opus 5.5 b9a706432a Add ShareFilesAsZip, for sharing several files as one zip
Zips the given files (content:// paths included) into a folder of their own
in the app's cache and offers the zip through System_ShareFile. The receiving
app reads it whenever it likes, so it can't be deleted right away: each share
deletes the folders of earlier shares once they're an hour old.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 16:06:55 +02:00
Henrik RydgårdandClaude Opus 5.5 834c3f00ee Android: Replace OpenSL ES audio with Oboe
Oboe uses AAudio on Android 8.1+ and falls back to OpenSL ES on older
devices. Output and microphone input both go through it. The mic now gets
resampled by Oboe from the device's rate to whatever the game asks for.

New: when a stream is disconnected (headphones unplugged, Bluetooth device
going away), it's reopened on the new default device instead of going
silent.

Oboe 1.11.0 is added as a submodule, built through ext/oboe-build for CMake
and as a module in Android.mk.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 12:13:58 +02:00
Henrik Rydgård 06fbbf1218 Merge pull request #22471 from hrydgard/parallel-loop-max-threads
Allow specifying a cap on the number of threads used in ParallelLoop
2026-10-09 15:38:09 +02:00
Henrik Rydgård 831acb099e Allow specifying a cap on the number of threads used in ParallelLoop 2026-10-09 14:33:58 +02:00
Henrik Rydgård 1862efe392 Add a bindable key to create frame dumps 2026-10-09 13:26:22 +02:00
Chriopter 1670f5d1f9 SDL: Add microphone recording and device selection. 2026-10-09 00:18:31 +02:00
Henrik RydgårdandClaude Fable 5.1 d0e45b94d9 Android: Handle rotation and window resizing without recreating the activity
Every rotation, fold or window resize destroyed the activity and with it
all of graphics, then built it all up again. Declare those config changes
handled, so they arrive as a surfaceChanged and go through the same resize
path as a desktop window resize.

That path needed three things it didn't have on Android:

- The GPU_DISPLAY_RESIZED message, left out for Android since 2020 when
  DeviceRestore covered every size change.
- A fixed (hardware scaled) surface size is now recomputed on each in-place
  surface change, since surfaceCreated no longer runs on a rotation.
- A 180 degree flip keeps the size but changes the surface transform, so
  the display rotation is passed along and a change in it is a resize too.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-08 21:17:49 +02:00
Henrik RydgårdandClaude Opus 4.8 ffc0a274a6 Achievements: Use a 256-byte rich presence buffer to avoid an rcheevos over-read
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 932d1e3b36 IconCache: Expire only avatars after a day, other icons after 30 days
Achievement badges and game icons don't change, so re-downloading them
daily was wasted. InsertIcon now takes a max age, and each entry saves
its expiry time. Leaderboard avatars get a day, everything else 30 days.
Bumps the cache version.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 bfdba164e3 Store: Remove HttpImageFileView's unused non-icon-cache path
Nothing constructs the view with useIconCache = false, and the path was
broken anyway: download_ was never assigned, so it started a new download
every frame, and the destructor couldn't cancel a callback that captured
this.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 e628fe3cb2 Achievements: Fix leaderboard screen use-after-free on close
rc_client frees a request's async handle right after calling back. The
error path didn't clear pendingAsyncCall_, so closing the screen after a
failed fetch aborted a freed handle. Switching between Top players and
Around me also overwrote the handle without aborting the old request,
which could then call back into a closed screen, or leak an entry list.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 c8b32dda0a Achievements: Keep a shut-down client alive until its requests finish
rc_client keeps raw pointers to itself in the callback data of award,
leaderboard submit and ping requests, so destroying it with one in flight
(disabling achievements mid-game) had the late callback write to freed
memory. Count requests per client, retire a busy client instead of
destroying it, and destroy it when its last request completes.

Request timeouts in naett are per operation and the plain HTTP client has
none for the body, so a retired client is also destroyed after 60 seconds
regardless. Its late callbacks are then dropped, leaking their data.
Clients are tracked by ID so a new client at a reused address can't get an
old one's callbacks. At app exit, pending requests are cancelled without
callbacks, so everything is destroyed immediately.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 10:26:00 -06:00
Henrik RydgårdandClaude Opus 5.5 3aaea4c0f9 GameInfoCache: Prioritize loads, so launching doesn't wait behind search
Type-to-search asks for the title of every game in the list, queueing a
load for each, and launching a game whose info wasn't loaded yet then
blocked until the whole queue had drained. Search's loads are now LOW,
and launching asks at HIGH, which queues its own load rather than wait
for a pending one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 16:34:38 -06:00
Henrik RydgårdandClaude Opus 5.5 e108e41675 GPU: Fix assorted leaks, null derefs and small rendering bugs
- Put the anisotropy level in the sampler key, so changing it applies on
  Vulkan and D3D11.
- Release CLUT textures at shutdown on GLES and D3D11.
- Fix the depth readback viewport, which squeezed the image whenever the
  read rectangle was smaller than the fbo.
- Test the computed depth, not the unset result, in the equal-depth clear
  check.
- Don't read back a CLUT from a framebuffer without an fbo.
- Tolerate null entries when releasing post-shader objects and CLUT
  textures after a failed creation.
- ImGe: Don't crash on a framebuffer without an fbo, or on GetVFB under the
  software renderer.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 10:33:32 -06:00
Henrik Rydgård d3ab52b4b3 Buildfix 2026-09-28 17:05:44 -06:00