Commit Graph
50262 Commits
Author SHA1 Message Date
Henrik Rydgård 7164fce7c4 Merge pull request #22897 from hrydgard/adhoc-ptp-segments
Ad hoc relay: Deliver back-to-back PTP sends about 1 ms apart
2026-11-03 23:09:50 +01:00
Henrik RydgårdandClaude Opus 5.5 92fbf32e19 Ad hoc relay: Iterate the PTP block queue instead of indexing it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 22:03:18 +01:00
Henrik Rydgård 723732ca67 Merge pull request #22913 from hrydgard/firmware-model-check
Warn when the installed firmware is for a different PSP model
2026-11-03 21:45:39 +01:00
Henrik Rydgård b86023c60c Merge pull request #22915 from hrydgard/texture-pack-saf-case
Replacement: Don't index packs on Android's shared storage to ignore case
2026-11-03 21:45:11 +01:00
Henrik RydgårdandClaude Opus 5.5 06f19c6473 Replacement: Don't index packs on Android's shared storage to ignore case
Looking for a file whose name differs in case lists the whole pack on
the first miss. For a pack behind a content URI, that's one content
resolver query per directory, which in a big pack takes long enough
that a Play report hit an ANR: the surface was destroyed while the
render loop sat in the texture cache's destructor, waiting for a load
blocked on the index. Shared storage already ignores case, so the index
couldn't find anything there anyway.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 20:03:13 +01:00
Henrik Rydgård caa91b54b5 Merge pull request #22912 from hrydgard/pvr-dynamic-ubo-crash
Vulkan: Work around a PowerVR crash when a vertex shader doesn't read the lights UBO
2026-11-03 19:56:02 +01:00
Henrik RydgårdandClaude Opus 5.5 6e292608d4 Translate the firmware model warning
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 19:50:30 +01:00
Henrik RydgårdandClaude Opus 5.5 c1c815da80 Ad hoc relay: Deliver back-to-back PTP sends about 1 ms apart
On a PSP, two PTP sends made back to back arrive about 1 ms apart (0.95 ms plus 0.65 us a byte), so
a receiver polling fast reads them one at a time; once both have arrived they come back as one read
(pspautotests net/adhoc/pair/ptpsegments, ptpmsg). Through the relay both arrived together, and
Capcom Classics Collection Reloaded's Street Fighter II, which expects them one at a time, dropped
the connection as the match started.

Relay PTP sessions now run in aemu_postoffice's block boundary mode, which hands over one send at a
time. Each block goes into a queue on the socket, up to its buffer size, and becomes readable no
earlier than the previous one plus the PSP's gap, counted from when it arrived; the relay's 1 ms poll
takes blocks as they come, so a receiver that looks late still gets them all at once. P2P mode
can't do this: its TCP stream has no send boundaries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 19:39:44 +01:00
Henrik RydgårdandClaude Opus 5.5 509d9a9f87 Use one string for both firmware model warnings
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 18:42:35 +01:00
Henrik RydgårdandClaude Opus 5.5 3a9ecbd04b Warn when the installed firmware is for a different PSP model
A firmware only has the files of the model it was installed for, and its XMB looks for the files of
the model we report, so a mismatch brings back #22909's blank theme colors and 6.61's red error
screen. Which models an install is for shows in the names of its ipl/ files (nandipl_01g.bin,
nandipl_psp2000.ipl); an install for every model has all of them, and firmwares older than the
PSP-2000 have one ipl for every model.

Changing the PSP model to one the installed firmware doesn't fit now asks first, with a way to
cancel, and booting the XMB with a mismatch shows a warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 18:37:26 +01:00
Henrik RydgårdandClaude Opus 5.5 73559d15aa Vulkan: Work around a PowerVR crash when a vertex shader doesn't read the lights UBO
On a Moto G54 (PowerVR BXM-8-256), F1 2009 and MX vs. ATV Untamed crash every few seconds in
vkCmdDrawIndexed, with a write fault at the start of a page inside vulkan.mtk.so.

At draw time, the driver writes the address and range of every dynamic UBO in the bound descriptor
set into a table, but sizes the table for the ones the shader stage reads. Our layout has two
dynamic UBOs, base and lights (vertex only), and a vertex shader without lighting reads only base,
so each such draw writes 16 bytes past the table. That's usually harmless, and faults when the
table ends a page.

With the new PVR_UNUSED_DYNAMIC_UBO_OVERRUN set on PowerVR, Vulkan vertex shaders always declare and
read the lights UBO. Declaring it isn't enough. On the G54, F1 went from crashing in 5 of 5
10-second runs to 0 of 5, and MX ran 3 of 3. The SPIR-V cache is keyed by source, so no cache
version bump is needed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 17:45:44 +01:00
Henrik Rydgård b00f806d3e Merge pull request #22904 from hrydgard/lazy-stencil-rebuild
Rebuild the stencil after a reinterpret only when a draw needs it
2026-11-03 17:16:52 +01:00
Henrik Rydgård 466e51a402 Merge pull request #22910 from hrydgard/sceReg-category-migration
Report the real PSP model to the VSH; let firmware upgrades migrate the registry, reset it on downgrades
2026-11-03 16:58:17 +01:00
Henrik RydgårdandClaude Opus 5.5 b5cf7b3f0c sceKernelGetModel: Report the emulated model instead of always a Slim
The VSH goes by this to decide what the PSP has. With the PSP model set to PSP-1000, the firmware
installer only writes the PSP-1000's files, so a shell told it's on a Slim looked for the Slim's:
3.71's theme color list showed its extra colors (flash0:/vsh/resource/13-27.bmp) as blank entries,
and 6.61 stopped at its red error screen. Both reproduced with the reporter's NAND and a PSP-1000
install of 6.61, and both are gone with this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 16:28:48 +01:00
Henrik RydgårdandClaude Opus 5.5 ff1a7840a3 Translations: DowngradeFirmware and UpgradeFirmware
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 16:10:10 +01:00
Henrik RydgårdandClaude Opus 5.5 928100c370 Firmware install: Say that an upgrade keeps the XMB's settings
An upgrade gets its own notice, informational rather than a warning, since the new shell migrates
the registry and nothing is lost. ReplaceFirmware stays for when a version can't be told.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 16:07:39 +01:00
Henrik RydgårdandClaude Opus 5.5 0f08ad103c Firmware install: Let the new shell upgrade the registry, reset it on a downgrade
Installing a firmware set category_version to the new firmware's schema, so no shell ever migrated
the settings PPSSPP keeps in its config. A shell upgrades the registry itself at its first boot: it
writes the default of every key added since the stored version and stores its own (seen booting
2.82, 3.71, 4.05, 5.50 and 6.61 from 1, and 3.71 and 6.61 from the previous firmware's version).
So an upgrade now leaves the version alone. A PSP can't be downgraded, and an older shell takes a
newer version for a corrupt registry, so a downgrade sets it back to 1; that shell's first boot then
rewrites everything added since 1.50, the theme, colour and wallpaper settings among them. Values a
newer shell left there across a downgrade and back broke the theme settings and then 6.61's boot.

The install screen says a downgrade resets the XMB's settings. Headless no longer sets the version
per boot either, so each boot migrates like a fresh config does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 15:58:29 +01:00
Henrik Rydgård 5708b4e44c Merge pull request #22908 from hrydgard/ir-vsrt-vf2h
IR: Compile vsrt1-4 and vf2h instead of interpreting them
2026-11-03 15:43:38 +01:00
Henrik RydgårdandClaude Opus 5.5 b18c3ed4d3 IR: Compile vsrt1-4 and vf2h instead of interpreting them
Colin McRae Rally 2005 interprets about 2 million of these each 10 emulated seconds, mostly vf2h.q.
vsrt1-4 become pairs of FMin/FMax, which order and break ties like the interpreter's vfpu_min and
vfpu_max, in the same operand order. The D prefix applies as usual (Colin masks half the lanes);
S and T prefixes, which vsrt rewrites, still go to the interpreter. vf2h gets an IR op of its own,
FFloatToHalf2, calling vfpu_f2h; the native backends call the IR interpreter's version of it.
vf2h with any prefix, and sizes other than pair and quad, still go to the interpreter.

The CPU equivalence fuzzer finds no differences on the IR interpreter or the ARM64 JIT, for these
ops alone, with random and unknown prefixes, and with the D prefixes Colin uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 14:45:06 +01:00
Henrik Rydgård 6215d4689e Merge pull request #22907 from hrydgard/cull-matrix-lanes
GPU: Multiply by lane in TestBoundingBoxFast instead of splatting the cull matrix
2026-11-03 14:41:40 +01:00
Henrik RydgårdandClaude Opus 5.5 8e5369953c Rebuild the stencil after a reinterpret only when a draw needs it
The stencil follows the alpha after a reinterpret (89fabe21fb), but MX vs. ATV Untamed swaps one
buffer between 565 and 8888 about 30 times a frame, and rebuilt it about 60 times a frame. One of
those got stencil tested. Without stencil export (PowerVR GE8320), that's a clear and eight draws
each. On a Galaxy A21, 10 emulated seconds of MX now take 29 s instead of 45 s (1.20.4: 27 s).

Now a reinterpret marks the stencil pending, and the first draw to that buffer that reads it, or
writes it where the color isn't written, rebuilds it from the buffer's own alpha. That goes back to
the copy from 89fabe21fb, so the same-pass stencil variant of the reinterpret shader goes. Draws that
write the stencil along with the alpha can go first: God of War zeroes it every frame, and no longer
rebuilds at all. Of the 15 benchmark states, only MX still rebuilds, once a frame.

Of the 1141 dumps in ppsspp-framedumps, 113 rebuild a stencil, 877 times in all, and three of those
get read, all in Ultimate Ghosts 'n Goblins. They all render the same as before, on Vulkan and
OpenGL on macOS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 14:22:40 +01:00
Henrik RydgårdandClaude Opus 5.5 5f50174440 GPU: Keep the cull matrix in four registers in TestBoundingBoxFast
Splatted, the matrix took sixteen vector registers, and on ARM64 the compiler reloaded them from the
stack every iteration. Multiplied by lane, it fits in four, with the same operations in the same order.
About 14% fewer samples in the function in Colin McRae on a Cortex-A53, where it's the top C++
function on the emu thread. Most of what's left is waiting for the vertex loads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 13:58:02 +01:00
Henrik Rydgård 19b2894c2a Merge pull request #22906 from hrydgard/bitplane-copy
Keep one framebuffer copy for a run of draws with the same write mask
2026-11-03 13:55:03 +01:00
Henrik RydgårdandClaude Opus 5.5 361f473f8c Keep one framebuffer copy for a run of draws with the same write mask
A draw with a write mask the hardware can't do reads the target from a copy, and takes a new copy
for every flush. But it only reads the bits its mask keeps, and doesn't change them, so while the
same mask draws on, without blending or a logic op, the first copy serves every draw. DBZ Tenkaichi
Tag Team draws its shadow map one bit of red at a time, about 26 copies a frame, now about 4.

The copy is dropped when the target or the mask changes, on any other draw, clear, block transfer or
stencil upload, and at the start of a frame. TEXFLUSH no longer drops it, only the self-texturing copy.

DBZ, 20 emulated seconds on an M1 Mac: 1.9 s to 1.1 s. On a Galaxy A21: 10.0 s to 9.7 s per 10.
The 1141 dumps in ppsspp-framedumps render the same, on Vulkan and OpenGL on macOS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 12:54:09 +01:00
Henrik Rydgård dd270dc123 Merge pull request #22905 from hrydgard/headless-wait-state
Headless: Hold the game until a --state has been applied
2026-11-03 12:46:19 +01:00
Henrik Rydgård 885c5401fb Merge pull request #22903 from hrydgard/xmb-music-old-firmware
sceIo: Let pre-3.80 XMB music browsers read the memory stick
2026-11-03 12:25:34 +01:00
Henrik Rydgård 83b6a83f20 Merge pull request #22902 from hrydgard/mpeg-firmware-fallback
HLE: Fall back to our HLE when a game asks for a firmware module we haven't got
2026-11-03 09:12:34 +01:00
Henrik RydgårdandClaude Opus 5.5 52b0a13f94 Headless: Hold the game until a --state has been applied
The state is read and decompressed on a worker while the game keeps booting. On a slow host that
got far enough to reach different code, and with MX vs. ATV Untamed without a firmware, its boot
crash, before the state landed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 08:15:18 +01:00
Henrik Rydgård a3309cdc2d Merge pull request #22900 from hrydgard/gamebutton-cleanup
sceReg: Sync registry settings with the config, match category_version to the firmware
2026-11-03 07:46:52 +01:00
Henrik RydgårdandClaude Opus 5.5 9d79b0d693 HLE: Fall back to our HLE when a game asks for a firmware module we haven't got
sceMpeg runs the real mpeg.prx by default since #22309, and boot only puts the HLE back when neither
the firmware nor the disc has one. MX vs. ATV Untamed carries an mpeg.prx it never loads, so without a
firmware it got the real sceMpeg, then asked sceUtility for the firmware's module, which wasn't there.
Every sceMpeg import stayed a missing stub, and the game crashed at boot writing through what the
calls returned.

Now that load turns the library over to our HLE and resolves the waiting imports against it. The
latched HLE flags change with it, so a savestate made afterwards restores the HLE too. Atrac goes on
to set up its HLE memory the same way. For a library the user disabled themselves the warning still
shows; for one that's real by default, like the boot-time check, it's only logged. MX now plays its
intro video without a firmware, and still loads the real module with one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 01:36:47 +01:00
Henrik RydgårdandClaude Opus 5.5 858b8f4873 sceIo: Let the 1.50 XMB's music browser read the memory stick
The 1.5x music browser reads PSP/MUSIC through msoem0:, the memory stick
with 8.3 names in the OEM code page, which wasn't mounted. It lists folders
with ioctl 0x02425051 on an ordinary directory fd (sceIoDread plus the name
in UTF-16), and sets a value on fatmsOem0: with devctl 0x02405852 at boot.
Formats from fatmsmod.prx and music_plugin.prx in 1.50.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 01:27:02 +01:00
Henrik RydgårdandClaude Opus 5.5 103f68f199 sceIo: Implement the memory stick path devctls the pre-3.80 VSH browsers use
- Fixes #22890

Before 3.80, the XMB's music browser doesn't list a folder with
sceIoDopen/sceIoDread. It asks the FAT driver directly, with the path as a
list of UTF-16 components: devctl 0x02415864 starts a directory search and
returns a dir fd, read entry by entry with ioctl 0x02425069. 0x02435865 and
0x02435860 are getstat and open, with the path given the same way. None of
these were implemented, so firmware 3.71 and older found no tracks.

The argument layouts are from fatmsmod.prx and music_browser.prx in 3.71.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 01:07:12 +01:00
Henrik Rydgård 06893a5526 Merge pull request #22899 from hrydgard/depth-raster-ram-wait
Depth raster: Don't wait for the worker on RAM addresses
2026-11-03 00:52:52 +01:00
Henrik RydgårdandClaude Opus 5.5 08d1e83739 sceReg: Map the XMB theme keys to new config settings
theme_type and CONFIG/SYSTEM/XMB/THEME's color_mode, wallpaper_mode,
system_color and custom_theme_mode now persist in the config. Their
defaults (0) are the firmware's schema defaults.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 00:46:25 +01:00
Henrik RydgårdandClaude Opus 5.5 4b74eccc38 sceReg: Set category_version to the installed firmware's schema version
The shell writes the default of every registry key added after the stored
category_version, and some of those (umd_autoboot) are now mapped to our
config. Each firmware's version is the default in its registry schema
table, in vshmain.prx (common_util.prx before 2.00). Installing a firmware
now stores it, and headless sets it from the NAND's firmware.

Also builds the config setting lookup in headless and libretro: without
g_Config.Init(), sceReg served its static dump instead of the mapped
config values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 00:46:25 +01:00
Henrik RydgårdandClaude Opus 5.5 2fd47cd7eb sceReg: Sync string keys with config, map the rest of the listed settings
owner_name and time_zone_area now read from and write to sNickName and
sTimeZoneArea. Also maps language, the date/time keys, summer_time and
parental_level. The config values are applied in the merged category view,
so reads by handle and the key info sizes see them too, not just
sceRegGetKeyValueByName. language reads through GetPSPLanguage() so that
the -1 'auto' setting reads as an actual language.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 00:46:25 +01:00
Henrik Rydgård 9d384d811d sceReg: Map the first settings to our config settings. Reset category version to 1 on firmware erase. 2026-11-03 00:46:25 +01:00
Henrik Rydgård 0b35fe863b More UI cleanup 2026-11-03 00:46:25 +01:00
Henrik Rydgård f416c318f4 Merge pull request #22898 from hrydgard/depal-pixel-mapped
Depal: Skip the bilinear filter on exactly pixel-mapped draws
2026-11-03 00:22:21 +01:00
Henrik RydgårdandClaude Opus 5.5 661e9a80f7 Depth raster: Don't wait for the worker on RAM addresses
WaitIfWriting compared addresses as VRAM offsets, which mapped RAM addresses onto VRAM too. Midnight
Club L.A. Remix loads CLUTs from RAM that land on its depth buffer's range that way, and the emu thread
waited for the depth worker at each, about a quarter of its time on a Galaxy A21. The depth buffers are
all in VRAM, so other addresses now return at once.

Midnight Club, 10 emulated seconds: 39.6 s to 24.0 s on the A21 (32.9 s in 1.20.4), 2.67 s to 2.32 s on
an M1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 00:17:37 +01:00
Henrik RydgårdandClaude Opus 5.5 7345002873 Software transform: Look for both kinds of pixel mapping in one loop
The smart 2D filtering check and the exact one for depal walked the rectangles separately. Now one loop
does both, stopping once neither can hold, and a rect of no size ends both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 23:49:40 +01:00
Henrik RydgårdandClaude Opus 5.5 8be9cbbe54 Depal: Skip the bilinear filter on exactly pixel-mapped draws
Shader depal filters by hand, with four texel and four palette lookups per pixel. DBZ Tenkaichi Tag Team
does two full-screen through-mode depal passes per frame, and on a PowerVR GE8320 (Galaxy A21) they took
DBZ from 8.3 to 14.4 seconds per 10 emulated seconds once #22204 had made framebuffer depal work again.
They're 1:1, where bilinear gives the nearest texel anyway, so rectangles that put every pixel center on
a texel center (equal UV and position deltas, at a whole-texel offset) now count as pixel mapped for
depal, which turns the filter off. Unlike the smart 2D filtering check, this changes nothing on screen:
the frame dumps render identically on Vulkan and OpenGL, 69 of them through this path. DBZ is down to 9.2s.

The depal uniform is also repacked when pixelMapped changes between draws, rather than only when the
texture is reapplied.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 23:25:04 +01:00
Henrik Rydgård 6f90e74176 Merge pull request #22895 from dogo/fix-macos-instance-counter
Instance: fix the instance counter on macOS
2026-11-02 21:31:55 +01:00
Henrik Rydgård 6088268605 Merge pull request #22896 from hrydgard/headless-http-games
Headless: Run a game over HTTP, and on Android without a JVM
2026-11-02 21:12:48 +01:00
Henrik Rydgård bf62233088 Merge pull request #22894 from hrydgard/adhoc-hw-behaviours
Ad hoc: Fix Shaun White Snowboarding's game mode, send buffer occupancy, and FIXMEs settled on hardware
2026-11-02 20:40:26 +01:00
Diogo Autilio 3ed7548ad1 Instance: fix the instance counter on macOS
Every instance after the first got PPSSPP_ID 1 on macOS, so they shared
the same ad hoc MAC and IP, and secondary instances saved the config.

- flock() on a shm object fails with ENOTSUP on Darwin, so the counter was
  never updated. Lock with a named semaphore there; keep flock elsewhere.
- ftruncate() on a shm object that already has a size fails with EINVAL on
  Darwin. Only size the object when it's new.
- Shutdown unlinked the shm object even while other instances were still
  running, so the next one to start got a fresh counter and ID 1 again.
  Only unlink when the last instance exits.
2026-11-02 16:01:00 -03:00
Henrik RydgårdandClaude Opus 5.5 09dd40f7a6 Headless: Accept an http:// game
The loader streams it (HTTPFileLoader), but headless rejected anything File::Exists doesn't
find. This lets a phone run a game served from another machine, over adb reverse or the LAN.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 19:32:01 +01:00
Henrik RydgårdandClaude Opus 5.5 9593c58d12 Net: Don't require a JVM on Android
Headless has none, and asserted at startup. Without one there's no HTTPS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 19:32:01 +01:00
Henrik Rydgård 5e39edd444 Merge pull request #22892 from hrydgard/inet-call-timing
sceNetInet: Timed waits end late, and the other calls cost what they do on a PSP
2026-11-02 18:45:06 +01:00
Henrik Rydgård 60ecaf04ee Merge pull request #22893 from hrydgard/flip-listener-race
Debugger: Fix a use-after-free and a deadlock in GPU stats; one connection per command in adhoc_session.py
2026-11-02 18:44:44 +01:00