Commit Graph
48928 Commits
Author SHA1 Message Date
Henrik Rydgård 61e60ee6ff Merge pull request #22560 from eraycep/add-fading-chat-button
UI: Fade chat button with touch controls
2026-10-14 14:13:48 +02:00
Henrik Rydgård 836004e684 Merge pull request #22558 from hrydgard/cpu-equiv-6
CPU equivalence 6/6: ARM32 JIT fixes, and the docs
2026-10-14 14:06:49 +02:00
Henrik Rydgård 4e442b22b2 Merge pull request #22559 from hrydgard/game-browser-xmb-list
Game browser: Add a more XMB-like list format, make default
2026-10-14 14:04:34 +02:00
Henrik Rydgård bac8668204 Merge branch 'master' into add-fading-chat-button 2026-10-14 13:28:20 +02:00
Eray Cepni d970cf74f2 UI: Fade chat button with touch controls
Apply touch-control opacity to the chat button so it fades after
inactivity and reappears on touch. Keep it visible when touch controls
are disabled.
2026-10-14 14:20:33 +03:00
Henrik RydgårdandClaude Opus 5.5 66dc8972e8 GitLab CI: Only run libretro pipelines for master, tags and manual runs
Every mirrored branch was triggering the full libretro build matrix and
tying up their shared runners. Requested by the libretro team.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 12:49:35 +02:00
Henrik RydgårdandClaude Opus 5.5 d0e6e0a7c7 Docs: CPU equivalence state, including ARM32
Where the cores now agree, what the hardware tests answered, what's still
open (the NaN handling waits on the cpu-equiv-4 branch), and the ARM32 cores
as measured on a Galaxy S8+ and A21.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:29:57 +02:00
Henrik RydgårdandClaude Opus 5.5 48f9752235 ARM JIT: Leave matrix inits with a prefix to the interpreter, like the others
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:29:49 +02:00
Henrik RydgårdandClaude Opus 5.5 ad6f0ceea2 ARM JIT: Fix mtvc masking and vsgn of denormals, and interpret vh2f
mtvc masks the written control register like the other JITs, vsgn tests the
exponent (so a denormal gives 0, as in the interpreter), and the hardware
half-to-float conversion quiets NaNs, so vh2f goes to the interpreter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:29:49 +02:00
Henrik RydgårdandClaude Opus 5.5 0e908f466c ARM JIT: Gate VFPU ops on prefixes like the other JITs, and drop its vasin
The ARM32 JIT only checked for unknown prefixes, so a swizzle naming a lane
past the op's size, or a T prefix on vscl, read the wrong register or
asserted in VMOV. It now uses the ARM64 JIT's gates, and sends what they
refuse to the interpreter.

Its vasin was a polynomial approximation, not the bit-exact function the
other cores use (cpu/vfpu/exact failed 364 lines), so it goes to the
interpreter too, like vsin and vcos already did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:29:49 +02:00
Henrik RydgårdandClaude Opus 5.5 d7e449ab75 ARM JIT: Fix ins with msb below pos, ext past bit 31, and constant max/min
ins with msb below pos encoded an invalid BFI instead of doing nothing,
as the interpreter and the other JITs do, and ext with pos + size past 32
an invalid UBFX. max and min of two constants compared them unsigned.
Found by CPUEquivalence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:29:49 +02:00
Henrik Rydgård 21da437b79 Merge pull request #22557 from hrydgard/cpu-equiv-5
CPU equivalence 5/6: vmin/vmax ordering, vmfvc and vcmov fixes
2026-10-14 12:29:36 +02:00
Henrik RydgårdandClaude Opus 5.5 b025e9f819 VFPU: vcmov with imm3 = 7 tests a CC bit that is always clear
So vcmovt never moves and vcmovf always moves (cpu/vfpu/undefined). The
interpreter did nothing for either, and the JITs took it as imm3 = 6,
one CC bit per lane.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 11:59:35 +02:00
Henrik RydgårdandClaude Opus 5.5 1a9e06e2d6 ARM JITs: Write vmfvc's 0 for a control register past the defined ones
The register was mapped without MAP_DIRTY, so the 0 never reached it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 11:59:35 +02:00
Henrik RydgårdandClaude Opus 5.5 1f5e7e275b test.py: minmax_zero and minmax_tie pass now
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 11:59:35 +02:00
Henrik RydgårdandClaude Opus 5.5 9a08ff39be VFPU: vmin and vmax order zeros and denormals as equal, on every core
On the PSP, zeros and denormals all compare equal, a tie returns the
second operand, and the result keeps its bits (cpu/vfpu/minmax_zero,
minmax_tie, fcr31). The interpreter got the ties and NaNs right but
compared denormals as numbers, and each JIT had its own fast path with
host min/max, which returned the first operand on a tie and flushed or
not depending on the host's mode.

All cores now compare by vfpu_minmax_key(), an integer key that is 0
for a zero exponent and orders the rest by sign and magnitude, and
select the operand by it, without branching on NaN.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 11:59:35 +02:00
Henrik Rydgård c6bec7e12c Merge pull request #22555 from hrydgard/cpu-equiv-3
CPU equivalence 3/6: Decode shift and Allegrex bit op encodings as the PSP does
2026-10-14 11:47:10 +02:00
Henrik RydgårdandClaude Opus 5.5 753e869ca1 Search: Drop the focus from a view the filter hides
When a search stopped matching the focused game, it stayed focused while
hidden, so its background and music kept going.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 11:17:44 +02:00
Henrik RydgårdandClaude Opus 5.5 754e49c6d6 Game browser: Switch existing installs to the large list on Games and Homebrew
Their old grid setting is no longer migrated, so everyone gets the new
view there. Recent and Remote still keep theirs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 11:12:00 +02:00
Henrik RydgårdandClaude Opus 5.5 9fe0ab593b MIPSTables: Include <algorithm> and <string_view> for the dispatch generator
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 11:05:42 +02:00
Henrik RydgårdandClaude Opus 5.5 ce8f48980a Game browser: Default to the large list for Games and Homebrew, bigger folders
The old GridView keys are now read as ints, so a missing key can be told
apart from false. Configs without them get the new defaults, while
existing ones still migrate their choice.

Folders get taller lines in the large list too, though not as tall as
the games.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 11:00:00 +02:00
Henrik RydgårdandClaude Opus 5.5 ef72f27fea Game browser: Keep the search and focus when returning from a game
FocusGame cleared the path to focus right after setting it, so since
the refresh became deferred nothing got refocused. The refresh also
showed every game again while the search bar still showed the filter.

Now an existing button is focused directly, without a refresh, and a
refresh reapplies an active search filter.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 11:00:00 +02:00
Henrik RydgårdandClaude Opus 5.5 51ce3fbde9 test.py: shift_encodings and allegrex_encodings pass now
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:56:48 +02:00
Henrik RydgårdandClaude Opus 5.5 4849ef020e Decode the unused bits of shifts and Allegrex bit ops as the PSP does
srl/srlv rotate when the low bit of their unused field (rs or sa) is
set and shift when it's clear, whatever the other bits hold
(cpu/cpu_alu/shift_encodings). The interpreter treated values above 1 as
invalid and the other cores shifted.

The Allegrex bit ops decode only some bits of sa, so all 32 values are
one of wsbh, wsbw, seb, seh and bitrev (cpu/cpu_alu/allegrex_encodings).
AllegrexBitOp() gives the canonical one for every core. Special3
function 0x18 does nothing on the PSP, where it was decoded as an alias
of 0x20.

The interpreter dispatch is regenerated, and its generator now lists
each instruction name once. CPUEquivalence no longer skips the srl/srlv
encodings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:56:48 +02:00
Henrik Rydgård 5ca12f0050 Merge pull request #22554 from hrydgard/cpu-equiv-2
CPU equivalence 2/6: Run every core in the guest's rounding mode and flush-to-zero
2026-10-14 10:56:15 +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 43704b215c Game browser: Keyboard focus for the info button, more left padding
In the large list, right and left move between a game and its info
button, so up and down still step from game to game.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 10:45:12 +02:00
Henrik RydgårdandClaude Opus 5.5 7d273e178f Game browser: Info button in the large list, long press with buttons
Each line in the large list gets an info button, doing the same as a long
press or right click.

Holding the accept button now works as a long press in all view modes,
so it can be done from a gamepad.

Rename "Grid icon size" to "Icon size", since it now also applies to the
large list.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 10:33:04 +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 e93c1c389c Unit tests: Run the IR JIT on macOS too
It was left out of the JIT harness tests in 2024 for a crash nobody tracked
down, and runs fine on both arm64 and x86-64 Macs now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:01:44 +02:00
Henrik RydgårdandClaude Opus 5.5 90510d9e88 ARM JIT: Keep the guest's flush-to-zero in round, ceil and floor
They swap only the rounding mode bits in FPSCR now instead of resetting it,
which kept FZ off, so a denormal input is flushed like on the other hosts
(cpu/fpu/denormal).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:38:29 +02:00
Henrik RydgårdandClaude Opus 5.5 8d8948ee37 ARM JIT: round.w.s of NaN, and the guest's rounding mode after conversions
round.w.s gave 0 for a NaN instead of 0x7FFFFFFF like the other
conversions. round.w.s, ceil.w.s and floor.w.s reset FPSCR to
round-to-nearest and left it there, so cvt.w.s and the float ops after
them ignored the guest's mode (cpu/fpu/roundmode).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:38:29 +02:00
Henrik RydgårdandClaude Opus 5.5 b1b4f26b89 Docs: The JITs' rounding mode gaps are fixed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:26:48 +02:00
Henrik RydgårdandClaude Opus 5.5 b623183764 Unit tests: Add CPURoundingMode
Runs FPU math after a ctc1, and after a mode set from outside on blocks
compiled before it, on every core with and without ops left to the
interpreter, and checks the result against the interpreter. A fake syscall
checks that HLE always runs in the host's own mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:26:29 +02:00
Henrik RydgårdandClaude Opus 5.5 4f47475a69 Headless: Support --appendconfig
Merges the settings in an ini file over headless's own defaults, for runs that
need something like JitDisableFlags. Unlike in the app, the result is never
saved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:26:29 +02:00
Henrik RydgårdandClaude Opus 5.5 b44f61cba4 IR interpreter: Force the host's mode back in RestoreRoundingMode
A native backend can run this op through its generic fallback after its own
asm applied the guest's mode, which RestoreHostRoundingMode() doesn't know
about, so it has to clear the bits even when it didn't save them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:26:29 +02:00
Henrik RydgårdandClaude Opus 5.5 39813ffaf1 JITs: Notice a rounding mode that didn't come from a compiled ctc1
A JIT only switched modes around syscalls, and only took the mode into account
in conversions, once it had compiled a ctc1 (hasSetRounding). A mode from an
interpreted ctc1, a savestate made on another core, a core switch or a thread
switch went unnoticed, and HLE then ran in the guest's mode. UpdateFCR31()
now sets the flag when fcr31 isn't the default, and clears the block cache at
the next safe point, since blocks compiled before don't switch either. A new
JIT gets an UpdateFCR31() too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:26:28 +02:00
Henrik RydgårdandClaude Opus 5.5 241e781810 JIT: Switch rounding modes around interpreted ctc1 and syscalls only
Interpreted ops run in the guest's mode. A syscall left to the interpreter
(with JitDisable flags, say) is host code and now gets the host's mode, like a
compiled one, and an interpreted ctc1 to fcr31 now takes effect right away:
nothing set hasSetRounding for it, so the mode only reached the host at the
next time slice. Every other interpreted op skips the two calls it used to
make after it. The IR frontend's Comp_Generic, which the IR interpreter and the
IR native backends share, gets the same treatment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:26:28 +02:00
Henrik RydgårdandClaude Opus 5.5 4631c7b2f3 Save the host's FPU mode on apply, so restoring it is just a write
RestoreHostRoundingMode read the control register back to clear our bits, even
when nothing had been applied. Now ApplyHostRoundingMode saves the host's mode
the first time it changes it, and restore writes that back only if it did. With
the guest in the default mode, both are now just a flag check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:26:28 +02:00
Henrik RydgårdandClaude Opus 5.5 4b7baaf629 ARM32: Flush denormal inputs to float-to-int conversions under FS
ARM32's libm ceilf/floorf don't honor flush-to-zero, so the interpreters flush
the input themselves there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:26:28 +02:00
Henrik RydgårdandClaude Opus 5.5 f0c40e521d IR interpreter: Use the NEON Vec4 paths only on ARM64
ARMv7 NEON always flushes denormals and rounds to nearest, whatever FPSCR
says, so on ARM32 the scalar paths are used, which follow the guest's mode
like everything else.

The Vec4 ops only come from VFPU code, and the VFPU itself always rounds to
nearest and flushes denormals (cpu/vfpu/fcr31, see docs/cpu-equivalence.md),
so the NEON paths were arguably closer to the PSP there. But they disagreed
with every other host and core, and agreement between those comes first.
Running VFPU ops in the VFPU's own mode on every core would get both, and is
still to do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:26:28 +02:00
Henrik Rydgård 88f4c12437 Merge pull request #22553 from hrydgard/gpu-fallback-fixes
GLES and fallback rendering fixes from running the framedumps on Android
2026-10-14 09:20:38 +02:00
Henrik RydgårdandClaude Opus 5.5 ff5483a43e ARM32: Apply the guest's rounding mode and flush-to-zero in the interpreters
ApplyHostRoundingMode fell back to fesetround, which can't set FPSCR.FZ,
so the interpreter and IR interpreter didn't flush with FS set as every
other host does. FPSCR has the mode and FZ at the same bits as ARM64's
FPCR. Found with CPUEquivalence on a Galaxy S8+ running the armeabi-v7a
build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:49:00 +02:00
Henrik RydgårdandClaude Opus 5.5 7708f30d08 JIT: Run interpreter fallbacks in the guest's rounding mode
Comp_Generic restored the host's default mode around the interpreter call, so
an instruction the JIT doesn't compile rounded and flushed differently than in
the interpreter. Now the guest's mode stays in place, and is reapplied after the
call in case the instruction changed fcr31.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:49:00 +02:00
Henrik RydgårdandClaude Opus 5.5 f5ca0b7932 x86: Set DAZ along with FTZ for the guest's flush-to-zero mode
With FS set in fcr31, x86 flushed only denormal results (FTZ) while
ARM64's FZ also flushes denormal inputs, so the hosts disagreed whenever
a denormal reached an FPU or VFPU op. With DAZ too, x86 flushes the way
ARM64 does. That matches the PSP's VFPU, which always flushes inputs and
outputs (cpu/vfpu/fcr31); the PSP's FPU flushes only results
(cpu/fpu/denormal), which neither host does now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:49:00 +02:00
Henrik RydgårdandClaude Opus 5.5 5ea015a510 IR interpreter: Apply the guest's rounding mode in the dispatcher
It only applied fcr31's rounding mode and flush-to-zero after a ctc1 in
the same block, so add.s, mul.s, cvt and friends rounded to nearest in
every other block. It's now applied once per time slice in RunLoopUntil,
where the native dispatchers do it, and the host's mode is put back
around CoreTiming, compiling, syscalls and replacement functions.

See docs/cpu-equivalence.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:49:00 +02:00
Henrik Rydgård 4f4441bee1 Merge pull request #22551 from hrydgard/cpu-equiv-1
CPU equivalence 1/6: CPUEquivalence fuzzer, and the crashes and wrong code it found
2026-10-14 08:19:50 +02:00
Henrik RydgårdandClaude Opus 5.5 b555ba044e frametests: Add 13 dumps from ppsspp-framedumps
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:13:57 +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