A desktop app for macOS and Windows that packs, converts, patches, backports and signs PS5 games, builds installable .pkg files, and checks and fixes PS4 and PS5 packages. You add a game folder, an archive, a disk image, a .ffpfs/.ffpfsc or a .pkg, pick what should happen to it and what should come out, and the queue works through it.
The app used to be called PS5 FFPFSC ULTRA.
If you like what I do, you can buy me a coffee*:
*It doesn't have to be a big donation. A few cents show me who uses the tool and cares about where it goes next. That keeps me motivated, and I know I'm not coding for the bin ;)
Grab the latest build from Releases.
- macOS 26 or newer on Apple Silicon (every M1 or later Mac can update to it for free): unzip and start the app. The app is only ad-hoc signed, so if macOS refuses to open it, run this once:
xattr -dr com.apple.quarantine "PS5 UltraPack.app" - Windows x64 (preview): unzip and start
PS5 UltraPack.exe. SmartScreen will warn on first start because the exe isn't signed ("More info", then "Run anyway"). Everything works on Windows 11 in my tests, but I haven't tried a package built on Windows on a console yet.
![]() Queue |
![]() Add job |
![]() A folder with PS4 and PS5 games |
![]() Auto output in Settings |
![]() A PS4 package that needs a fix |
![]() PS4 PKG Tools |
![]() A PS5 package that needs a fix |
![]() PS5 PKG Tools |
![]() Light mode |
|
Older versions of the UI are in docs/screenshots.
Inputs: a decrypted game folder (eboot.bin + sce_sys/param.json), a folder full of games (one job each), ZIP/RAR/7z archives including multi-part RAR sets and encrypted headers, .exfat/.ffpkg disk images, .ffpfs, .ffpfsc, and PS5 or PS4 .pkg files.
Outputs: .ffpfsc (compressed), .ffpfs (uncompressed, faster to mount), .exfat (an exFAT image with 64 KiB clusters, which ShadowMountPlus reads fastest from USB), an installable .pkg, a plain folder, or "Organize", which files the source into your library as it is. Auto picks one of these per source: you set in Settings › Compression what a game folder, an image or a .pkg turns into, and an archive counts as what it holds.
On the way a job can integrate a patch, backport the game to an older firmware, fake-sign the executables and, for games that load through AMPR, put their data into LZ4 asset packs, in that order. The packs make the game about half the size and are read by drakmor's ampr_emu, which the app puts into fakelib/; "Unpack LZ4" is the way back. All of that happens on a working copy. Your source only changes if you ask for it (signing or backporting a folder in place), and if a patch job on your own folder fails, the patch is rolled back.
Some things that make day-to-day use easier:
- Archives can go straight in. Saved passwords are tried first, and the app only asks if none of them works. The queue shows what an archive holds (
.pkg, Folder,.exfat) instead of.rar. An archive with several games in it is unpacked once and each game gets its own job. - A folder with PS4 and PS5 games side by side gives one job each, and the two platforms get their own output folder. Each "Save to" field remembers the folders you last used for that platform.
- A download folder with one game and a folder of add-ons next to it gives one job. After the game is done, its DLC and updates are unpacked and sorted into the game's title folder in the library, and anything else in the folder is copied next to the output. The add-ons don't show up as jobs of their own.
- Output files are named from the game itself:
<Title> [PPSA12345] [v01.200] [fw8.00].ffpfscin a folder per title. The firmware tag comes from the SDK version ineboot.bin. Names stay within ShadowMountPlus's length limit. - Extras that come with a release (notes, checksums, backport files, DLC folders) don't go into the image, but they aren't thrown away either. They end up next to the output. macOS and Windows junk like
.DS_Store,._*andThumbs.dbis dropped. - Work is spread across drives. The image is built on your fast temp SSD and the result is written to the output drive. If the SSD is too small, the app splits the work or falls back to the output drive. A job that won't fit is skipped up front, with the numbers, so it doesn't fail halfway.
- The queue keeps its order, can be rearranged by drag and drop, and shows overall progress and time left. Failed jobs stay in the list and can be edited and retried. Pause lets the running job finish first.
- After a job the source can stay, go to the Trash, be moved somewhere or be deleted.
The app builds PS5 debug fake packages natively, without Wine or Sony's DLL. It uses drakmor's LibProsperoPkg, wrapped in a small .NET tool that ships with the app.
I've tested this on a retail PS5 on firmware 11.60 with kstuff-lite: both homebrew and a retail game built this way install and launch, and the game keeps its saves. Which firmware a package runs on depends on the jailbreak, not on the builder.
- Any input can become a
.pkg. Content ID, title ID, version and title are read from the game'sparam.json. If a folder has none, "More options" asks for them. - The app fixes common problems in the working copy before building, such as icons in the wrong format, stale DDS files or a PlayGo set that doesn't match the files. A broken
param.jsonor an emptyeboot.binstops the build with a message. - Every build is checked afterwards (container, signatures, PlayGo, images, license, NP files, versions, eboot). If something is off, the log tells you which check failed.
- Compression uses Kraken, level -4 to 9 (default 0). Higher levels take a lot longer for very little gain.
- It also works the other way round: a
.pkgwith "Folder" as output unpacks the whole game includingsce_sys. Building that folder again gives the same file byte for byte.
![]() Backport in Add job |
![]() Settings › Backport & libraries |
A backport lowers the SDK version the game declares in eboot.bin and its modules. If the older firmware is missing functions the game uses, the game also needs patched system libraries in its fakelib/ folder, which ShadowMountPlus loads instead of the system ones.
The app does the SDK part itself, also on fake-signed files (only the two SDK values inside the signature change). It doesn't ship any system libraries. You extract them from your own firmware, and the app can apply the public patches for you.
| Target | Notes |
|---|---|
| 7.61 | Public library patches exist. This is the usual route. |
| 6.02 | Experimental, smaller patch set, only some games run. |
| 10.xx | SDK only, for games slightly newer than the console. |
| Any firmware in your folder | SDK values taken from that firmware's own libraries. |
How to set it up:
- In Settings › Backport & libraries, point the app at a folder with one subfolder per firmware (
7.61,9.60,10.01, …), each containing that firmware's original libraries. Each subfolder shows up as a target. - Put your 10.01 libraries in the
10.01folder, choose an output folder for patched libraries and click Prepare 7.61 or Prepare 6.02. The app downloads the BPS patches from BestPig/BackPork and applies them. - In Add job, Check tells you whether a game runs on the target with a lower SDK alone or needs the patched libraries. Every build runs this check first and stops before touching anything if libraries are missing.
Whether a particular game runs after a backport depends on the game and on the jailbreak's fakelib support.
The same is available on the command line:
python3 backend/cli.py --backport-analyze <game folder> --backport-target 9.60 --fw-libs-root <firmware folder>
python3 backend/cli.py --prepare-backport-libs 7.61 --fw-libs-root <firmware folder> --backport-libs <patched folder>
python3 backend/cli.py <game>.ffpfsc <output folder> --to ffpfsc --backport-target 7.61 --fw-libs-root <firmware folder> --backport-libs <patched folder>A PS4 save holds the keystone of the game that wrote it. A fake package built with a different keystone (most builders use a default one) shows saves of the retail game as corrupted. A full game with an update merged in can have a second problem: if its app version stayed at the game's, the console keeps offering the official update. Add job tells you about both.
PS4 PKG Tools in the sidebar fix them:
- Pick the game package.
- Give the keystone of the retail game, or leave the field empty to keep the one the package has. On a jailbroken console, open Apollo Save Tool, pick a save of the game, and either Export Keystone (then fetch
/data/apollo/<user id>/<title id>/keystoneby FTP and pick the file) or Show Keystone Fingerprint (then type the 64 hex digits). - If the package has the version problem, a Version line shows up. Checked, the job swaps app version and master version in its param.sfo, so the app version is the merged update's.
- Check the updates of the game. The tool lists the ones next to the package; add others with Add…. Each update records the package it belongs to, and the job points it at the changed package so it still installs. An update whose saves would go to another folder than the game's gets the game's folder. An update converted from another region is marked, because its language can differ from the game's.
- Add to queue and start the queue.
The packages are changed in place, nothing is rebuilt. Everything the job replaces is kept in the app folder under keystone-undo/, and Undo last change puts it back, one run at a time and newest first. A run that is stopped half-way can be undone too.
PS5 PKG Tools in the sidebar check a PS5 package without unpacking it. They run the validate checklist (package layout, param.json, PlayGo tables, images, license, executables) and compare the firmware the game needs with the firmware your console runs. They also look at the keystone, at update markers in param.json, for a stray param.sfo, at the checksums of the trophy archives, at the AMPR index of a game that ships the AMPR emulator, and, for an update package, at the game package next to it (the update has to be newer). Each finding says whether the rebuild fixes it. Add job shows the result for a PS5 package too.
The tools build a new package in the output folder and leave the original as it is. The rebuild already puts images, license and PlayGo tables right. On top of that you can:
- put in the keystone from the game's own dump (its folder, .ffpfsc or .pkg) or from a keystone file, instead of the default keystone a builder makes when the source has none,
- lower the firmware to the one your console runs,
- regenerate the PlayGo tables,
- make it a standalone game, which clears the update-check URL in param.json.
A trophy archive with a wrong checksum gets the right one, and a missing or stale AMPR index is written again. An update package is only checked, since the rebuild is for full games.
The view also has Look inside and Unpack for the package.
Organize (in the sidebar) cleans up an existing library. Pick a folder and press Scan. You get a list of every game folder, image, package and archive in it with its current and new name. Apply only renames, so it's fast even on a large drive, and Undo last organize puts things back, one Apply at a time.
Each game ends up in one title folder named after the newest version it has. PS4 packages get their own layout with UPDATE and DLC entries. Archives keep their file names. If the app can't tell which game an archive belongs to, it leaves that folder alone and says so.
Look inside opens a .ffpfs, .ffpfsc or .pkg and shows the file tree. You can extract single files or folders without unpacking the whole thing. Only the blocks you need are read and decompressed, so even a 100 GB container opens quickly. Extracted files are identical to the originals. Unpack all as a job puts the whole image into a folder through the queue.
- PlayGo/APR titles: the app detects
playgo-chunk.dat, adds the fakelib module and theAMPRIDX3index, and signs before indexing so the sizes are right. - HDR: the HDR flag in
param.jsonis kept in.pkgbuilds (--fpkg-hdr-flag auto|on|off).python3 backend/cli.py --param-report <folder>lists title ID, version, HDR flag, required system software and SDK version for a whole folder. - Fake-sign uses a vendored, pure-Python
make_fself. Files that are already signed are skipped, so running it twice is harmless. - Block size: images are always packed with 64 KiB PFS blocks. Smaller blocks pass a local check but crash on the console.
You need Python 3.10 or newer. This is also the way to run the app on a macOS older than 26: the release builds need macOS 26, but a source run uses whatever your Python is built for. I don't test or support older systems, though.
python3 -m pip install customtkinter pillow tkinterdnd2 py7zr rarfile psutil cryptography
python3 -m pip install ./backend/unrar
python3 PS5_UltraPack.pyThe RAR module needs a C++ compiler (Xcode Command Line Tools on macOS). For .pkg features build the fPKG helper once with ./BUILD_PKG_TOOL.sh (needs the .NET SDK 9+) and its OpenSSL with ./BUILD_OPENSSL.sh. Without the bundled 7-Zip, the app uses an installed 7-Zip or falls back to a slower Python path for .7z. AES and Deflate64 ZIPs need 7-Zip in any case.
On Windows, run.bat installs the packages from requirements-build.txt and starts the app. Build the fPKG helper with BUILD_PKG_TOOL.ps1. run.bat doesn't build the RAR module, so RAR needs 7-Zip or WinRAR installed. Windows has a 260-character path limit unless long paths are enabled, so keep temp and output folders short (e.g. D:\ps5).
macOS, from the repo root in a virtual environment (the script refuses to run outside one). It builds the fPKG helper first, so it needs the .NET SDK 9+:
python3 -m venv .venv && source .venv/bin/activate
./BUILD_MACOS_APP.shThis writes dist/PS5 UltraPack.app plus dist/PS5-UltraPack-<version>-macos-arm64.zip and its .sha256. FETCH_7ZIP.sh downloads the pinned 7-Zip binaries for the bundle.
Windows: build the native parts on a Mac first with WIN_PYTHON=<copy of the Windows Python folder> ./BUILD_WINDOWS_PARTS.sh (needs the .NET SDK and mingw-w64). Then run BUILD_WINDOWS_APP.ps1 on Windows. It writes dist\windows\PS5 UltraPack\PS5 UltraPack.exe and the release zip.
This isn't a fork, but it builds on a lot of other people's work. Thanks to:
- Bizkut for ps5-ffpfs-cli.
backend/cli.pystarted out as its backend wrapper. - PSBrew for MkPFS, which does the PFS images and compression (bundled, 1.0.0).
- drakmor for LibProsperoPkg 1.2.0, used for building and reading
.pkgfiles. My wrapper is inbackend/native/src/ffpfsc-pkg-tool/. - The ps5-payload-dev / flatz lineage for
make_fself(BSD-3). - RARLAB for UnRAR, vendored as C++ source for the RAR module.
- The authors of ShadowMountPlus and MicroMount, which load the
.ffpfsccontainers. - EchoStretch for kstuff-lite, and Drakmor and ArkSama for the fpkg launch fixes. Without them fPKG on 11.60 wouldn't launch at all.
- BestPig for the BackPork library patches.
- drakmor for ampr_emu, whose packer and runtime the LZ4 asset packs use (GPL-3), and Nazky and the other Lazy_AMPR authors for showing what it can do.
- titoum-be, who got it running on Windows and sent the launcher and build script the Windows version is based on (#1).
Python libraries: customtkinter, py7zr, rarfile, tkinterdnd2, Pillow, psutil, cryptography.
The details, including trademark notes, are in NOTICES.md. Short version:
- My own code (the GUI, the Python wrappers, the C# wrapper around LibProsperoPkg, tests and build scripts) is MIT, see
LICENSE. - MkPFS 1.0.0 is GPL-3.0-or-later (
backend/mkpfs/LICENSE). - LibProsperoPkg 1.2.0 is GPL-3.0-or-later (
backend/native/LICENSE.LibProsperoPkg). - The UnRAR sources are under the UnRAR license: free for extraction, but they may not be used to build a RAR-compatible compressor (
backend/unrar/license.txt). - ampr_emu's packer (
backend/ampr_pack/) and its runtimelibSceAmpr.sprxare GPL-3.0 (drakmor). make_fself.pyis BSD-3-Clause, attribution in the file header.- Bizkut's ps5-ffpfs-cli has no license file.
backend/cli.pystarted from it and has been mostly rewritten. I don't claim a license for what's left of the original code; MIT covers my changes. SeeNOTICES.md.
Because the compiled app includes MkPFS and LibProsperoPkg, the binaries are distributed as a combined work under GPL-3.0-or-later. Everything needed to rebuild them is in this repo, including the LibProsperoPkg assembly (original and patched, with the patch tooling and a notice in backend/native/src/ffpfsc-pkg-tool/lib/).
Not affiliated with Sony Interactive Entertainment. "PlayStation" and "PS5" are their trademarks and are only used to name the console and formats this tool works with. The app processes files you provide. It doesn't decrypt or distribute any Sony content, firmware, keys or executables, and it's your responsibility to only use it with content you have the right to use (your own game dumps, homebrew you're allowed to redistribute).
*It doesn't have to be a big donation. A few cents show me who uses the tool and cares about where it goes next. That keeps me motivated, and I know I'm not coding for the bin ;)














