Run PS4 games natively on Linux.
psport is a PS4 compatibility layer for x86-64 Linux. It is not an emulator: it works the way Wine does for Windows programs. The PS4 CPU is x86-64, so a game's original executable runs directly on the PC's processor, with no instruction translation. psport loads the executable and the modules it links, provides the system libraries the game imports, and translates the game's GPU work to Vulkan.
psport is an independent project. It started from bbport, the native Linux port of Bloodborne, and builds on the video core and shader recompiler of shadPS4. It is being generalised from one game into a layer for any title; Bloodborne remains supported with its own game profile.
Important
No game files are included. The user needs their own dumps of the games they own. This project is not affiliated with Sony Interactive Entertainment, FromSoftware, AMD or the publishers of the titles listed below, and it is not related to shadPS4.
psport is under active development. A title is playable, experimental (it runs, but only a
limited part has been seen), broken (it starts but a core part fails) or not supported. The
state is how far a title has been seen to get, not a full play-through; what each title does is in
docs/en/GAMES.md. Every title is listed in
tools/regress/titles.txt and run headless with tools/regress.sh
(see Testing).
| Title | Title ID | State |
|---|---|---|
| Bloodborne (1.09) | CUSA03173 | playable |
| Atelier Ryza | CUSA16458 | playable |
| Atelier Ayesha DX | CUSA16921 | playable |
| Symphonia | CUSA50989 | experimental |
| Astrea | CUSA49515 | experimental |
| SaGa Emerald Beyond | CUSA43027 | experimental |
| ALTDEUS: Beyond Chronos | CUSA26563 | not supported |
| Gal Guardians: Demon Purge | CUSA41240 | experimental |
| Gal Guardians: Servants of the Dark (JP) | CUSA52187 | experimental |
| Call of Duty: Black Ops | CUSA57547 | experimental |
| Call of Duty: Black Ops II | CUSA57548 | playable |
| Blood Omen 2 | CUSA49769 | experimental |
| Onigiri | CUSA01458 | experimental |
| OCTOPATH TRAVELER 0 (JP) | CUSA53477 | broken |
- Titles that require PS VR (
require_ps_vrinparam.sfo) are not supported. - No tested title needs a dump of the console's system modules.
- Only one machine has been tested thoroughly: AMD Radeon RX 7900 XT with Mesa (RADV).
- OS: Linux on x86-64. Windows is groundwork that runs no game yet; its CI build is a test package with a probe that reports what the machine's GPU driver offers (Windows test guide).
- GPU: Vulkan 1.3 with descriptor indexing and buffer device address. The GPU path is the same for every vendor and chooses features by what the device reports, not by vendor. It is tested on AMD with RADV; NVIDIA and Intel are not verified yet (NVIDIA test guide).
- Games: the user's own dumps of games they own (the game folder with
eboot.bin,sce_module/andsce_sys/param.sfo). - Build tools, one of:
- Nix: when dependencies are missing,
build.shandrun.shenter shell.nix themselves. - Host packages: GCC (or another compiler through
CC), CMake, Ninja, pkg-config and the libraries inshell.nix(Vulkan, SDL3, FreeType, FFmpeg, Boost, glslang and the rest of shadPS4's video core dependencies; nlohmann_json, mbedTLS, zlib and miniupnpc for the optional online module).
- Nix: when dependencies are missing,
- Python 3 only for online play, building the online module (it writes the shadNet messages), the bundled launcher and the developer tools; a normal launch does not need it.
decanter is the recommended front-end. Its PS section
clones psport, builds it with build.sh, rebuilds it when the checkout moves and launches each dump
through run.sh (titles other than Bloodborne with PS_PERMISSIVE=1).
git clone --recursive https://github.com/yerasuu/psport.git
cd psport
bash build.sh # produces out/psport and out/gpu/libpsport-gpu.soWithout --recursive, build.sh fetches the submodule (Dear ImGui) itself.
| Build option | Effect |
|---|---|
PS_LTO=OFF |
disable link-time optimization (on by default) |
PS_NET=OFF |
leave out the online module (libpsport-net.so), as the public binary cache and bundle are built |
PS_PGO=generate|use|off |
profile-guided optimization; use by default when pgo/ holds a profile |
| ccache installed | the GPU library compiles through it, one cache for every checkout (~/.cache/psport/ccache, or CCACHE_DIR) |
nix-build packaging/port.nix builds the port from source in Nix's sandbox, with the online module;
--arg withNet false leaves it out.
PS_GAME_DIR=/path/to/CUSA03173 bash run.sh # Bloodborne
PS_GAME_DIR=/path/to/dump PS_PERMISSIVE=1 bash run.sh # any other titlerun.sh builds the port when needed, then starts the game.
| Variable | Effect |
|---|---|
PS_GAME_DIR |
the game folder; by default the only dump next to the checkout |
PS_PERMISSIVE=1 |
imports psport does not implement yet return 0 instead of stopping the game |
PS_DATA_DIR |
writable folder for build output (out/), saves and shader cache (user/) and psport.ini; by default the checkout |
PS_SYS_MODULES=<folder> |
optionally links the user's own dump of system modules (*.sprx) where psport has no library yet; nothing from it is shipped |
bash run.sh --software renders with Lavapipe (Mesa's CPU Vulkan driver) instead of the GPU.
In game, Insert or L3+R3 opens the overlay menu. Saves and the shader cache go to user/,
settings to psport.ini.
Each version tag vX.Y.Z is built by CI and published as a GitHub Release with a bundle that runs
without Nix: psport-<tag>-x86_64.tar.zst and its .sha256, made by
tools/bundle.sh. Extract it anywhere writable and run it with the host's own
Vulkan drivers:
PS_DATA_DIR=<writable folder> PS_GAME_DIR=/path/to/dump bash <extracted folder>/run.shThe bundle has no online module (libpsport-net.so) yet: it no longer links OpenSSL, abseil or
protobuf (Apache-2.0, which can't be distributed with psport's GPL-2.0) but mbedTLS under its
GPL-2.0-or-later option, and it stays out until online play over it is checked; until then online
play (PS_ONLINE=1) needs a build from source. It doesn't carry the
Vulkan loader either: it uses the host's libvulkan.so.1, so a host without one in its library
directories can't start it (NixOS keeps none in /run/opengl-driver/lib).
The same build, without the online module too, is published as a Nix binary cache, where decanter
fetches its prebuilt builds from; see FORK.md. A local build (build.sh,
nix-build packaging/port.nix) keeps the online module.
launcher/ holds the GTK4 launcher inherited from bbport, built around Bloodborne:
bash launcher/psport-launcher.sh starts it and bash launcher/install-desktop.sh adds it to the
application menu.
Settings live in psport.ini in the data folder (PS_CONFIG names another file). Most of them
are changed from the overlay menu, which writes the file. Commonly used keys and variables:
| Setting | Effect |
|---|---|
output_res |
output resolution; for a title with presets, sizes other than 1080p scale the scene |
upscaler (PS_UPSCALER) |
temporal upscaler, where the game's profile places it (upscaler notes) |
frame_gen (PS_FRAME_GEN) |
off (default) or fsr: FSR 3.1 frame generation, one generated frame per game frame, where the GPU has its prerequisites (--list-features row frame_gen_fsr); auto and dlss are not available yet and leave it off; read at start (frame generation) |
menu_language (PS_MENU_LANGUAGE) |
overlay language: en, es or ru |
game_mouse_sensitivity |
scale of the host mouse motion a game receives (0.05 to 20, default 1) |
mouse_pad_filter (PS_MOUSE_PAD_FILTER) |
on by default: mouse motion while a controller stick is pushed is dropped, since Steam's Desktop Layout or reWASD makes it from the stick and it would turn the camera twice; 0 keeps it |
PS_LANGUAGE |
the system language the game reads (1 English, 3 Spanish, 8 Russian) |
PS_FPS |
frame rate preset for titles that have presets (Bloodborne: 30, 60, 90, uncap) |
PS_ONLINE=1 |
online play through the title's community servers (online play) |
PS_MODS_ENABLED=0 |
disables file mods (mods and patches) |
PS_GAME_PROFILE=none |
runs without the game's profile, on the generic paths only |
PS_QUIRKS=none,-<id>,+<id> |
turns per-title or per-host fixes off or on (quirks) |
debug (PS_DEBUG=1) |
gathers each run's logs in one folder (PS_DEBUG_DIR, PS_DEBUG_KEEP; FORK.md, Diagnostics) |
toypad (PS_TOYPAD=1) |
plugs in the emulated LEGO Dimensions toy pad, off by default (toy pad) |
skip_movies (PS_SKIP_MOVIES=1) |
key.skip_movie (Escape) or pad.skip_movie (misc1) stops the movies playing, off by default (FORK.md, Keyboard) |
Defaults and why they hold for any game: FORK.md, Defaults. Diagnostic
variables and the call report: FORK.md, Diagnostics. System modules and
fonts (PS_SYS_MODULES, PS_HLE, PS_LLE, PS_SYS_FONTS):
FORK.md, System modules.
- Loader. A C loader reads the eboot and the modules it links (SELF or ELF) straight from the game folder, relocates and binds them into one image and jumps into the game's code.
- System libraries. psport implements them natively: a C runtime (memory, threads,
synchronization, files, audio, pad, saves, exceptions, services, user-level threads, modules
loaded at run time) and the libraries in
gpu/(GnmDriver, VideoOut, AvPlayer, Videodec2, Ngs2, Audiodec, Fiber, Font, PngEnc, PngDec, JpegDec). - Graphics. The GPU command stream and GCN shaders are translated to Vulkan by a renderer
derived from shadPS4's video core and shader recompiler (
gpu/shadps4/), as bbport extended it. - Game profiles. What is specific to one title (hooks and optimisations) lives in its profile
under
gpu/games/; every title runs on the generic paths without one. - Nothing silent. Before a game starts, every import without an implementation or answered by a stub is listed; calls that fail or do no real work are logged and counted in a call report.
Details: docs/en/ARCHITECTURE.md (components and launch flow) and FORK.md (what psport takes from other projects and what it changes).
tools/regress.sh <games root> runs every title in tools/regress/titles.txt in a headless
gamescope, with no window, no sound and none of the user's controllers. A pad schedule
(tools/regress/*.sched) drives each title, and the report says how far it got (loaded, entered,
initialized, first GPU frame, frames drawn, audio), its crash signature and how many unimplemented
imports it called. With -c <earlier results.json> it flags regressions. Usage and milestones:
FORK.md, Regression runs.
docs/en/ADDING_A_TITLE.md walks through running a new dump, reading its log and call report, implementing what is missing and checking the result.
- Fixes address the underlying behaviour; no game- or shader-specific hacks in the core.
- Optimisations for one title go in its profile (
gpu/games/<game>/), and every title must run correctly without one (PS_GAME_PROFILE=none). - A temporary fix one title needs is a declared, logged and disableable quirk (docs/en/QUIRKS.md).
- No tests in the repository: changes are checked with
tools/regress.sh; hardware tests, when needed, are OpenOrbis homebrew (tools/hwtest/). - Changes match the surrounding code; naming and the other conventions are in CLAUDE.md.
- Changes from bbport and shadPS4 are ported by hand, each recorded in FORK.md with its source commit.
tools/gcn_dis.sh disassembles GCN shaders.
| Path | Contents |
|---|---|
src/ |
entry point (src/main/), native loader and C runtime |
gpu/ |
GPU library: shadPS4 video core with bbport's changes (gpu/VENDOR.txt), PM4 decoder (cp/), memory module (layer/), ported libraries (fiber/, font/, pngenc/, pngdec/, jpegdec/), libSceNgs2 (ngs2/), libSceAudiodec (audiodec/), game profiles (games/), overlay and in-game menu (port/), DLSS bridge, online module (net/) |
scripts/ |
online.py (online addresses for PS_ONLINE=1) and sce_file.py for the Python tools |
launcher/, packaging/ |
bbport's GTK4 launcher; Nix package and AppImage script |
patches/ |
marks psport's folder; a title's built-in patch file comes from the launcher (PS_BUILTIN_PATCHES_DIR) |
tools/ |
regression runs, GCN disassembler, FSR 4 tools, scripted-run helpers, release bundle |
docs/ |
docs/en/ (architecture, bringing up a title, feature notes, bbport's history in English), docs/ru/ (bbport's Russian originals) |
- docs/en/ARCHITECTURE.md: components and the launch flow.
- docs/en/ADDING_A_TITLE.md: bringing up a new dump.
- docs/en/QUIRKS.md: the registry of fixes for one title, host or middleware.
- FORK.md: ported components, changes to inherited code, variables, call report, regression runs, CI.
- Feature notes: upscaler, parallel GPU work, motion vectors, mods and patches, profiling, toy pad.
- docs/en/history/: bbport's design notes, plans and change logs (Russian originals in docs/ru/).
psport is licensed under the GNU General Public License, version 2 (LICENSE). Files marked GPL-2.0-only in their headers are under version 2 only; the rest is GPL-2.0-or-later, used as version 2. It is maintained by Yerasuu.
| Project | What it provides | License |
|---|---|---|
| bbport by deadinside | psport's origin: native loader, HLE runtime, Vulkan renderer, everything for Bloodborne | GPL-2.0-or-later |
| shadPS4 | video core, shader recompiler, AvPlayer and other libraries carried by bbport; source of the libSceFiber and libSceFont ports and of the libSceNgs2 headers | GPL-2.0-or-later |
| AnyPS5 | behaviour read for the native libSceNgs2 and libSceAudiodec, no code | GPL-2.0-only |
Source commits and changes to inherited code are recorded in FORK.md and gpu/VENDOR.txt.
The license of every file and component, and what is taken from each fork (bbport, SrShadowy, Teefpyre, Supermedo, Mrsuss60, willl03 and AnyPS5), is detailed in LICENSES.md (machine-readable: LICENSES.json).
| Component | Used for | License |
|---|---|---|
| sirit | SPIR-V emission | BSD-3-Clause |
AMD GCN headers (gpu/third_party/gcn) |
GCN instruction decoding | MIT |
| half | half-precision floats | MIT |
xbyak 7.43 (gpu/third_party/xbyak, its headers) |
x86-64 code emitted at run time | BSD-3-Clause |
| FSR-Vulkan by FireBurn, AMD FidelityFX SDK | FSR 3.1 | MIT |
| LibAtrac9 | ATRAC9 audio decoding | MIT |
| Dear ImGui | overlay and in-game menus | MIT |
Tracy (submodule, fetched only for PS_TRACY=ON) |
profiling builds | BSD-3-Clause |
RenderDoc's in-application API header (gpu/third_party/renderdoc) |
one-frame captures | MIT |
cpp-httplib 0.45.0 (gpu/third_party/httplib), over its mbedTLS backend |
online module | MIT |
DLSS bridge (gpu/dlss_bridge) from Supermedo's Windows port, adapted from IFreemz/shadPS4-Bloodborne-DLSS-FSR |
DLSS | MIT |
| DejaVu fonts | overlay text, fallback for libSceFont | Bitstream Vera (DejaVu changes public domain) |
| dxil-spirv | building the FSR 4.1.1 assets on the user's machine | MIT |
The release bundle carries in lib/ the libraries psport links from Nix (the AppImage, in its Nix
store), each under its own license: FFmpeg (built as LGPL-2.1-or-later, without the GPL encoders
and the network protocols), SDL3, FreeType, fmt, xxHash, glibc, libstdc++ and their dependencies.
The bundle's THIRD-PARTY-NOTICES lists each of them, the libraries compiled in (Boost, xbyak,
Zydis, miniz, Vulkan Memory Allocator, ...) and the code above, with its license and the license
files of its source; SOURCES.txt says where the source of every GPL, LGPL and MPL component is,
with a written offer of the source valid for three years. Both are generated by
packaging/licences.nix. A build from source links the same libraries from the system or the Nix
shell (shell.nix).
Bloodborne patches by Kyo, Lance McDonald, auser1337, illusion, emoose and other community members.
They now ship with decanter (crates/ps/data/bloodborne/Bloodborne.xml), not in psport, which reads
them from the folder the launcher gives (--builtin-patches-dir, PS_BUILTIN_PATCHES_DIR).
No game files and no console system modules. AMD's FSR 4 DLLs and model data and NVIDIA's DLSS SDK
and libraries are not included either; the user provides them. The FSR 4 v07 assets aren't in the
bundle or the AppImage: tools/fetch_fsr4_assets.sh, which the checkout, the bundle and the
AppImage carry, downloads them on the user's machine into fsr4_shaders/ next to run.sh
(bash <extracted folder>/tools/fetch_fsr4_assets.sh for the bundle), or with
PS_FSR4_DIR=<data folder>/fsr4_shaders into the data folder, where run.sh and the launcher find
them; the AppImage's launcher shows that command for its own copy.