UFC 3 — native PS4 port for Linux and Windows
UFC 3 is a native PC port of EA Sports UFC 3 for PlayStation 4 that runs on Linux and Windows with Vulkan.
- Type: PC port
- Game: EA Sports UFC 3
- Runs on Windows and Linux
- By GNSB
- Latest release ufc3-v0.1.14, 2026-10-21
- Source: https://github.com/GNSB/UFC-3-PS4-PORT-LINUX-WINDOWS
README
UFC 3 — native PS4 port for Linux and Windows
EA SPORTS UFC 3 (PlayStation 4, CUSA06534, update 1.14) running as a native x86-64
program on Linux and Windows. This is not a CPU emulator: the game's original code runs directly
on the PC's processor, a dedicated runtime replaces the PS4 system libraries, and a renderer
derived from shadPS4 translates the PS4's GPU work to
Vulkan.
It is built on SacredFire (Crash Team Racing: Nitro-Fueled), which itself comes from bbport, the native Bloodborne port. All code is GPL-2.0-or-later.
No game files are included. You need your own dump of UFC 3 (
CUSA06534) and its 1.14 update. This project is not affiliated with or endorsed by Electronic Arts, Sony Interactive Entertainment or the UFC. EA SPORTS UFC, PlayStation and related marks belong to their owners and are named only to identify the game.
Status
Current release: 0.1.9 (notes). What's new since 0.1.6:
- 0.1.9: the real fix for the slow Career menu after the 2nd belt (PR #41 by @nomadsdad), a
clean exit on Windows (PR #42), and a version check in every log (
VERSION MISMATCHwhen an install mixes versions). - 0.1.8:
- a controller can disconnect and reconnect without crashing the game;
- blood and sweat are fixed with
BB_WRITE_WINDOW=2; - old cached textures are freed, so FPS should no longer go down over long sessions.
- 0.1.7: two Career crashes are fixed (entering Career or loading a save after a title fight, and moving the Create Fighter sliders), and the launcher explains when the CPU is too old.
Playable. Menus, loading, fights (including the menu's attract-mode fight), sound, controller and saves. What works today:
- Career: it saves, and saves made after a title fight load again. It no longer crashes on entry or when you move the Create Fighter sliders or change presets. Changing hair/head repeatedly in the fighter editor no longer hangs the GPU, and the menu stays fast after you win belts.
- Blood and sweat on hits, with the created fighter's skin still correct.
- PS4 Pro mode (the game renders 1080p instead of 900p), with a checkbox in the Windows
launcher (
BB_NEO=1on Linux). - 2K / 4K (experimental): 2560x1440 and 3840x2160 internal resolution in the launcher (validated on Linux only; see Launcher settings).
- 90 FPS in the launcher's FPS limit, next to 60 / 120 / 144 / 240 / Unlimited.
- Hair and beards with proper coverage instead of square cards.
- Created-fighter skin that survives repeated editing (no black or garbled patches).
- Shadows without acne or flicker from the emulated depth format.
- Career portraits and the post-fight screen: your fighter shows up on the post-fight menu, in the career pause menu and on the Saved Careers cards.
- Game language selector in the Windows launcher.
- Launchers on both systems (Windows: UFC3.exe; Linux: a GTK launcher), with Offline / Join server / Host server.
- Online between friends (private hosting, rematch included); see Online.
| Scene | Linux · Ryzen 5 5600 + RTX 4070 | Windows · Omen 16 (RTX 3060 Laptop, 6 GB) |
|---|---|---|
| Menus / loading screens | 240 FPS (the game's own cap) | 240 FPS (Immediate present mode) |
| Career fight, no FPS limit | — | 60–70 FPS (0.1.5, write windows on, log folder on a local disk) |
| Fight, no FPS limit | 137–196 FPS (write windows on) | 66–83 FPS (0.1.4, a Quick Fight without write windows) |
| Fight, 120 FPS limit | steady 120 FPS | — |
- Tested by the maintainer on NVIDIA (Linux and Windows); AMD fixes come from @luscamovi's RX 9070, and players have reported on other AMD and NVIDIA cards (RX 7800 XT, RTX 4090…).
- Write windows (a faster CPU/GPU memory path, see Performance) are on on both Linux and Windows since 0.1.5: UFC-48 fixed the Windows heap corruption of 0.1.4.
Known issues
- Fights on Windows still run below Linux.
- Keep the log folder on a local disk for the best FPS.
- "Clear the shader cache at start" recompiles every shader on each start: leave it off.
- The 0.1.8 fixes (Career menu FPS, controller reconnect, blood/sweat in mode 2, long sessions) were checked with tests and code review, not yet by many players: if one does not fix your case, please reopen the issue with the new log.
- The 2K/4K internal resolutions are still experimental. If the game crashes with one of them, try again without it before you report the crash.
- Moving the window to another monitor during startup can crash the NVIDIA driver
(
Swapchain::Destroy). - Some long hairstyles leave a slightly lighter line at the base of the neck.
- Portuguese (Portugal) (
BB_LANGUAGE=7) is listed but the game has no text for it: pick Portuguese (Brazil) (17).
Requirements
-
x86-64 CPU with AVX2, BMI1, MOVBE and LZCNT (Intel Haswell / 4th-gen Core or newer, or AMD Ryzen). Older CPUs with only AVX (Sandy/Ivy Bridge, Xeon E5 v1/v2) are not supported yet.
-
GPU with Vulkan 1.3. ≥ 6 GB of VRAM recommended (below that a more aggressive texture collector kicks in).
-
A dump of the game: the
CUSA06534base folder and the 1.14 update, for example:PS4/CUSA06534 (base game, eboot.bin) PS4/CUSA06534-patch (1.14 update; -PATCH, -update, _patch… also work)scripts/merge_update.pymerges them automatically intoCUSA06534-mergedusing hard links (no extra disk space; on drives without hard links the files are copied).
Windows
- Download the zip from Releases (or build it, see Building) and extract it.
- Open
UFC3.exe. Pick theCUSA06534folder (the base game; an update next to it is detected automatically) and press Play. - On first launch the game is prepared (a few seconds) in
%LOCALAPPDATA%\UFC3Native. Each session's log goes to%LOCALAPPDATA%\UFC3Native\logs\; the launcher's Open logs folder button opens it. If the game crashes, send us that session's.log(with Frame statistics checked if you can reproduce it).
Launcher settings (God of War III port style)
Since 0.1.5 the launcher has a UFC 3 dark/gold look, with your dump's own artwork in the banner.
| Setting | Values | Notes |
|---|---|---|
| Player name | text (16 ASCII characters) | The name the game shows. |
| Game language | English (US), French, German, Italian, Spanish (Spain / Latin America), Portuguese (Brazil / Portugal), Polish, Russian, Japanese, Chinese (Traditional) | BB_LANGUAGE. Portugal has no text in the game: use Brazil. |
| Controls... | per PS4 input | Keyboard key (click, then press it) and gamepad button. Saved to bbport.ini. |
| Online play | Offline / Join server / Host server | Join: the host's address in Join address. Host: pick this PC's address in Host address (Rescan, Copy IP to share it); the server starts with Play and stops with the game. See Online. |
| Game resolution | 720p / 1080p / 2560x1440 (2K, experimental) / 3840x2160 (4K, experimental) | What the game renders. 2K/4K use PS4 Pro mode with a 4K output; in game choose VIDEO → RESOLUTION → Favor Resolution (the option only appears in these modes). Validated on Linux only. |
| Display resolution | Same / 1080p / 1440p (2K) / 4K | Window size; the game's frame is scaled to it (use FSR 1.0 + sharpening). Fullscreen uses the monitor's size. |
| PS4 Pro mode | on / off | BB_NEO: the game renders 1080p instead of 900p, at a lower frame rate. |
| FPS limit | 60 / 90 / 120 / 144 / 240 / Unlimited | Saved by value; the game never goes above 240. |
| Present mode | Mailbox / VSync (FIFO) / Immediate | On NVIDIA, Mailbox stops at 2× the monitor's refresh rate; Immediate reaches 240 (may tear). |
| Upscaling | Off / AMD FSR 1.0 | For an internal resolution below the monitor's. |
| Sharpness (RCAS) | Off / Low / Medium / High | |
| FPS counter | on / off | Top left. |
| Frame statistics | on / off | Periodic FPS, readback and (on Windows) memory figures in the log; useful in crash reports. |
| Clear the shader cache at start | on / off | Recompiles every shader on each start: leave it off. |
| Log folder | a folder (empty: %LOCALAPPDATA%\UFC3Native\logs) | Where the run logs and frame/readback CSVs go; BB_LOG_DIR wins over it. A network drive works, but a local disk gives the best FPS. |
Environment variables you already have set take precedence over the launcher (for example a
.bat with set BB_WRITE_WINDOW=2 before starting UFC3.exe). Since 0.1.7 you no longer need
BB_WRITE_WINDOW=0 to avoid the Career crashes.
Linux
# dependencies: C/C++ compiler, CMake, Vulkan, SDL3 and Python 3 (see shell.nix / build.sh)
git clone <this repo> ufc3 && cd ufc3
git submodule update --init --recursive
bash build.sh # builds the runtime + renderer
python3 scripts/merge_update.py /path/PS4/CUSA06534 # base + 1.14 -> /path/PS4/CUSA06534-merged
BB_GAME_DIR=/path/PS4/CUSA06534-merged bash run.sh # defaults to orig/CUSA06534
run.sh detects the ufc3 profile and applies the game's defaults; any variable can be
overridden on the command line (BB_FPS_LIMIT=0 bash run.sh).
There is also a GTK 4 launcher (game folder, player name, language, resolution, Offline / Join /
Host) that needs Python PyGObject and GTK 4: python3 launcher/ufc3_launcher.py from the repo,
or ./ufc3.sh with no arguments in the Linux package (./ufc3.sh --play /path/to/CUSA06534
plays from the command line). Logs go to ~/.local/share/UFC3Native/logs/.
Linux AppImage
Download the Linux AppImage from Releases, then:
chmod +x UFC3Native-x86_64.AppImage
./UFC3Native-x86_64.AppImage # GTK launcher; close it without Play to test
./UFC3Native-x86_64.AppImage --play # saved settings, same arguments as ufc3.sh
Release assets include the version in the filename; substitute that name above.
Like the tar.gz, this requires glibc 2.38+, system Python 3 and, for the launcher,
PyGObject + GTK 4 (python-gobject gtk4 on Arch; python3-gi gir1.2-gtk-4.0 on
Debian/Ubuntu). Python runs the bundled preparation scripts and private online server;
Python and GTK are not bundled. Vulkan and the window system also come from the host.
Normal AppImage mounting needs FUSE 2 (libfuse2t64 on Ubuntu 24.04), or use
./UFC3Native-x86_64.AppImage --appimage-extract-and-run without FUSE.
The mounted image is read-only: settings, prepared files, saves and logs remain in
~/.local/share/UFC3Native (respecting XDG_DATA_HOME and BB_DATA_DIR, plus
BB_LOG_DIR for logs). Keep your game dump/update outside the image; merging the
update creates a sibling CUSA06534-merged directory as with the tar.gz.
To package, build with ufc3-build, run bash scripts/package-linux.sh, then
bash scripts/package-appimage.sh. The latter wraps the existing tar.gz unchanged and
writes dist/UFC3Native-x86_64.AppImage and its .sha256. Install appimagetool on
PATH, or set APPIMAGETOOL=/absolute/path/to/appimagetool; an executable x86_64
appimagetool AppImage works too, without FUSE on the build machine. No tool is downloaded
automatically; a missing tool produces an installation hint. Use BB_ALLOW_DIRTY=1
when making the tar.gz from an uncommitted local test build. Releases publish all three
packages with SHA-256 checksums.
Online (experimental)
Private hosting between friends: one player runs the server on their own PC, with no public matchmaking. Either Windows or Linux can host, and the two PCs may run different systems; both need the same port build and the same game dump/update.
- The host picks Host server in the launcher, selects their address, shares it (Copy IP) and presses Play. The friend picks Join server, enters that address and presses Play.
- Both enter Online → Quick Fight and search at about the same time. Rematch works.
- Outside your LAN, use a VPN such as Tailscale on both PCs and share the
host's VPN IP (never
127.0.0.1).
Step by step: docs/ufc3/HOW-TO-PLAY-ONLINE.md; ports, logs and
troubleshooting: docs/ufc3/ONLINE-HOSTING.md.
Advanced: the launchers set BB_ONLINE_SERVER=<host address> for the game (without it the
console stays offline). An inherited BB_ONLINE_SERVER overrides the launcher's Offline/Join
choice. You can also run the server yourself (python3 tools/ufc3_server.py --bind 0.0.0.0)
and have both players use Join server. BB_NET_LOG=0 silences the network log (on by default in
this mode). Details: docs/ufc3/ONLINE_IMPLEMENTATION.md.
Building the Windows zip (on Linux)
bash scripts/build-windows.sh # llvm-mingw cross-compile, LTO on
BB_ALLOW_DIRTY=1 bash scripts/package-windows.sh
# -> dist/UFC3Native-windows-x86_64.zip (UFC3.exe, bin/, embedded Python, scripts/)
Publishing a release
Write the notes in docs/ufc3/releases/<version>.md, commit, then:
bash scripts/release.sh <version> # tags ufc3-v<version>, builds, packages, pushes, creates the GitHub release
Key environment variables
| Variable | UFC 3 default | What it does |
|---|---|---|
BB_FPS_LIMIT | 0 on Windows (unlimited; the launcher offers 60/90/120/144/240), 120 in run.sh | FPS limit (0 = none). |
BB_GUEST_FPS_LIMIT | 0 | FPS limit applied to the game's own frame loop (once per frame in sceGnmSubmitDone), instead of holding finished frames in the flip queue as BB_FPS_LIMIT does: the next frame reads the pad after the wait, so the limit adds no input latency. With BB_FRAMES_AHEAD=1 it lowered the GPU wait per frame from 4.7 to 1.9 ms on a GTX 1650. |
BB_NEO | 0 (launcher: "PS4 Pro mode") | PS4 Pro mode: the game renders 1080p instead of 900p (about 80 FPS in fights on an RTX 4070). |
BB_PRESENT_MODE | Immediate (Windows) | Mailbox, Fifo or Immediate. |
BB_VBLANK_HZ / BB_FLIP_RATE | 480 / 0 | The game asks for 30 Hz; with flip rate 0 and a high virtual vblank it runs at the real rate (the simulation follows real frame time). |
BB_READBACKS / BB_READBACK_LINEAR | 2 / 1 | Precise reads of GPU-written memory (without them the fight renders black, as UFC 4 does in shadPS4). |
BB_WRITE_STEP | 1 | CPU writes next to a few GPU-written bytes are single-stepped instead of waiting for the GPU; write windows need it. Validated on Windows (UFC-48 coherent windows) with correct created/career skin. |
BB_WRITE_WINDOW | 1 (run.sh and the Windows launcher, since 0.1.5) | Pages shared by CPU and GPU data stay open for the CPU until the game's next submission; then only what changed is uploaded (see Performance). The 0.1.4 Windows heap corruption is fixed by UFC-48's coherent windows (validated on an RTX 3060: second fight and contract without a crash). BB_WRITE_WINDOW=0 turns it off. BB_WRITE_WINDOW=2 opens a window only when the faulting write's exact bytes are known (a guest memcpy/memmove/memset, or a guest store decoded as one plain store) and they do not cover GPU bytes; any other write is handled as with 0 (single step or readback). It removes the per-frame readbacks of the Map(WRITE_DISCARD) + memcpy at guest +0x431c4f and the stores at +0x4219b8 (see docs/ufc3/WINDOWS-EXACT-WRITE-WINDOWS.md). Since 0.1.8 mode 2 no longer overwrites GPU data next to a CPU write, which broke blood and sweat. |
BB_PREUPLOAD | 1 | Background upload of rewritten game memory into VRAM (1 = resident memory, 2 = all of it). Restores blood/sweat on hits (UFC-49); validated on Linux and Windows. A user-set value overrides the default. |
BB_ALPHA_TO_MASK | on | Hair/beard coverage (DB_ALPHA_TO_MASK emulated as a shader dither). 0 turns it off; coverage uses Vulkan alpha-to-coverage on MSAA targets; colourmap limits it to draws sampling the hair colour map (Create Fighter only). |
SHADPS4_BC_MODE | 3 | GPU-compressed textures go through memory (created-fighter skin). 0 restores the older compressed-view/copy behaviour, for comparison. |
BB_T4_PRESERVE_ALIAS | 1 | Keeps the portrait the game draws into a larger render target when it re-reads it at the portrait's size (post-fight fighter, career portraits). 0 disables it. |
BB_LDS_ORDER | 1 | Subgroup memory barriers around shared-memory (LDS) stores in translated shaders, which the GCN code expects (octagon floor grain on AMD). 0 turns them off; clear the shader cache when changing it. |
BB_GPU_WRITE_TWINS | 0 | Incompatible with precise readbacks (deadlock). |
BB_INTERNAL_WIDTH/HEIGHT, BB_FSR1, BB_RCAS | from the launcher | Internal resolution and upscaling. |
BB_WINDOW_SIZE | from the launcher | Window size (2560x1440, 3840x2160…); the game's frame is scaled to it. |
BB_SKIP_MOVIES | 1 | The EA intro and the first-start video play a short black clip (share/skip_movie.mkv). |
BB_USER_NAME | Player 1 | The PS4 user name the game shows (16 bytes). |
BB_LANGUAGE | 1 (launcher: "Game language") | The PS4 system language: 1 English (US), 2 French, 3 Spanish (Spain), 4 German, 5 Italian, 0 Japanese, 7 Portuguese (Portugal; the game has no text for it), 8 Russian, 10 Chinese (Traditional), 16 Polish, 17 Portuguese (Brazil), 20 Spanish (Latin America). |
BB_FRAME_STATS | 1 in run.sh | Periodic statistics in the log (FPS, µs per draw, readbacks, write sites…). |
BB_UI_BACKPRESSURE | 1 | A UI scene built 8 times since the last frame waits for the next frame, up to 250 ms. This fixes the Career crash in the "UI Update" thread (0.1.7). 0 turns it off. |
BB_APPEARANCE_BACKPRESSURE | 1 | When the fighter appearance pool is full, the game waits up to 250 ms for an entry to be freed. This fixes the Create Fighter crash (0.1.7). 0 turns it off. |
BB_DEPTH_AS_COLOR_REUSE | 1 | A shadow map read as color is converted only again after it changes, instead of at every draw. This fixes the slow Career menu after winning the 2nd belt (0.1.8). 0 converts at every draw, as before. |
BB_GC_STALE_SECONDS | on | Frees cached textures that the game overwrote and that were not used for 60 s, even when memory use is low (0.1.8). N (1–63) changes the number of seconds; 0 turns it off. |
BB_GROWTH_SECONDS | 60 | How often the log prints a Growth line with cache sizes, memory and FPS. 0 turns it off. |
There are also purely diagnostic switches (*_TRACE, *_SKIP, *_DRAWS…); they are described
in the release notes.
How it works
- Native execution.
eboot.binis converted offline (scripts/prepare.py,link_libc.py,link_modules.py) into a flat memory image with the game's own PS4 libc andlibSceFios2linked in as native code. TLS accesses (fs:) are rewritten (gs:on Linux, the TEB TLS slot on Windows). - Runtime (
src/runtime_*.c): memory, threads, mutexes/semaphores/event flags, files, audio (ATRAC9, and MP3 for AJM), controller (SDL), saves, user services and network/online stubs. On Windows: SRWLOCK-based mutexes, high-resolution timers,timeBeginPeriod(1), raised priority and EcoQoS disabled. - GPU (
gpu/): an adapted shadPS4 renderer. PM4 commands are decoded on one thread and draws are recorded into Vulkan on another (a two-stage pipeline), helped by draw-preparation and recording threads. GPU-written memory is page-protected so CPU