Commit Graph
50224 Commits
Author SHA1 Message Date
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 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
Henrik RydgårdandClaude Opus 5.5 c4c8ddc6a1 Ad hoc: GameModeUpdateReplica gives the last timestamp when there's no new data
A PSP never writes the info struct's length, and on a call without new data writes updated = 0 and
the last data's timestamp again, 0 before any came (pspautotests net/adhoc/pair/gamemodeinfo).
PPSSPP wrote the length and left the timestamp alone without new data. Shaun White Snowboarding
reads the timestamp either way, from a struct on its stack, and keeps the newest it has seen as the
time of the last update; stack garbage got in there, and the host gave up on the game a moment
after the match started ("The game is no longer available").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 18:42:29 +01:00
Henrik RydgårdandClaude Opus 5.5 91965a3d1d Ad hoc: Data in flight takes up the PTP send buffer
On a PSP, with 8192 bytes in flight from an 8 KB send buffer, poll leaves out SEND and a
non-blocking send of 16 more returns WOULD_BLOCK until about half the buffer has drained, and poll
leaves out FLUSH until the data has arrived, which takes as long as a flush (pspautotests
net/adhoc/pair/ptpsendready). PPSSPP reported both at once and took any send. The in-flight bytes
from the flush model now drain linearly until their delivery time; sends that don't fit wait, and
GetPtpStat counts what's left. Relay PTP sockets now record their buffer size, which they didn't.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 18:19:34 +01:00
Henrik RydgårdandClaude Opus 5.5 8e68d52332 adhoc_session.py: One debugger connection per instance per command
wait polled the emulated clock with a new connection every few milliseconds, thousands of them
in a long wait, each with its own thread and subscribers on the PPSSPP side.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 18:19:21 +01:00
Henrik RydgårdandClaude Opus 5.5 f4195c6c17 Debugger: Fix a deadlock in gpu.stats.feed
Feed() held pendingLock_ across Core_RunOnCPUThread(). Once sendFeed_ was set, the CPU thread's
next flip waited for that lock in FlipListener(), while Feed() waited for the CPU thread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 18:19:21 +01:00
Henrik RydgårdandClaude Opus 5.5 16544a3bd3 Display: Don't call a flip listener after it's been removed
DisplayFireFlip() copied the listener list and called the copy without the lock, so a debugger
connection closing on its own thread could free its GPU stats subscriber while the CPU thread was
about to call it. Headless crashed (or hung) in WebSocketGPUStatsState::FlipListener() with
scripts that open a connection per command. Hold the lock across the calls, as LogManager does for
its callbacks, so __DisplayForgetFlip() returns only once the listener can't be running.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 18:19:21 +01:00
Henrik RydgårdandClaude Opus 5.5 35753699db Ad hoc: GetPeerList and GetScanInfo leave a too-small buffer alone
A PSP returns size 0 without touching a buffer too small for one entry, and GetPeerList refuses
a negative size with INVALID_ARG (pspautotests net/adhoc/pair/listsizes). PPSSPP cleared the
whole buffer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 18:19:08 +01:00
Henrik RydgårdandClaude Opus 5.5 693a6a89ba Ad hoc: Settle FIXMEs with pspautotests net/adhoc/edges
What a PSP does, where PPSSPP differed:
- A PtpOpen or PtpListen on a port in use uses up a socket ID, as PdpCreate's does.
- A connect to a MAC that isn't in the group would block or times out, and is refused once the
  retransmits would have run out, (count + 1) * interval. It returned INVALID_ADDR at once.
- PtpAccept's flag must be 0 or 1.
- A blocking broadcast returns 0, so one the host can't take in time is dropped, not a TIMEOUT.

The FIXMEs and TODOs other tests already answer (socketids, adhocctl, gamemode, ptp) now say what
the PSP does instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 18:19:08 +01:00
Henrik RydgårdandClaude Opus 5.5 94263e15ed sceNetInet: What the other calls cost
pspautotests net/inet/calls measures what socket, bind, listen, connect,
accept, the socket options, getsockname and getpeername, shutdown, close
and the address conversions cost on a PSP when they don't wait: from 3
us for an address conversion to 76 us to close a TCP connection (95 us
with RST), and 4 us on a socket that isn't open. They cost about 1 us
each here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 18:07:42 +01:00
Henrik RydgårdandClaude Opus 5.5 cedbf009f0 sceNetInet: Timed waits end 120 us late and last at least 330 us
On a PSP, select and poll with nothing ready return about 120 us after
their timeout (pspautotests net/inet/timing), wait at least about 330 us
for any timeout from 10 us up, and don't wait at all for a timeout of
1 us. We waited exactly the timeout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 18:07:42 +01:00
Henrik Rydgård 9c9eefa358 Merge pull request #22891 from hrydgard/adhoc-joiner-22886
Ad hoc: Fix NBA 2K13's joiner (scan list, relay self-connect, PtpFlush timing)
2026-11-02 17:55:51 +01:00
Henrik RydgårdandClaude Opus 5.5 ae2835838e Ad hoc: PtpFlush waits until the sent data would have reached the peer
On a PSP a non-blocking flush right after a send returns WOULD_BLOCK, and 0 once the data is in
the peer's buffer, about 4.5 ms plus 2.4 us per byte, and GetPtpStat counts the bytes as unsent
until then (pspautotests net/adhoc/pair/ptpflush). PPSSPP's flush returned 0 at once. NBA 2K13's
host sends the match info, flushes until it gets 0 and closes; with the instant flush it closed in
the same frame, and the joiner, which checks for a disconnect before reading, never read the last
chunk ("There was a problem transferring the match information").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 17:04:03 +01:00
Henrik RydgårdandClaude Opus 5.5 7ee4cf67ea Ad hoc: Keep the scan list while connected
GetScanInfo returned nothing while in a group. On a PSP the list from the last scan stays after
Create, Join and Disconnect, and only a scan attempted while connected empties it (pspautotests
net/adhoc/pair/scaninfo, added here along with ptpflush). NBA 2K13's joiner looks for the group it
just joined in the list and leaves when it isn't there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 17:04:03 +01:00
Henrik RydgårdandClaude Opus 5.5 38d94e02f2 Ad hoc relay: Refuse a PTP connect to yourself with no listener at once
A PSP refuses it immediately (pspautotests net/adhoc/ptp, "Connecting to nobody"), while the
relay held it for about 4 seconds before giving up. NBA 2K13's joiner connects to each entry of
its peer table in turn, itself first, and gave up on the group before it got to the host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 17:04:03 +01:00
Henrik Rydgård ae21ead0d8 Merge pull request #22889 from hrydgard/input-latency
Android: Minor input and audio latency improvements
2026-11-02 16:49:06 +01:00
Henrik Rydgård ef6ca2a303 Merge pull request #22887 from hrydgard/fix-stencil-rebuild-cost
Reinterpret: Write the stencil from the source, in the same render pass
2026-11-02 15:48:41 +01:00
Henrik RydgårdandClaude Opus 5.5 0ad07d1560 Reinterpret: Write the stencil from the source, in the same render pass
Rebuilding the stencil after a reinterpret (89fabe21fb) copied the whole
destination to a temp buffer and redrew the stencil from it in a pass of its
own. Tantalus games reinterpret about 70 times a frame, and on an M1 with
Vulkan that made MX vs ATV Untamed 44% slower (GPU bound).

Now a stencil variant of the reinterpret shader reads the source the same way
the color reinterpret does and draws the stencil from its alpha, into the same
rectangle right after it, so it lands in the same render pass and needs no
copy. One draw with stencil export, otherwise a clear and one per alpha bit.

The 1141 dumps in ppsspp-framedumps render identically before and after, on
Vulkan (export) and OpenGL (per bit) on macOS. Split Second, OutRun and
Ultimate Ghosts 'n Goblins dumps go through this path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 14:09:07 +01:00
Henrik RydgårdandClaude Opus 5.5 f1a76fde80 Docs: The Android version string no longer lags behind
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 09:24:33 +01:00
Henrik RydgårdandClaude Opus 5.5 32b67c0c55 CMake: Declare git-version.cpp as a byproduct of the GitVersion step
Ninja only knew git-version.cpp from its timestamp at the start of the
build, so when the GitVersion step rewrote it, the object wasn't rebuilt
until some later build happened to notice. An Android APK built right
after a commit could carry the previous commit's version string.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 09:24:03 +01:00
Henrik RydgårdandClaude Opus 5.5 9add5a78f3 Android: Report each frame's work to an ADPF performance hint session
Emulation does a burst of work each frame and then waits, so the scheduler
sees a mostly idle thread and moves it to slow cores at low clocks. On
Android 13+, report the frame thread's CPU time per frame against a target
of half a frame. CPU time leaves out the frame limiter's sleep and any
blocking on vsync or the GPU. Idea from Azahar.

Does nothing on devices without hint session support.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 09:04:26 +01:00
Henrik RydgårdandClaude Opus 5.5 445ecb46dc Android: Let Oboe pick the callback size, grow the buffer on underruns
setFramesPerDataCallback forced callbacks of PROPERTY_OUTPUT_FRAMES_PER_BUFFER
frames, which made Oboe add a block adapter holding back an extra buffer
whenever that doesn't match the burst. On a Galaxy S21 Ultra the MMAP stream
has a 96 frame burst against a 192 frame property. NativeMix takes any size.

The buffer was fixed at two bursts, 4 ms there, with nothing to recover from
underruns. Use Oboe's LatencyTuner, which starts at two bursts and adds one
per underrun, and log the underrun count when the stream closes.

Also take the lock when clearing the error and info strings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 09:04:26 +01:00
Henrik RydgårdandClaude Opus 5.5 1d477fa248 Android: Request unbuffered dispatch of touch and joystick input
Android batches touch moves and joystick axis events until the next UI
vsync, up to a frame of latency. On API 30+, ask for them unbatched.
Non-pointer sources only apply to the focused view, so the surface view
now stays focused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 08:52:24 +01:00
Henrik RydgårdandClaude Opus 5.5 5ea0921301 Ctrl: Let a press shorter than the sample interval be seen once
A press and release that both land between two sceCtrl samples were
lost. Now the next sample sees the button pressed. Idea from Azahar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 08:52:24 +01:00
Henrik Rydgård fc9ca4d1f7 Merge pull request #22885 from Kethen/aemu_postoffice_enet
bump aemu_postoffice
2026-11-01 23:05:31 +01:00
Katharine Chui 274da28e09 hasten aemu_postoffice enet pumping
this is to address long retransmission delays
2026-11-01 22:44:59 +01:00
Katharine Chui 13efba30c6 bump aemu_postoffice
- various bug fixes
- allow disabling enet when creating relay and adhocctl server objects
- pdp_peek_next_size can now be used to check whether a pdp session has no packet or an upcoming 0 size packet
2026-11-01 22:43:24 +01:00
Henrik Rydgård d0cb768568 Merge pull request #22875 from hrydgard/misc-fixes
HLE: Media and IO fixes from the review branches
2026-11-01 19:11:07 +01:00
Henrik Rydgård 0525608cb7 Merge pull request #22881 from hrydgard/savestate-discid-mounts
Savestates: disc ID and named mounts; headless can boot a state as-is
2026-11-01 18:42:12 +01:00
Henrik Rydgård 44f1f44be7 Merge pull request #22883 from Rularia/ice-test
MIPSAnalyst: Add Koori no Bohyou (NPJH50186/ULJS00247) picking pass readback (Follow-up to #22514 and #22610)
2026-11-01 17:34:27 +01:00
Rularia cc99fb01a1 Koori: rsingle source-buffer readback 2026-11-02 00:14:34 +08:00
Rularia 906fc16170 Update ReplaceTables.cpp 2026-11-01 22:42:55 +08:00
Henrik RydgårdandClaude Opus 5.5 bf2c81e37d Headless: Don't save states while running from a state without its game
The game runs without its disc there, so a state saved from it would keep that broken
environment. Saves are refused, and so is --save-state together with a state to boot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 15:41:23 +01:00
Rularia 70ab07755d Update ReplaceTables.cpp 2026-11-01 22:10:23 +08:00
Rularia 5c7632d99b Update MIPSAnalyst.cpp 2026-11-01 22:08:57 +08:00
Henrik Rydgård fb93fad41c Merge pull request #22880 from hrydgard/gamebutton-cleanup
GameButton code cleanup
2026-11-01 11:42:50 +01:00
Henrik Rydgård 7bbbe813e0 Merge pull request #22879 from hrydgard/dependabot/github_actions/actions/setup-java-6.1.0
build(deps): bump actions/setup-java from 6.0.1 to 6.1.0
2026-11-01 11:38:37 +01:00
Henrik RydgårdandClaude Opus 5.5 5c37b0d798 Headless: Count failed disc reads when booting a state, and benchmark such states
The count is opens of files missing from the disc, and reads and seeks on handles whose file
was dropped as the state loaded, from the load on. It tells how far a game booted without its
disc has strayed from its usual path. headless_bench.py takes bare .ppst files and directories
of them (--state-dir), and reports the count with the timings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 11:15:35 +01:00
Henrik RydgårdandClaude Opus 5.5 8122a5ec70 Headless: Boot a savestate without its game
Running a .ppst boots a placeholder program, with the disc ID and boot type peeked from the
state, then loads the state over it. An ISO game gets a disc with nothing on it, which the
mounts now load into by name. Meant for measuring performance with states that can be kept
without the games; the app still refuses to boot a state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 11:04:26 +01:00
Henrik Rydgård ec1246b221 Deduplicate text rendering code from GameButton 2026-11-01 10:49:59 +01:00