Commit Graph
49186 Commits
Author SHA1 Message Date
Henrik Rydgård 2c19007b61 Merge pull request #22634 from hrydgard/peacewalker-cutscene-state
sceVideocodec: Hand pictures back when the PSP's decoder does (fixes MGS Peace Walker cutscene end)
2026-10-18 12:20:46 +02:00
Henrik Rydgård 9718284261 Merge pull request #22636 from hrydgard/gamelist-no-touch-video
GameBrowser: Only play ICON1 videos on keyboard/gamepad focus
2026-10-18 12:20:39 +02:00
Henrik RydgårdandClaude Opus 5.5 9e04178054 UI: Let ScrollView children see mouse moves without a button held
ScrollView dropped every mouse event without the left button, so views inside
one never saw hovers or right clicks. This kept nested scroll views from
tracking hover for the mouse wheel, and GameButton's right-click info only
worked once a left click had set its hover flag.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 11:55:40 +02:00
Henrik RydgårdandClaude Opus 5.5 672ff85efa GameBrowser: Only play ICON1 videos for keyboard/gamepad focus
With touch or the mouse, the video started as soon as you pressed a game,
so watching it without launching the game took a careful drag-and-release.
Touch and mouse users can still see the video from the info button or a
long press.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 11:49:09 +02:00
Henrik RydgårdandClaude Opus 5.5 8d2fbf7079 sceVideocodec: Hand pictures back when the PSP's decoder does
The PSP's AVC decoder follows the H.264 output process (Annex C),
measured in the new pspautotests video/mp4/avchold on streams that
differ only in their headers, and video/mpeg/decodeend. With HRD
parameters and picture timing SEI, a picture comes out dpb_output_delay
after its access unit; Sony's movies have a one frame delay. Without, it
is bumped out of a buffer three frames deep, whatever the stream
declares. sceMpegAvcDecodeStop hands back what's left, and streams with
more than three reference frames are refused with 0x80628002.

We handed each picture back as soon as it was decoded. MGS Peace
Walker's movie player only checks for the end of a movie while its
clock is short of the movie's length, so its last picture landed right
on that limit and the game hung on a black screen after the cutscene.

ffmpeg still decodes the pixels, in display order; each access unit is
tagged with its index so frames can be matched back, and ffmpeg's H.264
parser supplies the picture timing. A call can now hand back several
pictures, as consecutive 0x2C byte descriptors the way mpeg.prx's
sceMpegAvcDecodeStop reads them, each in a frame buffer slot of its own
(reallocated when a savestate brings a block too small for that).

Not followed: with B-frames and no picture timing, the PSP can complete
several pictures in one call; here they come out one a call. All of
the game movies checked have picture timing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 11:25:55 +02:00
Henrik Rydgård 3a569380a2 Merge pull request #22635 from hrydgard/adhoc-savestate-inited
Adhoc: Restore the inited flags from savestates
2026-10-18 11:25:36 +02:00
Henrik RydgårdandClaude Opus 5.5 16a03f16e8 Adhoc: Restore the inited flags from savestates
Loading a savestate kept the current session's netAdhocInited,
netAdhocctlInited and matching-inited flags rather than the saved ones.
Loaded into a fresh boot, a state saved with adhocctl initialized (but not
connected) then failed every adhocctl call with NOT_INITIALIZED. MGS Peace
Walker shuts ad hoc down before a cutscene and retried
sceNetAdhocctlDisconnect forever, leaving the screen black.

Take the flags from the state, and bring the host side in line: start the
friendFinder and log in again when the state has adhocctl up and we don't,
stop it in the opposite case. Also save the product code, which that login
sends.

Also add a game.state.save debugger command, used to reproduce this.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 09:15:51 +02:00
Henrik Rydgård 1265a3cef4 Merge pull request #22633 from hrydgard/android-jni-cleanup
Claude code review: Android JNI, again
2026-10-18 02:09:16 +02:00
Henrik RydgårdandClaude Opus 5.5 e32e558aab Android Vulkan: Drop the stale surface extent workaround
The transposed extents f7ec86c5d5 worked around came from the size race
the previous commit fixed: with the size now applied between frames, the
workaround didn't fire once in 38 rotations on the Galaxy S8+ that hit it
in about one in four.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 01:47:07 +02:00
Henrik RydgårdandClaude Opus 5.5 515b497f91 Android: Apply size changes on the render thread, between frames
backbufferResize comes from the UI thread, and changed g_display while the
render thread was drawing with it. Like iOS, it now leaves the new size for
the render thread to apply before its next frame, or applies it directly if
no render loop is running. A rotation in a resize that's superseded before
it's applied still forces the swapchain recreate.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 01:44:03 +02:00
Henrik RydgårdandClaude Opus 5.5 d6985d81eb Android: Simplify joystickAxis and queryGameInfo, drop dead JNI calls
joystickAxis copies the axes in batches on the stack instead of allocating
per event, and bounds the count by the arrays it got. queryGameInfo's cache
is a local, in a helper so it's gone before the thread manager is torn down.

Removes Android_GetFreeSpaceByFilePath (never called) with its Java side, and
isLandscape, which only existed to call NativeGetAppInfo early.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 01:36:35 +02:00
Henrik Rydgård 508c915ec8 Remove unused translation key 2026-10-18 01:32:36 +02:00
Henrik RydgårdandClaude Opus 5.5 a09f59910b Android: Fix JNI edge cases, read Java strings as real UTF-8
- Scoped storage no longer flips on while no activity is registered: whether
  legacy storage was preserved is fixed per install, so it's asked once.
- Free space reads as unknown (-1), not 0 bytes, without an activity.
- Strings from Java (file listings and info, crash history, the camera list,
  the input debug string) go through GetJavaString, so names with characters
  outside the BMP aren't mangled, and a null string can't crash the crash
  history.
- Requests (inputbox, browse_*) whose command can't be delivered are failed
  instead of left waiting forever.
- A font that fails to load uses the default typeface (-1) instead of font 0,
  and is retried later if there was no activity yet. Missing exception checks
  added in the text renderer.
- Method IDs and the storage callbacks are looked up once in JNI_OnLoad.
- Unknown permissions are logged correctly.

Also removes what was left of Moga support, the unused backbuffer format and
a stray MessageBox macro, and tidies System_GetCameraDeviceList.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 01:29:18 +02:00
Henrik Rydgård 0665ea0feb Merge pull request #22632 from hrydgard/android-optional-location
Android: Make location an optional feature
2026-10-17 20:35:53 +02:00
Henrik RydgårdandClaude Opus 5.5 363fe679c2 Android: Make location an optional feature
The location permissions imply android.hardware.location as required,
on top of the .gps and .network subfeatures we already marked optional.
Also skip the permission prompt on devices without location hardware.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 19:49:12 +02:00
Henrik Rydgård f572831d37 Merge pull request #22631 from hrydgard/fix-microphone-requirement
Android: Fix microphone requirement
2026-10-17 19:32:13 +02:00
Henrik RydgårdandClaude Opus 5.5 1d7458c4f9 Android: Don't ask for microphone permission on devices without one
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 19:28:12 +02:00
Henrik RydgårdandClaude Opus 5.5 b3ed6971d2 Android: Make the microphone an optional feature
RECORD_AUDIO implies android.hardware.microphone with required=true
unless declared otherwise, which hides the app from devices without one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 19:26:29 +02:00
Henrik Rydgård 521d54bb19 Merge pull request #22630 from hrydgard/mac-fixes
UI: Use Cmd for shortcuts on Mac and iOS, not Ctrl
2026-10-17 18:34:34 +02:00
Henrik RydgårdandClaude Opus 5.5 db3ec7567f UI: Use Cmd for shortcuts on Mac and iOS, not Ctrl
- Fixes #17608

Text fields took Ctrl or Cmd for copy/paste/undo; now it's Cmd on Apple
platforms and Ctrl elsewhere, as is Ctrl+F (Cmd+F) for game search. Word
delete in the search filter is Option+Backspace on Apple.

The ImGui debugger never got Super, so with ImGui's Mac Cmd/Ctrl swap,
its paste and other Ctrl shortcuts could not be reached at all on Mac.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 17:46:55 +02:00
Henrik Rydgård bd0937efd2 Merge pull request #22629 from hrydgard/savedata-test-flakiness
Update pspautotests: Fix flaky savedata tests
2026-10-17 17:27:04 +02:00
Henrik Rydgård ff594ac1fa Merge pull request #22610 from hrydgard/amagoushi-hit-test-readback
Compat flag for Amagoushi no Yakata 3D investigation hit-test readback (fixed PR)
2026-10-17 17:26:42 +02:00
Henrik RydgårdandClaude Opus 5.5 ed6d92aab5 Update pspautotests: Fix flaky savedata tests
The savedata tests printed the utility's results on every poll, so they
failed when PPSSPP's IO thread was caught partway through writing them.
They now print them once the utility reports FINISHED.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 15:45:10 +02:00
Henrik Rydgård 52ba05d9e7 Merge pull request #22628 from hrydgard/jit-stats-overlay
Add a JIT stats debug overlay, and rebalance the JIT's code and IR space
2026-10-17 15:36:45 +02:00
0a0458ed7a Amagoushi no Yakata: Read the picking pass back at sceGeDrawSync instead
The hook on the decode function fixed hit-testing, but the solid color
picking frames could stay visible on screen, more so at high render
resolutions. Reading back at sceGeDrawSync(0), right after the game
waits for the pass, doesn't show them. Only the framebuffer the last
list drew to is read back. Rularia found and tested this at 10x on
ULJS00216.

The new ColorPickingDrawSyncReadback compat flag replaces the
ReplaceTables hook, and ULJS00247 (the third game's UMD) is added
alongside the others.

Co-Authored-By: Rularia <Rularia@outlook.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 15:19:31 +02:00
RulariaandClaude Opus 5.5 ed347bf0e4 ReplaceTables: Fix Amagoushi no Yakata 3D investigation hit-test readback
- Fixes #22514

The 3D investigation mode renders an ID picking pass into VRAM and reads
it back on the CPU to build the hit-test table. Hook the decode function
to flush the framebuffers to VRAM first, and force lower resolution for
effects to avoid stutter.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 15:15:59 +02:00
Henrik RydgårdandClaude Opus 5.5 b175bc859a IR JIT: Grow the native code space to 24 MB
Big games fill 16 MB in normal play. It's now one constant shared by
every backend. ARM32's 32 MB branch range is the limit on going higher
there.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 15:11:47 +02:00
Henrik RydgårdandClaude Opus 5.5 315fd0e490 IR JIT: Cut the IR arena to 4M instructions
The native code space fills long before the arena did: Tekken 6 has it
30% full with the arena at 3%. The old limit was the 24 bits an emuhack
opcode had for the offset, which the block shadow no longer needs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 15:00:47 +02:00
Henrik RydgårdandClaude Opus 5.5 86791f6c3a JIT stats overlay: Count block invalidations
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 14:49:24 +02:00
Henrik RydgårdandClaude Opus 5.5 5e0cafaa52 docs: Say that the cpu-equivalence fixes for the ARM64 and x86 JITs are history
Those JITs were removed, and every JIT is IR-based now.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 14:49:24 +02:00
Henrik RydgårdandClaude Opus 5.5 2b0b1ed561 Add a JIT stats debug overlay
Shows the number of blocks, how full the native code space and the IR
arena are, and how many times each filling up cleared the cache.

The "Ran out of block numbers" message was logged for both of those, and
there is no block number limit. It now says which one filled up.

Also hide the GPU profile and allocator overlays by value on backends
that lack them. Cutting the last two off the list had been hiding the
framebuffer list since it was added after them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 14:49:24 +02:00
Henrik Rydgård 370a9ca963 Merge pull request #22627 from hrydgard/windows-exit-hangs
Windows: Fix hangs on exit (HID pads, web server), and log the exit waits
2026-10-17 14:48:43 +02:00
Henrik Rydgård 9673f63b21 Merge pull request #22626 from hrydgard/ui-fixes
UI: Recent tab toolbar, and Escape from Settings back to the pause menu
2026-10-17 14:06:38 +02:00
Henrik Rydgård f29d72cea8 Merge pull request #22625 from hrydgard/ios-frametests
Fix two frame dump batch problems found by frametests --ios
2026-10-17 13:57:00 +02:00
Henrik RydgårdandClaude Opus 5.5 37591a2401 Web server: Don't hang shutdown when it lands during startup
StopWebServer() only stopped a RUNNING server, while ShutdownWebServer()
joined in any state but STOPPED. Shutting down while the server was
still STARTING joined a thread nobody had told to stop, which then
entered its loop and never left. Stop it while STARTING too, and only
switch to RUNNING if no stop came in meanwhile.

Also make the report.ppsspp.org registration cancellable. It runs at
startup and every nine minutes, and couldn't be interrupted, so exiting
during a stalled one waited out its connect and 900s header timeouts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 13:53:52 +02:00
Henrik RydgårdandClaude Opus 5.5 f959acd680 Log the waits on exit
So a log from a process that never exits shows which step it hung in.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 13:51:56 +02:00
Henrik RydgårdandClaude Opus 5.5 2968debfe7 Windows: Don't hang on exit when a HID pad stops sending reports
DualShock, DualSense and Switch Pro pads are read with a blocking
ReadFile on the input thread, and WM_DESTROY joins that thread. If the
pad stops sending reports the read never returns, so the window is gone
but the process stays. Cancel the thread's I/O until it stops, retrying
in case a cancel lands just before a read starts. This also covers the
synchronous writes the pads' shutdown does.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 13:51:56 +02:00
Henrik RydgårdandClaude Opus 5.5 64ae00da91 Darwin: Keep the view reservation intact while releasing views
MemoryMap_Shutdown deallocated each view, opening holes in the reserved
range, and then released the whole range. A mapping another thread got in
a hole meanwhile was unmapped along with it. On iOS that was Metal's
command buffer memory: headless crashed in vkQueueSubmit about a hundred
frame dumps into a launch. Map inaccessible pages over a released view
instead, so the range stays ours until ReleaseViewSpace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:33:45 +02:00
Henrik RydgårdandClaude Opus 5.5 f0f0b11576 GPU: Reset the flip count when creating a GPU
Framebuffer ages are measured in flips, and the count carried over from
the previous game. Headless replaying several frame dumps in one process
(frametests.py --ios does, 100 per launch) then rendered a dump
differently from replaying it alone: Colin McRae Rally lost its car and
trees whenever any dump came before it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:33:45 +02:00
Henrik Rydgård c21f3521e2 Merge pull request #22624 from hrydgard/ios-frametests
iOS: Add support for running PPSSPPHeadless on iOS, add support in the frametests.py script
2026-10-17 12:53:14 +02:00
Henrik Rydgård 1461c929e3 Merge pull request #22623 from hrydgard/tekken-movie-fps
GPU: Use the width inside the scissor to compute the timing of video blits
2026-10-17 12:52:47 +02:00
Henrik RydgårdandClaude Opus 5.5 ea1ea14042 Pause screen: Ignore the pause key while another screen is on top
- Fixes #22622

Escape is both the UI back key and the default pause key. The pause
screen listens to the control mapper, which UI screens pass keyboard
input to, so Escape in Settings closed Settings and the pause screen
under it at once, dropping straight back into the game. EmuScreen
already checks IsOnTop() for the same reason.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 12:36:03 +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årdandClaude Opus 5.5 1b475f219c GPU: Cite blittiming's scissor-strip cases for the clipped blit width
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 12:11:21 +02:00
Henrik RydgårdandClaude Opus 5.5 a69ca3b218 GPU: Judge the blit texture cache by the width inside the scissor
Tekken 6 draws its intro movie as one full-width sprite eight times, each
scissored to a 64-pixel strip. The fill cost model picked the thrashing
rate from the sprite's full 480-pixel width, charging ~51ms per frame, so
the game's sceGeDrawSync held it to 15fps. It plays at 30fps on a PSP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 12:04:05 +02:00
Henrik RydgårdandClaude Opus 5.5 57cc1a6cb7 Headless: Run on iOS as an app, and frametests.py --ios
iOS only runs app bundles, so with HEADLESS=ON the iOS build makes
PPSSPPHeadless an app (org.ppsspp.headless) that starts UIKit and runs
the headless main on a thread with the arguments devicectl launched it
with. Vulkan only, and the IR interpreter since there's no JIT.

frametests.py --ios installs it, copies over the dumps the device lacks,
and compares each render with the host's Vulkan one like --adb does.
Each devicectl call costs a second or two, so the new --screenshot-dir
lets one launch render a batch of dumps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 11:11:31 +02:00
Henrik RydgårdandClaude Opus 5.5 ab587c98e8 FileUtil: Make CreateFullPath work with relative paths
GetRootVolume() returns a relative path unchanged, so the path to create
came out empty: nothing was created, and it still returned true.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 11:11:31 +02:00
Henrik Rydgård bd3df9de3c Merge pull request #22621 from mariobob/ccc-stop-at-invalid-input
sceCcc: Stop string conversions at invalid input
2026-10-17 10:03:45 +02:00
Henrik Rydgård e03cd3ef32 Merge pull request #22619 from hrydgard/vertex-depth-snap
GE: Make hardware and software transform depth agree more often, and keep more near/far-plane draws on the GPU
2026-10-17 09:42:01 +02:00
Henrik Rydgård 5f2d4afbdc Merge pull request #22617 from hrydgard/medievil-fire
Fix the Medievil Dragon Armor fire at 60hz
2026-10-17 00:16:14 +02:00