Commit Graph
2129 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5.5 6dc9bb05cb Translations: Insert/Eject UMD and the XMB savestate message
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 18:30:07 +02:00
Henrik RydgårdandClaude Opus 5.5 0877c3d19a SaveState: Refuse savestates and rewind in a session booted into the XMB
Inserting and ejecting a disc there adds and removes the umd0:/umd1:/
umd:/disc0: mounts, and MetaFileSystem's state pairs sections with mounts
by position without recording which disc was in. A state could then fail
to load, or load one disc's open files onto another. The pause screen
already hid its save buttons for vshmain.prx; the save hotkeys, rewind,
the ImDebugger and the WebSocket debugger all went around that. The check
is now in SaveState itself, and rewind snapshots aren't taken. Verify
still runs, since it reads back with the mounts as they are.

A proper fix records the mounted image in sceUmd's state and remounts it
on load.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 18:25:01 +02:00
Henrik RydgårdandClaude Opus 5.5 7d2663bf73 VSH: Insert and eject UMDs from the pause screen
While the XMB is running, the pause screen offers "Insert UMD" with the
drive empty, opening the Switch UMD game picker, and "Eject UMD" with a disc
in. The XMB notices the change through its drive callback, as it does over
the debugger's game.umd.insert/eject. Games keep "Switch UMD".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 17:32:43 +02:00
Henrik RydgårdandClaude Opus 5.5 ef7ca8b85f GPU: Move sprites on pixel centers back half a pixel above 1x (compat SnapHalfPixelSprites)
The PS1 emulator draws sprites with their corners on pixel centers (x.5) and
their texture coordinates on texel centers. At 1x that covers whole pixels,
but above 1x it covers half a pixel more on the right and bottom and reads
the neighbouring texels, which shows as seams between tiles. With compat.ini's
SnapHalfPixelSprites, such sprites and their texture coordinates are moved back
half a pixel, which draws the same at 1x. Texture coordinates are also nudged
a 64th of a texel in, as a scaled sprite can sample right on a texel edge,
where interpolation can fall short of the texel the GE reads (the emulator's
video unpacking does).

Set for PS1 games (POPS00000).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 14:51:06 +02:00
Henrik RydgårdandClaude Opus 5.5 cf788d72ca GPU: Optionally draw logic ops done on a framebuffer copy one at a time (compat SeparateLogicOpDraws)
Where the backend has no logic op and no framebuffer fetch, the logic op is
done in the shader against a copy of the framebuffer taken when the batch is
drawn, so draws batched together don't see each other. The PS1 emulator puts
each 24-bit video frame together by ORing passes into the same pixels, so it
lost all but the last. With compat.ini's SeparateLogicOpDraws, such draws are
flushed one at a time, and the rectangles of one draw are split, as they can
overlap too.

It costs a framebuffer copy per draw. Set for PS1 games (POPS00000).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 14:51:06 +02:00
Henrik RydgårdandClaude Opus 5.5 da0ecd838e GPU: Framebuffers kept at native resolution (compat NativeResolutionFramebuffer)
compat.ini's NativeResolutionFramebuffer (an address) keeps that framebuffer at
1x whatever the render resolution, for one that holds data read back texel by
texel: the PS1 emulator unpacks 24-bit video into one three bytes per pixel.

Set for PS1 games (POPS00000).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 14:51:06 +02:00
Henrik RydgårdandClaude Opus 5.5 c9641b1332 GPU: Fixed framebuffers, whole from the start (compat FixedFramebuffer)
A framebuffer the game always keeps at one size, and also reads and writes
outside the area it draws: the PS1 emulator's VRAM, a 1024x512 16-bit surface
it copies between and reads back from the CPU. compat.ini's FixedFramebuffer
("address,width,height") makes it that size instead of one estimated from the
drawing, initializes it from memory even when the first draw doesn't look like
one, and uploads into it without filtering, since what goes in is data that's
read back (#22686 saw FFVI crash on bilinear uploads at 4x).

Set for PS1 games (POPS00000).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 14:51:06 +02:00
Henrik RydgårdandClaude Opus 5.5 979028645d Translations: Use gyroscope, Right Analog Stick in Controls
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 13:14:18 +02:00
Henrik RydgårdandClaude Opus 5.5 2fbb67f207 lang: A savestate that fails to load is from a newer version, not an older one
States from older versions load fine. The string is now shown when a
section of the state fails to load, which in practice means a newer
build saved it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 17:58:36 +02:00
Henrik RydgårdandClaude Opus 5.5 0978a3e363 PostShaders: Rename videoAA.fsh's texture2d() helpers
On Metal (and Vulkan through MoltenVK), SPIRV-Cross keeps the function
name, which collides with Metal's texture2d type, so the shader failed
to compile and the screen went black.

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ård 508c915ec8 Remove unused translation key 2026-10-18 01:32:36 +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 7163bd4b9e Translate the nearby players permission string
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 20:44:06 +02:00
Henrik RydgårdandClaude Opus 5.5 19e4b77be4 Android: Ask for the local network permission for ad hoc, UPnP and servers
Part of #21585

Android 17 blocks LAN traffic in both directions (TCP and UDP, including
broadcast and multicast) without ACCESS_LOCAL_NETWORK. Ask for it when
networking, the built-in ad hoc server, UPnP, share-on-startup or the
remote debugger gets turned on, when a game initializes ad hoc with
networking enabled, and at startup if a server is set to start then.

A denied ad hoc send fails with EPERM, which the games never see, so show
a message for it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 20:44:05 +02:00
Henrik RydgårdandClaude Opus 5.5 41bf0dec01 Translate the local network permission strings
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 20:44:05 +02:00
Henrik RydgårdandClaude Opus 5.5 d2e9e87242 Android: Ask for the local network permission before starting file upload
Part of #21585

Android 17 apps need ACCESS_LOCAL_NETWORK to serve other devices on the LAN.
The upload screen now asks for it when it opens, starts the web server once
it's granted, and shows a warning and a retry button if it's denied.

The permission only exists from API 37, so check for that rather than 35.
On Android 15 and 16 it reads as denied, which left Remote ISO's connect tab
stuck behind a permission request that could never succeed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 20:44:04 +02:00
Henrik RydgårdandClaude Opus 5.5 634300bedf Remove the he_IL_invert translation
It stored Hebrew strings reversed, to work around text rendering without
right-to-left support. All our text drawers now handle bidi text, the
SDL one through FriBidi, so the reversed strings render backwards.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 17:01:11 +02:00
Henrik Rydgård 54a6ac7dd1 Remove translation strings 2026-10-16 13:27:26 +02:00
Henrik Rydgård 0a9b57371f Delete the spline quality setting 2026-10-16 13:27:26 +02:00
Henrik RydgårdandClaude Opus 5.5 8e9b19ab7b Compat: Require default CPU clock for the PopCap games (Bejeweled 2, Peggle, Zuma)
They are very sensitive to timing on startup.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 10:33:37 +02:00
Henrik Rydgård f672916c77 Merge pull request #22568 from hrydgard/accurate-vdot-ir
Accurate VFPU dot products in every IR backend, on by default
2026-10-15 00:38:49 +02:00
Henrik RydgårdandClaude Opus 5.5 20530d35c0 Add a ReadbackShadow compat flag, for games that read many pieces of a buffer
Since the sequential copies heuristic went (50696c5b1f), every partial readback
waits for the GPU. Motorstorm reads parts of the screen about 18 times a frame,
and ran about 75% slower than 1.20.4: 5403 blocking readbacks in 10 emulated
seconds, against 156.

With the flag, the first partial color readback of a buffer reads all of it into
a copy outside PSP memory, and the pieces until the next render to the buffer
are copied from there. Unlike the old heuristic, only what the game asked for is
written to PSP memory. Motorstorm is back to 153 blocking readbacks and 1.20.4's
speed, with identical output. Grand Knights History, which the heuristic was
added for, gets the flag too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:56:32 +02:00
Henrik RydgårdandClaude Opus 5.5 bd54c3e659 Compat: Replace MoreAccurateVMMUL with ForceAccurateVdot
The games that needed vmmul's accurate dot products (Tekken 6, Warriors Orochi,
Tomb Raider Anniversary) now get AccurateVdot for every dot product, even with
the setting turned off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:30:37 +02:00
Henrik RydgårdandClaude Opus 5.5 524e8b5254 Translations: Game browser view modes, "Icon size"
"Grid icon size" is renamed to "Icon size", keeping the translations with
"grid" dropped from them. New keys for the view mode choices.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 10:46:40 +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 49e0711d10 Compat: Turn on CorrectCullAfterClip for Nova
The same as GachiTora: without it, GPUs with cull distances draw parts the PSP
range-culls after clipping.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:13:57 +02:00
Henrik RydgårdandClaude Opus 5.5 c46bf4aca5 Compat: Turn on CorrectCullAfterClip for GachiTora
A strip through the near plane leaves a sliver at the screen edge on GPUs with
cull distances, where it isn't software clipped. The PSP range-culls it after
clipping.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:13:57 +02:00
Henrik RydgårdandClaude Opus 5.5 60100c4254 - Fixes #13676
Vulkan: Batch Jackass' tiled in-place color grade

Jackass: The Game color grades the framebuffer in 32x64 tiles, one channel
per pass, texturing from the framebuffer it renders to. Each of the 225
draws became a depal pass plus a pass drawing it back, 450 render passes
per frame. A new queue hack, enabled by the TiledDepalHack compat flag,
sorts these pairs into waves of non-overlapping tiles and runs each wave
as one depal pass and one draw pass, leaving 6.

Output is byte-identical to before on both dumps from the issue, at 1x
and 3x on desktop, and at 1x on both phones below.

Time saved per post-processed frame, from replaying the dumps from the
issue with headless --bench (each replay renders that frame once):

  Redmi 9A (PowerVR GE8320):  ~145ms at 1x, ~180ms at 2x
  Unisoc UMS9632 (Mali-G57):  ~55ms at 1x and 2x

Either is more than a whole 33ms frame, so on those GPUs this pass alone
ruled out 30fps.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 17:08:58 +02:00
Henrik Rydgård 54d2f7efe1 Merge pull request #22522 from hrydgard/resync-gamecontrollerdb
Re-sync gamecontrollerdb.txt with SDL_GameControllerDB, add a sync script
2026-10-12 17:34:51 +02:00
Henrik RydgårdandClaude Opus 5.5 531a75f045 Add AccurateSplines compat flag, enable for Coded Arms
- Fixes #21391

Makes the hardware backends tessellate Bezier patches and splines with the
GE-exact evaluation the software renderer uses. Fixes the z-fighting glow
under the floor grates in Coded Arms.

AGENTS.md: Put "- Fixes #N" first in commit messages

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 14:04:38 +02:00
Henrik RydgårdandClaude Opus 5.5 2363a10a77 Re-sync gamecontrollerdb.txt with SDL_GameControllerDB, add a sync script
- Fixes #18091

The upstream part hadn't been synced since 2023. Tools/update_gamecontrollerdb.py
replaces it with the current upstream file and keeps PPSSPP's own mappings,
dropping those whose GUID upstream now has (after SDL's old-GUID conversion),
since a later line overrides an earlier one. 193 of 207 were covered,
including the PS3 and 8BitDo Ultimate 2C one-offs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 13:49:49 +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ård 4beabce32b Update compat.ini for Echoshift, more IDs for Echochrome 2026-10-12 09:24:46 +02:00
Felipe bfca12edac Updated brazilian portuguese translation
Updated/fixed strings.
2026-10-11 19:44:03 -03:00
Henrik Rydgård b21ba7b3b3 Enable accurate vmmul for two games that have had math precision problems before
- #11179 - Warriors Orochi 1/2
- #9843 - Tomb Raider Anniversary
2026-10-11 22:13:57 +02:00
Henrik Rydgård 38528d4790 Remove obsolete JitInvalidationHack
See #22494
2026-10-11 22:06:06 +02:00
Henrik Rydgård 72b338001f Throw in a speculative workaround for #17474 . Not gonna hurt. 2026-10-11 00:57:14 +02:00
Henrik Rydgård e312af9b04 Merge pull request #22483 from hrydgard/reinterpret-subpixel
Further improve the Tantalus games
2026-10-10 15:27:21 +02:00
Henrik RydgårdandClaude Opus 5.5 3cd6bf9d27 Tantalus depth fog: read depth at each render pixel's own sub-position
The Tantalus games (Cars Race-O-Rama, MX vs ATV Reflex and Untamed, SpongeBob)
turn depth into fog with a CLUT16 read of the swizzled depth mirror, stretched
2x into a 565 view of an 8888 buffer. A following 8888 copy writes the scene's
RGB and keeps the alpha, so each pixel's fog factor is the upper 565 half.

At a higher render scale, the depth X swizzle snapped every render pixel to its
PSP pixel's left edge, so the fog came out in PSP-pixel blocks. It now keeps the
position within the PSP pixel. That leaves the upper half sampling the right
half of the depth texel, half a pixel off the scene, which drew magenta halos on
the right of objects in Cars. With the new DepthCLUTIntoHalves compat flag, the
depal pass outputs twice as wide so each render pixel reads its own 8888 pixel's
depth.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 01:48:05 +02:00
Henrik RydgårdandClaude Opus 5.5 b9b1a29c42 Read CLUT8 from 16-bit framebuffers in the shader, replacing the SOCOM hack
The shader depal CLUT8 mode now handles 565, 5551 and 4444 framebuffers
(the format goes in the depal format bits, which this mode didn't fill
before), rebuilding the 16-bit pixel and taking its low or high byte.
This replaces SOCOMClut8Replacement, which assumed the high byte.

- The GE samples a pixel at its corner, the GPU at its center. With u
  stepping two bytes per pixel (SOCOM and Bend's games use u = 1 + 2x)
  that's a whole byte, so the shader steps back to the corner.
- The CLUT index shift, mask and start are applied, as in the other
  depal modes.
- The self-render copy region counted CLUT8's U in pixels, not bytes.

SOCOM, Star Wars: The Force Unleashed and the NPJG90068 dumps improve a
lot. Syphon Filter and Resistance: Retribution now read the right bytes,
which exposes a 16-bit precision difference in their bright pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 01:04:23 +02:00
Henrik RydgårdandClaude Opus 5.5 8a852ec47c Fix the Burnout Dominator lens flare at even render scales
The flare's occlusion result is rendered into every other 16-bit pixel of a
palette whose other half is uploaded from memory, then read back as a CLUT.
Two things broke it at 2x:

- The CLUT8-from-8888 shader depal picked the byte out of each pixel using
  the scaled texture size, so at 2x it read the wrong byte. It now works in
  PSP units (from u_texclamp, which it now always gets) and samples the
  pixel's center, not its edge, which is a render pixel boundary when
  scaled.
- The palette upload was linearly filtered when stretched, blending each
  16-bit half with its neighbour. Burnout Dominator joins Ridge Racer in
  NearestFilteringOnFramebufferCreate.

1x and 3x only worked because their sample points happened to land inside
the right texels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 01:04:23 +02:00
Henrik RydgårdandClaude Opus 5.5 a71a037e09 Compat: Read back MX vs ATV Reflex's luminance reduction too
The same engine as Cars Race-O-Rama, with the same 8x8 copy out of VRAM. Without
the readback the value the CPU reads never changes, so its brightness adaptation
stays frozen; with it, it follows the software renderer's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 17:01:37 +02:00
Henrik RydgårdandClaude Opus 5.5 a9b18a9192 Compat: Read back Cars Race-O-Rama's luminance reduction for its brightness adaptation
The game reduces the scene to 8x8 on the GPU, block transfers that into RAM,
and the CPU sets its brightness adaptation from it. With BlockTransferAllowCreateFB
the copy went into a GPU-side buffer instead, the CPU read stale RAM, and the
game kept getting darker on the hardware backends (#15914).

New compat flag BlockTransferReadbackSmall: transfers of up to 64 pixels into
RAM are still read back, a frame late, so it doesn't stall. Brightness from
the issue's savestate now follows the software renderer's (72 vs 84 at 6 s,
84 vs 95 at 20 s, from 25 and falling), at the same speed as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 17:01:37 +02:00
Henrik Rydgård 74ebc8af05 Add translation string 2026-10-09 13:26:22 +02:00
Henrik RydgårdandClaude Opus 5.5 feaa41fadb Always emulate partial color write masks in the shader, drop ShaderColorBitmask
Partial red, green and blue write masks now always go through the shader with
a framebuffer read. Across the frame dump set this only improves games outside
the old list (Split/Second, Ultimate Ghosts 'n Goblins, older DiRT 2 and OutRun
dumps without a game ID). Partial alpha masks keep the old heuristic: alpha is
the stencil, with its own write mask, and taking the shader path for them made
Pro Yakyu Spirits and Gangs of London worse.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 11:18:05 +02:00
Henrik Rydgård 8e596032f1 Merge pull request #22446 from hrydgard/misc-rendering-fixes
Misc rendering fixes
2026-10-08 11:16:14 +02:00
Henrik RydgårdandClaude Opus 5.5 2f9f9bf77e Compat: ShaderColorBitmask for Ultimate Ghosts 'n Goblins
Its glow sets the 5551 alpha through a 565 draw with only the top blue bit
unmasked. Without the flag the whole blue channel was written, tinting the
glow; 25276 -> 4274 pixels off the PSP in issue #20728's dump.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 10:46:54 +02:00
sum2012 bef8e2d9ad Fix Unbound saga saving issue
Find bug in #13111
2026-10-08 06:14:08 +08:00