Commit Graph
50728 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 4e8db90ece Translations: PSP system clock speed, its hint and boot warning
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 12:33:48 +01:00
Henrik RydgårdandClaude Opus 5.5 0585eb4019 UI: Rename "Change CPU Clock" to "PSP system clock speed", warn at boot when it's set
The setting changes the bus clock as well as the CPU's. "(unstable)" moves into a
hint, and starting a game with a non-default clock speed now shows a warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 12:32:10 +01:00
Henrik Rydgård 31137057cf Minor layout tweaks 2026-11-12 12:24:32 +01:00
Henrik Rydgård 16427de5b2 Flip the default for EmulateMediaEngine to true 2026-11-12 12:17:02 +01:00
Henrik Rydgård 9ff411df48 Spacing adjustments on the main screen 2026-11-12 12:16:16 +01:00
Henrik Rydgård aeeeed1714 Merge pull request #23051 from hrydgard/reporting-played-seconds
Reporting: Send time played in seconds, firmware version, OS, device model and disc format
2026-11-12 12:08:07 +01:00
Henrik Rydgård 382f64dddc Merge pull request #23050 from hrydgard/vulkan-split-huge-frames
Vulkan: Split frames with more than 1000 render passes into several submits, framedump player bugfix
2026-11-12 12:05:53 +01:00
Henrik RydgårdandClaude Opus 5.5 983defba6d Frame dump replay: Don't read command data through struct pointers
The data in a dump is only 2-byte aligned at times. Reading two fields of a
struct there can compile to LDRD on 32-bit ARM, which faults: replaying
11583 Weird shader bug Z-fighting_4 died with SIGBUS (BUS_ADRALN) in
DumpExecute::Display on a Galaxy A2 Core. Copy the data out with memcpy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 11:34:30 +01:00
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årdandClaude Opus 5.5 e8e9ac5870 Vulkan: Split frames with more than 1000 render passes into several submits
A Brave Story frame dump has 7347 render passes in one frame. On an Adreno 506
(Redmi Note 4, kernel driver kgsl) submitting that fails in the kernel with
ENOMEM: adreno_ringbuffer_submitcmd needs a physically contiguous order-7
allocation for it. The driver doesn't report the error, the frame fence never
signals, and the emulator hangs in vkWaitForFences. FlushSync once a frame
reaches 1000 steps. Ordinary frames are far below that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 11:18:04 +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