Hardware: Ryzen 7 7800X3D + RTX 5070, Arch Linux, BlueZ 5.86. Everything below is what actually worked, including the gotchas.
Used the official prebuilt from the AUR (updates frequently, no Flatpak sandbox quirks):
yay -S --noconfirm rpcs3-binBinary lands at /usr/bin/rpcs3 (wraps /opt/rpcs3/usr/bin/rpcs3).
RPCS3 ships no firmware. Get the official PS3UPDAT.PUP from Sony and install it.
# current official firmware URL (v4.93) — from playstation.com/support PS3 system software page
cd /tmp
curl -L -o PS3UPDAT.PUP \
"http://dus01.ps3.update.playstation.net/update/ps3/image/us/2026_0318_a2b60b6ac1d2e49e230144345616927c/PS3UPDAT.PUP"
# install it (firmware install needs the GUI; --no-gui refuses)
rpcs3 --installfw /tmp/PS3UPDAT.PUPVerify (should be ~140 modules):
find ~/.config/rpcs3/dev_flash/sys/external -name '*.sprx' | wc -lPS3 game dumps come in two shapes:
- JB folder dump (
PS3_DISC.SFB+PS3_GAME/with a plainEBOOT.BIN) → already decrypted, just use it. No decryptor needed. - Encrypted redump
.iso+.dkey→ needs decryption. On Linux useps3dec(NOT the Windows-only PS3-Quick-Disc-Decryptor).
Example (Uncharted 2 was a JB folder inside a .rar):
mkdir -p ~/Games/PS3
unrar x -o+ ~/Downloads/Uncharted_2_Among_Thieves_BCUS98123.rar ~/Games/PS3/Then in RPCS3: File → Add Games → point at ~/Games/PS3/. Registers in ~/.config/rpcs3/games.yml by serial (e.g. BCUS98123).
The DS3 cannot pair like a normal BT device. Its internal "master" address must be set to your
adapter's MAC over USB first. BlueZ has a sixaxis plugin that's supposed to automate this, but on
BlueZ 5.86 the plugin loads and never fires on hotplug — so you must do it all manually.
Symptoms hit along the way:
- Controller LED 1 lit but never connected → its master was still set to an old host.
- After
sixpair, BlueZ accepted the ACL link but no HID input device appeared. - Root cause: BlueZ only pre-loads bonded devices at startup; a hand-written unbonded entry was ignored, so on connect it did fresh SDP discovery (DS3 returns a broken record) → no HID UUID → no joystick.
- Fix: pre-seed a correct HID SDP record in BlueZ's cache + a trusted device entry with the HID UUID,
set
ClassicBondedOnly=false, and disable L2CAP ERTM.
- Write this host's adapter MAC into the controller (hidraw feature report
0xf5). - Create a trusted-but-not-bonded device entry under
/var/lib/bluetooth/<adapter>/<pad>/info(Class=0x002504, HID service UUID00001124-..., no LinkKey). - Plant a correct DS3 HID SDP record in
/var/lib/bluetooth/<adapter>/cache/<pad>(fixesCould not parse HID SDP record). The hex is host-independent (it's the controller's descriptor). ClassicBondedOnly=falsein/etc/bluetooth/input.conf(DS3 is trusted, never bonds).options bluetooth disable_ertm=1in/etc/modprobe.d/bluetooth-ds3.conf(stops connect/disconnect flapping).
Then: unplug USB, press the PS button → connects, /dev/input/js* appears and stays.
Press PS anytime to reconnect (it's trusted; no agent needed). One DS3 = one player; the 4 LEDs are
just player-slot indicators (1–4), not 4 devices. A 2nd player needs a 2nd physical controller (run the
same script with it plugged in).
Auto-detects the adapter MAC + controller node, so it works on any machine (e.g. a ThinkPad too). Run with the pad plugged in via USB:
sudo ./ds3-bluez-setup.sh(Full script is the second file in this gist: ds3-bluez-setup.sh.)
RPCS3 logs Failed to set RLIMIT_MEMLOCK size to 2 GiB. Default was 8 MB. Raise it (needs reboot/re-login):
# PAM
echo '* soft memlock unlimited
* hard memlock unlimited' | sudo tee /etc/security/limits.d/99-rpcs3-memlock.conf
# systemd (this is the one that governs GUI/graphical-session apps)
sudo sed -i 's/^#DefaultLimitMEMLOCK=.*/DefaultLimitMEMLOCK=infinity/' /etc/systemd/system.conf
sudo sed -i 's/^#DefaultLimitMEMLOCK=.*/DefaultLimitMEMLOCK=infinity/' /etc/systemd/user.confPer-game config lives at ~/.config/rpcs3/config/custom_configs/config_<SERIAL>.yml
(copy the global config.yml then edit). Settings from the RPCS3 wiki for this title:
| Setting | Value | Why |
|---|---|---|
| Renderer | Vulkan (RTX 5070) | — |
| Write Color Buffers | On | fixes overly-bright scenes |
| Read Depth Buffer | On | fixes flickering; needed by async streaming |
| Asynchronous Texture Streaming | On | perf |
Resolution scale threshold (Minimum Scalable Dimension) |
160 | fixes bloom artifacts when upscaling |
| ZCULL accuracy | Precise (default) | reflections / heat-wave |
| Anisotropic filter | Auto (default) | anything else glitches |
| Resolution Scale | 200–300% | RTX 5070 has tons of headroom at native 30fps |
The wiki's "highly recommended" patches (Disable SPU Post-processing / Disable Mesh Trimming /
Enable GPU Lighting) caused a fatal Unknown/Illegal opcode PPU crash (~3:30 in, during level load)
on this RPCS3 build. Clearing the cache did not help. Disabling all patches = stable.
# disable all patches
sed -i 's/Enabled: true/Enabled: false/g' ~/.config/rpcs3/patch_config.ymlTo force a clean recompile after changing patches/settings, clear the game cache:
rm -rf ~/.cache/rpcs3/cache/<SERIAL>/ppu-* ~/.cache/rpcs3/cache/<SERIAL>/spu-*- 30fps is full speed. Uncharted 2 is a native 30fps game; there is no 60fps unlock patch for serial BCUS98123. A locked, steady 30 = the game running perfectly.
- White boxes/rectangles = shaders still compiling (Shader Mode: Async Recompiler). Objects render as white placeholders until their shader builds in the background, then pop in. They cache out as you play and don't return on revisits. (Only the Disable SPU Post-processing patch + 100% scale causes persistent white boxes — and that patch is off.)
yay -S --noconfirm rpcs3-bin
curl -L -o /tmp/PS3UPDAT.PUP "<sony firmware url>"
rpcs3 --installfw /tmp/PS3UPDAT.PUP
unrar x game.rar ~/Games/PS3/ # JB folder dumps need no decryption
sudo ./ds3-bluez-setup.sh # DS3 over Bluetooth (pure BlueZ)
# memlock + per-game config as above; leave Uncharted 2 patches OFF