Commit Graph
1303 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 9be1d223b6 Remove MoltenVK: Metal is the backend on iOS, and the default on Macs
The iOS and tvOS apps no longer link the static MoltenVK (the
ios/MoltenVK submodule is gone), so Vulkan can't load there and Metal is
the only backend. Without the static case, Vulkan's functions are now
always loaded at runtime (PPSSPP_VK_STATIC is gone).

The Mac app no longer bundles libMoltenVK.dylib (ext/vulkan/macOS is
gone). Metal is the default on Apple Silicon (Intel Macs stay on
OpenGL), but Vulkan still works with a separately installed MoltenVK,
the Vulkan SDK's or Homebrew's, which is useful for comparisons. A saved
Vulkan setting falls back to the default when there's none.

The libretro cores are unchanged: they get MoltenVK from the frontend.

frametests.py's --ios and --adb default to Metal on a Mac host.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 14:58:38 +02:00
Henrik RydgårdandClaude Opus 5.5 b2fc4a80fe Metal: Leave the backend out of the libretro cores
They get their graphics context from the frontend, so they compiled and
linked the Metal backend without being able to use it. Adds
PPSSPP_API_METAL, like PPSSPP_API_D3D11, for the code that only exists
with it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 12:05:14 +02:00
Henrik RydgårdandClaude Opus 5.5 27edb50409 Config: Don't reset a saved Metal backend to the default
The range check predates GPUBackend::METAL (4), so the setting was lost
on every load, and the app came back up on Vulkan.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 12:02:22 +02:00
Henrik RydgårdandClaude Opus 5.5 16ed2ad55a Metal: Add a thin3d backend (WIP, not hooked up yet)
thin3d on Metal, plus a small render manager that owns frames, command
buffers, lazily started render passes and a per-frame push buffer.

Shaders are the same Vulkan GLSL the Vulkan backend gets, translated to
MSL through glslang and SPIRV-Cross, with the Vulkan binding numbers as
Metal buffer/texture indices. flip_vert_y makes Metal's clip space match
Vulkan's, so everything else follows the Vulkan conventions.

Adds GPUBackend::METAL (4) and builds the files on Apple platforms. Not
yet selectable: the SDL window setup, the UI choice and the GPU core
come next.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 12:02:22 +02:00
Henrik RydgårdandClaude Opus 5.5 ab94767522 VFPU: Drop the inaccurate dot product paths
- Fixes #12082

The bit-exact VFPU dot product is the default everywhere and fast enough,
so the plain multiply-add paths in the interpreter and the IR frontend go,
along with the AccurateVdot setting, --accurate-vdot, the ForceAccurateVdot
compat flag and the Vec4Dot IR op, which nothing emits any more.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 12:11:46 +02:00
Henrik RydgårdandClaude Opus 5.5 57601a9d3b Game browser: Give Recent the toolbar, and the large list by default
Recent gets the view mode and grid settings buttons. It has no path,
nothing to navigate, and its list comes from memory, so the path,
navigation and refresh stay out. Its old grid setting is no longer
migrated, like Games and Homebrew.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 12:32:42 +02:00
Henrik Rydgård 0a9b57371f Delete the spline quality setting 2026-10-16 13:27:26 +02:00
Henrik Rydgård f5255eefaf Move the Hardware Transform setting to developer tools, reset by renaming the key.
This setting should always be on, not having it ruins performance.
2026-10-16 13:27:23 +02:00
Henrik RydgårdandClaude Opus 5.5 0e77a2d1cd VFPU: Make AccurateVdot the default
The accurate dot products cost a few percent at most in the IR JIT, apart
from GTA (about 20% on a game that's cheap to run anyway). The fuzzer follows
the default too, unless PPSSPP_CPUFUZZ_ACCURATE_VDOT=0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:37 +02:00
Henrik RydgårdandClaude Opus 5.5 1952d20805 Config: Add AccurateVdot, and --accurate-vdot to set it
Not wired to anything yet. It will make every core compute the VFPU's dot
products (vdot, vmmul, vtfm and the rest) bit-exactly like the PSP, through
vfpu_dot().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:36 +02:00
Henrik Rydgård 4c2bb35630 Merge pull request #22564 from hrydgard/arm32-ir-jit
ARM32: Replace the legacy JIT with an IR-based one
2026-10-14 19:18:54 +02:00
Henrik RydgårdandClaude Opus 5.5 edef36d97e Load game patches installed on a PSP, given its Fuse ID
- Fixes #12343

Killzone: Liberation's Chapter 5 DLC is an installer that the PSP turns
into ms0:/PSP/GAME/<id>/KZL.PRX, which the game loads with
sceKernelLoadModuleDNAS. That file is a PGD around a type 3 PRX (decrypt
mode 18), both keyed to the console that installed it. Its Fuse ID
gives everything needed:

- libkirk: the per-console key derivation, and KIRK commands 3, 5 and 8
  built on it (KIRK ROM per uofw, key mesh per psdevwiki).
- PrxDecrypter: type 3, which is type 5 with the first step through
  KIRK command 3 (JPCSP's PRX.java), and the DNAS PGD unwrap.
- sceKernelLoadModuleDNAS uses the new FuseID setting (or --fuse-id).
  Without one, or with the wrong one, the game falls back to its stock
  module and an OSD message says why.
- Headless --re-decrypt takes --re-decrypt-key and --fuse-id, to decrypt
  such a file offline.

Verified with a patch installed on a real PSP: the v1.20 module loads,
starts and reads CHAPTER5.BIN. Type 5 output is unchanged (an NPJH50521
PBOOT.PBP decrypts byte-identically). How to install one over PSPLink is
in docs/dnas-patches.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 18:10:08 +02:00
Henrik RydgårdandClaude Opus 5.5 74703b031e Remove the legacy ARM32 JIT
The IR-based one replaces it. With that, every native JIT is IR-based, which the JIT viewer and
the settings' comments now assume. The ARM emitter test loses its part that drove the old FPU
register cache.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 17:32:53 +02:00
Henrik RydgårdandClaude Opus 5.5 66d7975e7f Remove the legacy (non-IR) x86-64 and ARM64 JITs
Their IR-based replacements stay. The JIT core now creates the IR JIT on both, so "JIT using
IR" is the same as "JIT" on every architecture (ARM32 still uses its legacy JIT for both). The
settings no longer offer it, a saved JIT_IR loads as JIT, and the JIT harness and CPUEquivalence
fuzzer drop the duplicate run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 14:39:45 +02:00
Henrik Rydgård 4e442b22b2 Merge pull request #22559 from hrydgard/game-browser-xmb-list
Game browser: Add a more XMB-like list format, make default
2026-10-14 14:04:34 +02:00
Henrik RydgårdandClaude Opus 5.5 754e49c6d6 Game browser: Switch existing installs to the large list on Games and Homebrew
Their old grid setting is no longer migrated, so everyone gets the new
view there. Recent and Remote still keep theirs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 11:12:00 +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 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 4f47475a69 Headless: Support --appendconfig
Merges the settings in an ini file over headless's own defaults, for runs that
need something like JitDisableFlags. Unlike in the app, the result is never
saved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:26:29 +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 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 a89fdb2c9a SoftGPU: Remove the pixel and sampler JITs
The C++ paths draw and sample four pixels at a time in vector lanes,
while a JIT function only does one, and with a JIT function in use the
span and quad paths were skipped. On x86 the JITs had become slower:
Wipeout took 13% more wall time and 25% more CPU with them, God of War
3% more. They were also a second implementation of every GE rule, and
ARM never had them.

The SoftwareRendererJit setting goes with them. RasterizerRegCache.h
keeps only the types the pixel and sampler functions take, as
RasterizerTypes.h.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 13:44:48 +02:00
Chriopter 1670f5d1f9 SDL: Add microphone recording and device selection. 2026-10-09 00:18:31 +02:00
Henrik Rydgård 2fe24d1182 Add warning if you run the 32-bit version on 64-bit window. 2026-09-22 10:04:31 -06:00
Henrik RydgårdandClaude Opus 5 ad06cbe2c4 Auto-install firmware from the game disc on boot
Most UMDs carry a firmware updater, and having a real firmware in the NAND is
what the LLE modules want. On boot, if the disc's updater is newer than what's
installed - or nothing identifiable is installed, which is what a fonts-only
NAND looks like - unpack it, with a progress bar on the OSD. Controlled by
bAutoUpgradeFirmware, on by default, with a checkbox on the firmware screen.
Off in headless, which shouldn't rewrite the NAND during a test run.

The install itself is now shared with the install screen, and hardened, since
it can run without anyone watching:

- It stages into <NAND>/install-staging and only erases the installed firmware
  once the new one is complete on disk, so a failure leaves what's there alone.
- A single entry that didn't unpack fails the whole install. A firmware with
  holes still looks installed, so nothing would ever replace it.
- A truncated archive is rejected instead of unpacking to half a firmware that
  every stat reports as a clean install. The PSAR header records the length;
  it was being clamped to the buffer rather than checked against it.

Also falls back to the version in the archive's own header when the PARAM.SFO
next to the updater is unreadable, which it is on a fair number of discs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 15:52:53 -06:00
Henrik RydgårdandClaude Opus 5 fbdf611fc4 Chat: keep more lines of history, and add timestamps
The log was trimmed to 50 lines, which isn't enough to scroll back
through a conversation - now 250. Chat entries also carry the time they
arrived, shown as a dimmed HH:MM in front of the name, behind a new
"Show timestamps in chat" setting.

The timestamp is kept next to the text rather than baked into it, since
the chat view finds the sender by splitting the line at the first colon.

Fixes #15444

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
2026-09-04 13:10:54 -06:00
Henrik RydgårdandClaude Opus 5 6bb91bf2f0 Remove the "Up to 2" buffered frames option
Three frames in flight showed no performance benefit over two, so drop
the option and clamp existing configs (and the default) down to 2.
The now-unused "Up to 2" translation keys are left in place.

Fixes #21419

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
2026-09-04 13:08:21 -06:00
Henrik RydgårdandClaude Opus 5 375fa0fc11 Misc correctness fixes
GetStringErrorMsg had the strerror_r result test backwards. The XSI variant returns
0 on success, so every successful lookup returned "Unknown error"; and under glibc
with _GNU_SOURCE the GNU variant is selected instead, which returns the message by
pointer and typically leaves the buffer untouched, so it returned an empty string.
Either way GetLastErrorMsg() was useless on Linux, Android and macOS. Pick the right
handling by overload resolution rather than guessing which signature we got.

KeyMap's "no gamepad button mapped to cancel" fallback pushed into confirmKeys
instead of cancelKeys - and pushed the confirm button. So unmapping cancel left no
gamepad way out of menus, and duplicated an entry in the confirm list.

ControlMapper::AddListener mutated listeners_ without taking mutex_, while
RemoveListener takes it and the input thread iterates the vector under it. Opening a
screen while an axis is moving could reallocate it mid-iteration. The comment about
piggybacking on a screenmanager mutex was stale - there isn't one.

Config's two std::stof calls on PostShaderSetting values ran on user-editable ini
text with no try/catch, so a malformed entry called std::terminate during startup
config load. Use the same checked sscanf that LoadGameConfig already uses.
(CmdLine.cpp and Compatibility.cpp have the same pattern; not touched here.)

The screenshot downscale path leaked its final buffer on every downscaled shot,
which savestate thumbnails hit on every save at 3x and above.

HandleUploadPost is registered unconditionally, so closing the Upload screen left an
unauthenticated file-write endpoint live for as long as anything else kept the server
up. Check the flag in the handler.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCPmm7FoQUoqrbMdhfqhQ2
2026-08-31 01:19:06 +02:00
Henrik RydgårdandClaude Opus 5 bd505b7f1c Interpreter: implement the FPU divide-by-zero exception
div.s now maintains fcr31's Cause.Z and (when the trap is masked) sticky
Flag.Z bits, in the standard MIPS bit positions. Only a finite non-zero
dividend counts, so 0/0, inf/0 and NaN operands are excluded per IEEE 754.

When the guest has the trap unmasked, the new Core_FPUException() reports it
with the usual module suffix and MIPS call stack, and fd is left unwritten as
hardware would. That's gated behind a new developer setting, off by default:
PSP threads start with fcr31 = 0x00000e00, i.e. three of the traps already
enabled, and games divide by zero without meaning anything by it. The fcr31
bits are updated either way, so what the game reads back doesn't depend on
the setting.

Interpreter only - the JITs are unchanged, and none of this is reachable
under them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R9fKXvYBrnqtp1QQGaGWVv
2026-08-29 23:40:48 +02:00
Henrik RydgårdandClaude Sonnet 5 29a38af37e Per-module symbol save/load, module identity via crc, GetModuleIndex fix
SymbolMap:
- Fix GetModuleIndex(): it only checked the end of an active module's range
  (via activeModuleEnds.upper_bound), never the start, so an address sitting
  in the gap before a module was silently misattributed to it. Added
  GetModuleIndexByName() as a companion lookup.
- AddModule() gains an optional crc param, stored per ModuleEntry. Reactivating
  a module by name now also requires the crc to agree when both sides know it,
  so two unrelated binaries that happen to share a name no longer get merged
  into one symbol table (addresses the old TODO at the top of SymbolMap.h).
- AddLabel()/AddFunction() gain an updateName param (default false, preserving
  existing "first writer wins" behavior) so a trusted source - like a loaded
  symbol file - can be allowed to overwrite a name that a lower-confidence
  automatic pass already assigned.
- New SaveModuleSymbols()/LoadModuleSymbols()/GetModuleSymbolsPath(): save or
  restore one module's functions/data/labels to/from a small human-editable
  text file, addressed relative to the module (so the file stays valid however
  the module ends up positioned on a later run). Keyed by
  PSP/SYSTEM/SYMBOLS/<moduleName>_<crc>.ppsym - deliberately by module+crc
  rather than by game, so it's shared by every game/homebrew that loads the
  exact same module. A "# game <id> <title>" comment records who last saved
  it, informational only.

WebSocket debugger: hle.module.saveSymbols/loadSymbols expose the above.

sceKernelModule.cpp: auto-load a module's saved symbols right after it's
registered with the symbol map (both the real ELF-load path and the
savestate-load path), and auto-save on unload (before UnloadModule(), while
its symbols are still active) - gated behind the new bAutoSaveLoadSymbols
config setting (default off), with a matching Developer Tools checkbox and
a --auto-save-load-symbols command-line override for headless use.

Includes some in-progress cleanup already staged: DescribeAddress now calls
g_symbolMap->GetDescription() directly instead of through the now-removed
MIPSDebugInterface::getDescription() wrapper.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-17 16:01:23 +02:00
Henrik Rydgård fbfcb8925e Merge pull request #22099 from n00mkrad/softgpu-dither-opt
Allow disabling dithering when using software rendering
2026-08-17 12:47:57 +02:00
nmkd 8e9a8b8d76 Allow disabling dithering when using software rendering 2026-08-16 15:27:41 +02:00
Henrik Rydgård 5cffcd34ad Get rid of the confusing old USING_WIN_UI define. Make a more clear system property for headless. 2026-08-16 12:19:41 +02:00
Henrik Rydgård abb57c620f Adjust some log levels 2026-08-09 22:10:54 +02:00
Henrik RydgårdandClaude Sonnet 5 dcf742edb4 Dsable AndroidHwScale by default
AndroidHwScale defaults to 0 instead of the old device/resolution-based heuristic (which is
removed along with DefaultAndroidHwScale()).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L4QAoxV2KY7ek4PcZw3WvY

...
2026-08-09 19:03:08 +02:00
Henrik Rydgård 8cd7e1b2c0 Delete all support for Qt
Our Qt backend has long been left behind and doesn't even support Vulkan
currently. There would be a lot of work to make it viable, and I don't
think anyone is really interested.

ImGui on SDL will soon fulfill the need for a more classic user interface
with a menu bar on Linux, and on Mac we already have a native UI.
2026-08-08 18:18:28 +02:00
Henrik Rydgård 25532a9b64 Fix build error in iOS app store build. Also fix a log error. 2026-08-07 18:43:29 +02:00
Henrik Rydgård 092ab42fe7 Clean up ugly usage of the g_nativeLibDir global. Now it's local in VulkanLoader. 2026-08-06 18:12:04 +02:00
Henrik Rydgård 60fc887306 Clean up Config::PostLoadCleanup, reject disabled GPU backends 2026-08-06 17:45:37 +02:00
Henrik Rydgård db30fabf03 Add a setting (defaulting to false) for enabling file handler plugins 2026-08-03 11:24:36 +02:00
Henrik Rydgård 683704d61d Add new log category for config 2026-07-30 10:03:15 +02:00
Henrik Rydgård 5ef736f6a7 More command line improvements 2026-07-27 18:37:28 +02:00
Henrik Rydgård a886cfb5ab First step of centralizing command line parsing 2026-07-20 12:02:07 +02:00
Henrik Rydgård 993c3a9c67 Avoid accurately computing disk space on iOS and Android (where it can be slow). Add a setting. 2026-07-14 22:22:29 +02:00
Henrik Rydgård 61e1ef8f7a Remove the "Software skinning" option. Now always on. 2026-07-14 17:02:57 +02:00
Henrik Rydgård 5f7281bd8e Remove old vestiges of geometry shader support 2026-07-08 18:25:08 +02:00
Henrik Rydgård 623545bd24 Delete the "Hardware tessellation" feature.
Very hard to maintain and debug, not worth it.
2026-06-16 16:17:14 +02:00
Henrik Rydgård 5265422c0e Remove the old "Fragment ubershader" setting. It's been on by default for years and is not really an ubershader. 2026-06-10 09:54:52 +02:00
Henrik Rydgård 36bdde68f9 Delete the "Lazy texture cache" option 2026-06-09 23:49:54 +02:00
jasaaved 95006cf1d3 Changed bFullScreenExclusive to bAllowFullScreenExclusive
There's no guarantee VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT will enter Fullscreen exclusive (FSE). Under the right conditions, the driver and/or DWM can grant FSE. Adding "allow" to the FSE setting should make this a bit clearer.
2026-06-04 12:54:52 -07:00