Commit Graph
50719 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 a92bd2cd9f Reporting: Send the OS, device model and disc format, and the HLE flags
Renames played_seconds to seconds_played. On SDL, the OS build is now
uname's sysname and release on Linux and Mac.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 11:26:55 +01:00
Henrik RydgårdandClaude Opus 5.5 c0a419ab32 Reporting: Send played_seconds and the installed firmware version
Ticks don't measure time played, since games change the CPU clock.
played_seconds is emulated time. ticks is still sent for now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 11:19:24 +01:00
Henrik Rydgård 34372307c1 Merge pull request #23045 from cscd98/libretro-vr-vulkan
libretro: support Vulkan stereo and immersive VR
2026-11-12 10:33:31 +01:00
Henrik Rydgård b06020936e Merge pull request #23047 from hrydgard/gles-fetch-output-readback
Adreno 5xx: Work around framebuffer fetch (GL) and light ubershader (Vulkan) driver bugs
2026-11-12 10:17:41 +01:00
Henrik Rydgård 4efc94341a Merge pull request #23048 from Narugakuruga/patch-41
Fix firmware version detection in update screen
2026-11-12 10:16:36 +01:00
Narugakuruga 0ec82a7bf4 Fix firmware version detection and NAND erased
Load the PARAM.SFO before pushing the installer — the same g_gameInfoCache pattern the game list already uses for update PBPs — and pass info->GetTitle(). --By MIMO v2.6 Pro
2026-11-12 15:43:36 +08:00
Henrik RydgårdandClaude Opus 5.5 e72dfa1006 Vulkan: Don't use the light ubershader on Adreno 5xx
On an Adreno 506 (Vulkan 1.0.20 driver, Redmi Note 4), the ubershader's
loop over the lights gives wrong lighting: LittleBigPlanet's Sackboy and
lit scenery came out pale. The per-light shaders render it right. Uses
the existing UNIFORM_INDEXING_BROKEN flag, set so far for old Mali.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 23:58:33 +01:00
Henrik RydgårdandClaude Opus 5.5 4a98ebba11 GLES: Don't use framebuffer fetch on Adreno 5xx
On an Adreno 506 (driver V@145, Redmi Note 4), fetch can return black for
pixels an earlier draw in the same render pass wrote, which showed up as
dark noise on LittleBigPlanet's foliage. Framebuffer copies render it
correctly, and that frame needs only a few of them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 23:52:20 +01:00
Henrik RydgårdandClaude Opus 5.5 15e4c378fb GLES: Don't read back fragColor0 when it's the framebuffer fetch inout
With EXT_shader_framebuffer_fetch, fragColor0 is inout. On Adreno 506
(driver V@145, Redmi Note 4), reading it back after writing it gives the
wrong value: the color write mask path packs it and LittleBigPlanet's
objects drew solid black. Build the color in a local and write the output
once at the end.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 23:37:19 +01:00
Craig Carnell 8638b091c7 libretro: Support Vulkan stereo and immersive VR
Present multiview game framebuffer layers as frontend stereo views, sharing the tracked cylinder camera with OpenGL. Resize presentation images before drawing when VR changes.

Recreate cached Vulkan backbuffers after GPU device-loss handling so frontend resets and resolution changes cannot start duplicate rendering threads.
2026-11-11 21:29:08 +00:00
Henrik Rydgård 1a6d0c1ff0 Merge pull request #23043 from hrydgard/fix-core-filters
Fix the broken Core.vcxproj.filters, and check the filters files on CI
2026-11-11 22:02:21 +01:00
Henrik Rydgård 2a36fcdea9 Merge pull request #23044 from hrydgard/report-game-crashes
Report game crashes to the report server
2026-11-11 21:09:41 +01:00
Henrik Rydgård b9b12d0ccc Merge pull request #23042 from hrydgard/ui-changes
Zip import fixes, busy save slots in the pause menu
2026-11-11 21:08:50 +01:00
Henrik RydgårdandClaude Opus 5.5 539bfb95fd Keep the stack trace for bad jumps and break instructions
The crash screen and crash reports read it from the exception info,
which only memory, FPU and HLE errors filled in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:12:25 +01:00
Henrik RydgårdandClaude Opus 5.5 ad48b5389b Translate the crash report strings
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:11:17 +01:00
Henrik RydgårdandClaude Opus 5.5 692556599f Report game crashes to the report server
When reporting is enabled, a crash is sent as a report message when the
crash screen first shows it. The message is a template per exception
type, so the server groups crashes of the same kind, and the value has
the details and the MIPS stack trace.

When reporting is off, the crash screen gets a "Report crash" button
that sends the same report once, to report.ppsspp.org. Like the
compatibility reports, it isn't offered when cheats, plugins or other
settings that make reports unreliable are in use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 17:34:10 +01:00
Henrik RydgårdandClaude Opus 5.5 605935d38f Add a check for the .vcxproj.filters files, and run it on CI
A broken filters file still parses and MSBuild ignores it, so the build
stays green while Visual Studio's folder tree falls apart. The check
catches nested items, undefined filters, duplicates and items that the
filters file and the project disagree on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 16:55:17 +01:00
Henrik RydgårdandClaude Opus 5.5 beed2536a7 UWP: Fix stale entries in the filters files
ui_images used a forward slash in an undefined filter, KL4E.h, upload and
packages.config were missing, and two atlas entries were for files the
project no longer lists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 16:55:17 +01:00
Henrik RydgårdandClaude Opus 5.5 d5c14e8cf1 Fix Core.vcxproj.filters, broken by the network simulation commit
AdhocTransportNetSim.cpp's entry was nested inside AdhocTransportRelay.cpp's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 16:36:38 +01:00
Henrik Rydgård 87d7e00285 Merge pull request #23041 from hrydgard/profiler-timeline
Profiler: Replace with a per-thread timeline profiler, compiled into every build
2026-11-11 14:32:33 +01:00
Henrik RydgårdandClaude Opus 5.5 42c6c4420b Pause menu: Show a slot as busy while its save is being written
On a slow device, pausing again right after saving a state could show
the slot's Save and Load buttons enabled while the save was still being
written. The slot now has its buttons and screenshot disabled, with a
spinner, until the save ends, and the menu refreshes then.

The refresh message is now posted when a save ends any way (written,
failed or refused), after it has left the pending list, so the refresh
can't still see it as pending.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 14:22:33 +01:00
Henrik Rydgård 562f22a60f Texture replacer: Don't complain about incompatible filenames on mobile 2026-11-11 14:22:33 +01:00
Henrik RydgårdandClaude Opus 5.5 e433aba891 Translate the savedata Import string
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 14:22:33 +01:00
Henrik RydgårdandClaude Opus 5.5 35dc169920 Zip install: Say "Import" on the button for saves and savestates
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 14:22:13 +01:00
Henrik RydgårdandClaude Opus 5.5 e3ea1adc48 Zip install: Reject PS3 save data
A zipped PS3 save folder has a PARAM.SFO and ICON0.PNG, the same layout
as a PSP save, so it was offered for install as one. PS3 saves have
CATEGORY SD in the SFO (PSP saves have MS) and a PARAM.PFD; either now
makes the zip unrecognized.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 14:22:13 +01:00
Henrik Rydgård 4da13731aa Merge pull request #23040 from hrydgard/savedata-export
Export saves as zip files, and share or save frame dumps
2026-11-11 14:19:57 +01:00
Henrik RydgårdandClaude Opus 5.5 56e3017966 libretro: Build the profiler, which every build has now
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 13:07:27 +01:00
Henrik RydgårdandClaude Opus 5.5 6f5eab87d9 Profiler: Write the log without fputs, which libretro's stdio doesn't have
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:59:36 +01:00
Henrik RydgårdandClaude Opus 5.5 af59826fe0 Profiler: Compile it into every build, with coarser scopes in rendering
It's now in release builds too, Android's included, and on iOS, UWP and
libretro, so no build runs a rarely tested configuration. NO_PROFILER still
leaves it out.

The scopes per GE CALL (gpu_call), per primitive (execprim) and per draw inside
a flush (renderman_q, applydrawstate, soft) are gone: their time shows in
gpuloop and flush (now named the same on every backend, D3D11 included). A
software-transformed flush is labelled "soft" instead. PROFILE_THIS_SCOPE_DYNAMIC
is gone too; its one user, the curve code, labels a "curve" scope with the kind.

The profiler windows and Tools/profile_report.py show how many scopes run per
frame, and headless ends a profiler frame per emulated one, so --profile-log
works there as it says.

What a scope costs while off, timed in the unit test on a Galaxy S8 (20 million
of them against the same loop without): nothing measurable. It's two
instructions there (a load of the switch and a branch), up to four elsewhere.
GTA: Liberty City Stories runs about 1,640 scopes a frame, so a few thousand
instructions in about 31 million. (The 0.39% more instructions measured over
whole runs is about 64 per scope, so most of it was something else, likely
threads that spin while waiting.)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:51:22 +01:00
Henrik RydgårdandClaude Opus 5.5 dacea56aaa SoftGPU: Remove the frame profiler scopes
A sampling profiler shows its costs better. Some were per pixel, and two in
one scope kept USE_PROFILER builds from compiling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:51:22 +01:00
Henrik RydgårdandClaude Opus 5.5 c4f3d7db37 Profiler: Check that it's on before the scope's category
The category's static has a thread-safe init guard, which every scope checked
before the profiler's on switch. Now the lookup is in a lambda that only runs
while the profiler is on, so a scope costs a load and a branch while it's off.
A non-literal name no longer compiles there (the lambda can't capture it); that
takes PROFILE_THIS_SCOPE_DYNAMIC.

Measured on a Galaxy S8 with ppsspp_headless, 20 emulated seconds of GTA:
LCS driving from a savestate, 12 runs each: compiled in and off, it runs 0.39%
more instructions than a build with NO_PROFILER (the runs spread 0.35-0.47%),
and no measurable CPU time difference.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:51:21 +01:00
Henrik RydgårdandClaude Opus 5.5 1b92700e54 Docs: Finding stalls with the frame profiler, and driving the app or a phone
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:51:21 +01:00
Henrik RydgårdandClaude Opus 5.5 a935279cc4 adhoc_session.py: Attach to a running PPSSPP, also on Android, and branch in scripts
attach drives one PPSSPP that's already running with --debugger, like the
app. With --adb it's the app on an Android device: the port is forwarded and
screenshots are taken with screencap, cut to the game's image (--rect) and
scaled to 480x272, so references and positions mean the same as headless.
screencap also doesn't pause emulation, unlike the debugger's screenshot, so
it can watch a run that's being profiled.

until takes --or REF@X,Y for screens that differ between runs (a menu that
only shows with a save), and a script line "if REF --box X,Y : COMMAND ;
COMMAND" runs the commands only when the screen shows the reference.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:51:21 +01:00
Henrik RydgårdandClaude Opus 5.5 1db3a7ecce Profiler: Log stalls without the UI, and compile it in with a runtime switch
--profile-log=FILE writes each frame's per-thread totals as JSON lines, and
for each slow frame every scope of at least --profile-span-ms that ended in it,
with its own time. A frame is slow if it takes at least --profile-hitch-ms and
1.5 times the median of the frames before it (a 30 fps game takes 33 ms every
frame). Slow frames also get a line in the log naming their longest scopes.
Tools/profile_report.py tells stalls (frames that fell behind the emulated
time they covered, counted with a new vblank scope) from frames where the
game just didn't flip, and sums up what the stalls' time went to.

PROFILE_LABEL names a scope: syscalls get the function's name, CoreTiming
events (now a scope) the event's, module loads the file and pipeline creation
the pipeline's tag. New scopes cover sleeps (labelled with their reason, and
the frame-idle wait now goes through sleep_us), Vulkan's waits for the GPU, the
render thread, pipelines and shaders, and GPU memory copies, uploads and
framebuffer readbacks.

The profiler is now compiled in everywhere except iOS, UWP, libretro and
Android release builds, and off until --profile-log, the frame profile overlay
or an ImGui profiler window turns it on. Off, a scope costs a load and a
branch. While on, syscalls compiled by the JIT go through CallSyscall, which
has the scope (decided in GetQuickSyscallFunc, instead of at build time in
each backend). The frame profile overlay's slot is no longer build-dependent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:51:21 +01:00
Henrik RydgårdandClaude Opus 5.5 377fa492b3 Profiler: Record per-thread event timelines, and add timeline and graph windows
The frame profiler kept its state in 4 thread slots, and every thread after
the fourth shared the last one's nesting depth and stack without locking.
Several threads entering and leaving scopes at once corrupted the depth,
which then indexed outside the arrays and crashed.

Now each thread that enters a scope gets a lane of its own: a ring of begin
and end events that only it writes. A thread that exits hands its lane to the
next new one; lanes are never freed, so readers can walk them without locks,
and a reader checks that an event wasn't overwritten while it copied it. A
literal scope name is looked up once per call site.

The per-frame totals (time in each category, not counting nested scopes) are
worked out from the events at each frame end, so the on-screen overlay keeps
working. The ImGui debugger gets a CPU profiler window, with a zoomable
timeline of each thread's scopes and frame ends plus a table of per-frame
totals, and a Frame profile window with the overlay's graph, per thread.

The Vulkan render thread has scopes for rendering, submitting and presenting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:50:57 +01:00
Henrik RydgårdandClaude Opus 5.5 78c7ce36b1 Translate "Share"
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:45:04 +01:00
Henrik Rydgård 9bd1d59902 Reorder 2026-11-11 12:44:09 +01:00
Henrik RydgårdandClaude Opus 5.5 ad58640cdb Frame dumps: Offer Share, Save or Continue where folders can't be shown
On Android, Save picks a place with the system's save picker, through
a new BROWSE_FOR_FILE_SAVE implementation (ACTION_CREATE_DOCUMENT).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:43:03 +01:00
Henrik Rydgård 7dcd534c43 Merge pull request #23039 from hrydgard/crash-screen-gpu-model
Crash screen: Show the GPU model and emulated time, tighten the spacing
2026-11-11 12:21:13 +01:00
Henrik Rydgård 9cc2d2d378 Reorder the buttons on the SavedataScreen Popup 2026-11-11 12:14:47 +01:00
Henrik RydgårdandClaude Opus 5.5 2fae0dadba Game screen: Export all of a game's saves from its menu
Exporting a single save stays in the savedata manager's popup. Exporting
a whole game's saves is rarer, so it moves to the game's menu.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:14:46 +01:00
Henrik RydgårdandClaude Opus 5.5 ec36fad065 Savedata manager: Make the highlight outline show up
An outline with a zero radius isn't drawn at all, so use square corners
instead. Medium width, so it doesn't look like the gaps between rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:14:46 +01:00
Henrik RydgårdandClaude Opus 5.5 95e7f2d686 Savedata manager: Export a game's saves from the popup of one of them
The page-wide button depended on the game the screen was opened for, which
the screen doesn't show. The popup knows the game from the save itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:14:46 +01:00
Henrik RydgårdandClaude Opus 5.5 9be62bb7d5 Frame dumps: Share them as zips where folders can't be shown
Where the file can't be shown in its folder (Android, iOS), "Create frame
dump" in the dev menu now zips the dump and opens the share sheet. The
frame dump hotkey does the same when its message is clicked, so the game
isn't interrupted. Both go through OnFrameDumpCreated(), which moves the
share to the main thread, since the recorder calls back on the emulation
thread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:14:46 +01:00
Henrik RydgårdandClaude Opus 5.5 f2c049d178 Translate the savedata export strings
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:14:46 +01:00
Henrik RydgårdandClaude Opus 5.5 ba94ea9da8 Savedata manager: Export saves as zip files
- Fixes #23031

The savedata popup gets an Export button, which zips the save folder (or
a savestate and its screenshot) and hands it to ShareFilesAsZip: the
share sheet on Android and iOS, a Save As dialog on Windows. The zips
use the layouts the zip import already recognizes, so they import back.

Opened for a game, the manager outlines that game's saves and states,
scrolls to them, and offers to export all of the game's saves in one
zip. The game screen gets a button that opens it that way.

Installed data is never exported. It looks like a save (same PARAM.SFO
fields), but games write the installed files with sceIo rather than the
savedata utility, so they're missing from SAVEDATA_FILE_LIST.
IsInstalledGameData() counts a folder as installed data when the files
outside that list add up to 10 MB or more. The game screen's split
between save and install sizes now uses it too, instead of treating any
folder over 10 MB as installed data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 12:14:46 +01:00
Henrik RydgårdandClaude Opus 5.5 a7209dc832 Crash screen: Show the emulated time
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 11:39:01 +01:00
Henrik RydgårdandClaude Opus 5.5 f1f87f7f98 Crash screen: Space the blocks by their measured height
The fixed offsets left big gaps after short blocks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 11:35:43 +01:00
Henrik RydgårdandClaude Opus 5.5 639427ee9c Crash screen: Show the GPU model and the graphics API
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 11:33:54 +01:00
Henrik Rydgård 362be19c51 Merge pull request #23037 from hrydgard/vulkan-pipeline-wait-lock
Vulkan: Don't hold a pipeline's lock while waiting for it to compile
2026-11-11 10:44:19 +01:00