- Python 89.9%
- C# 4.8%
- Shell 4.6%
- F# 0.6%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
- Vendor quer3q/ampr-emu-ng v0.1.0 release and debug payloads (match its SHA256SUMS) with the GPL source snapshot at 61cb122 and license - Add --ampr-impl ng|drakmor (SM_FAKELIB_AMPR_IMPL, [fakelib] ampr_impl); NG serves loose files and packs from one release build; Drakmor 0.4.2.1 stays selectable - Warn that the NG debug build exposes a metrics/tuning port (9090) - Bundle NG payloads in the single binary; label implementations in status - Stage NG via tools/vendor_helpers.py; update README, notices, AGENTS |
||
| .github/workflows | ||
| docs | ||
| packaging | ||
| ps5_mountaneer | ||
| tests | ||
| tools | ||
| vendor | ||
| .gitattributes | ||
| .gitignore | ||
| AGENTS.md | ||
| mkexfat_linux.sh | ||
| mkufs2_freebsd_docker.sh | ||
| ps5-mountaneer | ||
| ps5-mountaneer.cmd | ||
| pyproject.toml | ||
| README.md | ||
| THIRD_PARTY_NOTICES.md | ||
ps5-mountaneer
Cross-platform image and fake-package builders for PS5 game dumps.
ShadowMountPlus accepts four image families, and this tool exposes all of them:
.ffpkg/ UFS2: recommended ShadowMountPlus default. Built with UFS2Tool, native FreeBSD tools, host QEMU/FreeBSD, or Docker/Podman fallback..exfat: compatibility format for titles that behave better as external-drive-style content. Single-file releases use embedded MkPFS; source runs can also use native Linux, macOS, or Windows host tools..ffpfs: direct PFS image built with MkPFS. This is first-class here, but still experimental in ShadowMountPlus runtime compatibility..ffpfsc: MkPFS/PFSC container wrapping an existing.ffpkgor.exfatimage. This is the recommended compression path; generated names include the nested base format, such as.ffpkg.ffpfscor.exfat.ffpfsc.
The source folder must be the game root and contain:
eboot.bin
sce_sys/param.json
The generated .ffpkg, .exfat, and .ffpfs images place those files directly
at image root, not under an extra top-level folder. .ffpkg.ffpfsc and
.exfat.ffpfsc containers hold a nested .ffpkg or .exfat image instead.
See docs/format-contracts.md for the compatibility contract agents and
contributors should preserve when changing format policy or backend behavior.
The staged repack/conversion design is in docs/conversion-roadmap.md.
The CLI also builds finalized debug fake packages with the canonical .pkg
suffix. .fpkg is accepted as an input alias for inspection, verification, and
extraction, but new output is always .pkg.
Requirements
Python 3.10+ is required for the CLI launcher.
Docker-free UFS2 path:
(cd ../UFS2Tool && dotnet build UFS2Tool.csproj)
./ps5-mountaneer --config ./mountaneer.ini config init
./ps5-mountaneer --config ./mountaneer.ini doctor
UFS2Tool creates/checks UFS2 image files on Linux, macOS, and Windows without root, Docker, or a FreeBSD VM. The auto policy now prefers UFS2Tool when it is available, then falls back to native FreeBSD, host QEMU/FreeBSD, and Docker/Podman FreeBSD paths.
Linux exFAT requirements:
sudo dnf install exfatprogs rsync
Optional Fedora fallback requirements for host QEMU or container UFS2:
sudo dnf install qemu-system-x86 qemu-img xorriso openssh-clients xz
sudo dnf install pv # optional progress meter
sudo dnf install moby-engine
sudo systemctl enable --now docker
macOS exFAT uses built-in hdiutil, newfs_exfat, mount, and rsync.
Windows exFAT uses OSFMount, format.com, and robocopy.exe; run the command
from an Administrator shell.
MkPFS can also be used from a local checkout:
(cd ../MkPFS && uv sync --group dev)
MKPFS_BIN="../MkPFS/.venv/bin/mkpfs" ./ps5-mountaneer info ./PPSA12345.ffpkg.ffpfsc
FPKG development requires .NET SDK 10 and 7-Zip (7z or 7zz). The bridge build
verifies and extracts the pinned engine archive before compiling, and never
puts passcodes or entitlement keys on the child process command line:
python3 tools/build_fpkg_bridge.py
The supplied engine archive has no included license or corresponding source.
Its redistribution provenance is unverified; see THIRD_PARTY_NOTICES.md.
Single-file executables
Release builds use PyInstaller to produce one executable for the current OS and CPU architecture. The executable contains Python, the MkPFS CLI and native Python extensions, plus self-contained target builds of the external helpers. It extracts those components to a private runtime directory when launched; an installed Python or .NET runtime is not required.
Build the executable from a checkout with a sibling
../UFS2Tool repository:
python3 -m pip install -r packaging/requirements-build.txt
python3 tools/build_single_binary.py --mode onedir
python3 tools/build_single_binary.py
Develop and test onedir first; the second command produces the final onefile
artifact under dist/. Builds are native: run the process separately on each
Windows, macOS, and Linux architecture. CI defines the supported build matrix
in .github/workflows/single-binary.yml.
The normal build now includes the FPKG bridge, UFS2Tool, MkPFS, the AMPR LZ4
packer, python-lz4, and the AMPR/PlayGo/DLC payloads. This makes .pkg and every
fakelib operation work from the single executable without setting helper
variables or installing Python or .NET. Use reduced-build switches only when
those capabilities are intentionally unwanted:
python3 tools/build_single_binary.py --without-fpkg
python3 tools/build_single_binary.py --without-review-gated-assets
The current FPKG engine still has unresolved redistribution provenance, so
artifact upload remains an explicit, review-gated CI input. Do not publish a
full artifact until the bridge has migrated to a source-built, redistributable
LibProsperoPkg version and the fakelib corresponding-source delivery has been
reviewed. The old --include-fpkg, --allow-unverified-fpkg, and
--include-unverified-assets switches remain accepted for build-script
compatibility, but inclusion is now the default.
Usage
Estimate local allocation-based formats:
./ps5-mountaneer estimate /path/to/APPXXXX
./ps5-mountaneer estimate --format ufs2 /path/to/APPXXXX ./PPSA12345.ffpkg
./ps5-mountaneer estimate --format pfs /path/to/APPXXXX ./PPSA12345.ffpfs
Recommend the balanced format:
./ps5-mountaneer recommend /path/to/APPXXXX
./ps5-mountaneer recommend --probe-pfsc /path/to/APPXXXX
./ps5-mountaneer recommend --base-format exfat --probe-pfsc /path/to/APPXXXX
Create by output suffix. --format is optional when the destination has a
known ShadowMountPlus image suffix:
./ps5-mountaneer create /path/to/APPXXXX ./PPSA12345.ffpkg
./ps5-mountaneer create /path/to/APPXXXX ./PPSA12345.exfat
./ps5-mountaneer create /path/to/APPXXXX ./PPSA12345.ffpfs
./ps5-mountaneer create /path/to/APPXXXX ./PPSA12345.ffpkg.ffpfsc
./ps5-mountaneer create /path/to/APPXXXX ./PPSA12345.exfat.ffpfsc
./ps5-mountaneer create /path/to/APPXXXX ./PPSA12345.pkg
Create a finalized debug FPKG. Metadata is read from sce_sys/param.json; use
the explicit flags when a field is absent. The pinned engine is from Drakmor's
FPKG_GUI 0.6.12. Our profile uses app packages, debug FIH, plaintext/no-auth
publisher images, PFSv2, automatic Kraken level 7 with 256 KiB blocks, SDK 1,
and deterministic builds. PlayGo uses the source layout when available, with
a fallback of 100 chunks (configurable from 1 through 255).
./ps5-mountaneer create --format fpkg /path/to/APPXXXX ./PPSA12345.pkg
./ps5-mountaneer create --format fpkg --package-kind homebrew \
--content-id UP0000-PPSA12345_00-EXAMPLE000000000 /path/to/APPXXXX ./PPSA12345.pkg
./ps5-mountaneer create --format fpkg --source-mode gp5 ./project.gp5 ./PPSA12345.pkg
FPKG build controls are exposed in create --help, including native or
plaintext image mode, AC-data entitlement key, PFSv2/v3, Kraken backend/level/
threads/block size, shuffle analysis and prediction, layout passes, PlayGo chunk
count, SDK override, and deterministic mode. --sdk-major 0 preserves source
metadata. AC-data builds require a 16-byte (32-hex-character) entitlement key,
which can also come from a GP5. GP5 content IDs and mapped param.json metadata
are read automatically.
Every build passes the engine's quick verification before replacing the final
output, including with --force. Keep a loose-folder build's output and
--temp-dir outside its source tree. GP5 builds can write beside the project;
they use external scratch space when needed. Folder builds default to an owned
scratch directory beside the output, rather than the operating-system temp
directory. --temp-dir selects its parent; only this run's scratch directory is
removed on success or failure. Child temporary files follow the same directory.
GP5 output inside its project uses a writable sibling scratch location outside
the project; select --temp-dir explicitly if that location is unavailable.
plan --json accepts the same FPKG settings as create and reports a conservative
budget per filesystem, grouping shared Btrfs storage by UUID. Creation stops when
the budget plus reserve cannot fit; --allow-low-space explicitly overrides this
estimate. The reserve defaults to 4 GiB (SM_FPKG_MIN_FREE_MB=4096). Existing
outputs are retained until verification, so --force does not reclaim their
space in the estimate. --verify full runs full verification before publication;
--verify none retains the mandatory quick check. Full verification requires an
updated bridge advertising that capability.
Intermediate images can require substantial additional space on the temporary
and destination filesystems; the run metrics include sampled peak scratch usage.
Updated helpers announce owned build/publication paths, letting JSON metrics
record space_observed component and simultaneous peaks once per second,
including quiet phases. Allocation measurements are labeled when a platform
only provides logical size. Older helpers report incomplete coverage.
The live progress bar reports the current phase's completion and ETA, with
per-file compression progress shown separately. Quick verification has its own
phase and ETA. --progress auto shows the bar in a terminal and plain tool
output in redirected streams; --progress always forces the live display.
ETA uses a rolling rate after a five-second warmup; --:-- means insufficient or
stale progress evidence. The display refreshes during quiet periods and avoids
duplicate/high-frequency redraws.
For reproducible compression comparisons, run:
python3 tools/benchmark_fpkg.py --source /path/to/game \
--work-dir /large/disk/fpkg-benchmark --full-candidate
It compares a bounded deterministic corpus with uncompressed storage and Kraken
levels 1, 3, and 7, using three rotated repetitions. Every sample is fully verified
and extracted bytes are compared. The fastest profile within 2% of the smallest
sample is selected for the opt-in full-game candidate. Source hashes are checked
before/after. Reports and logs remain; owned packages are cleaned unless
--keep-packages is selected. Default compression settings are not changed by
the benchmark. The historical full-game run is not a matched control.
Source files are preserved. Native Publishing Tools are optional and can be
selected with --publishing-tools-dll; the bridge build bundles only the managed
engine. Use --kraken-backend built-in for the managed encoder.
Restore missing or damaged plaintext sce_sys metadata in a dump from the
exact-version metadata piece (*_sc.pkg) referenced by param.json
versionFileUri:
./ps5-mountaneer recover-metadata --dry-run /path/to/APPXXXX
./ps5-mountaneer recover-metadata /path/to/APPXXXX
./ps5-mountaneer recover-metadata --url https://.../PPSA12345_sc.pkg /path/to/APPXXXX
This is the one command that downloads anything; only the metadata piece is
fetched and its manifest SHA-256 and identity are checked. It changes sce_sys
in place. Originals go to a sibling <game>.metadata-backups folder, and a
failure or Ctrl-C rolls back. Local sdkVersion, requiredSystemSoftwareVersion
and applicationDrmType are kept unless --original-runtime is given. Protected
records are skipped and listed; keep their decrypted dump copies. keystone and
game payloads are never recovered or upgraded. Use --url with a version XML,
manifest, or _sc.pkg URL when versionFileUri only offers a newer version, and
--ca-cert to add a trusted root (hostname checks still apply).
Because versionFileUri comes from the dump itself, it must be an https URL
unless you pass --url. Every connection, including redirects and the URLs read
from the downloaded version XML and manifest, is checked when it is opened:
loopback, private, link-local, and other non-public addresses are refused (and a
host that does not resolve fails). --allow-private-network turns that off, for
example to test against a local mirror. TLS matches the engine's own client:
normal validation, plus Sony's metadata root CA for sgst.prod.dl.playstation.net
only (or your --ca-cert root).
Generate an AMPR resolver index while creating an image:
./ps5-mountaneer create --ampr-index /path/to/APPXXXX ./PPSA12345.ffpkg
./ps5-mountaneer create --ampr-index --base-format exfat /path/to/APPXXXX ./PPSA12345.exfat.ffpfsc
Generate or check an AMPR index directly:
./ps5-mountaneer ampr-index /path/to/APPXXXX
./ps5-mountaneer ampr-index --check --json /path/to/APPXXXX
Build and verify AMPR's seekable LZ4 asset packs from a prepared working copy:
./ps5-mountaneer prepare-fakelib --fakelib-preset ampr --fakelib-variant packed --ampr-index ./packed-app0
./ps5-mountaneer ampr-pack pack --root ./packed-app0 --ampr-index ./packed-app0/ampr_emu.index --output ./packed-app0 --include 'assets/**' --self-contained
./ps5-mountaneer ampr-pack verify --index ./packed-app0/ampr_assets.index --root ./packed-app0
./ps5-mountaneer create ./packed-app0 ./PPSA12345.ffpkg
The packer deliberately leaves source files in place. Review the verification
result and its loose_paths before considering source removal. See
docs/ampr-lz4.md for the format, safe workflow, and runtime constraints.
Inject AMPR/PlayGo/DLC fakelib helpers while creating an image. This uses a temporary hardlink staging tree and leaves the source dump unchanged:
./ps5-mountaneer create --fakelib-preset ampr /path/to/APPXXXX ./PPSA12345.ffpkg
./ps5-mountaneer create --fakelib-preset all --fakelib-variant release /path/to/APPXXXX ./PPSA12345.ffpkg.ffpfsc
./ps5-mountaneer create --fakelib-preset all --dlc-config ./dlc_emu.ini --playgo-dat ./playgo_stub.dat /path/to/APPXXXX ./PPSA12345.ffpkg
./ps5-mountaneer prepare-fakelib --fakelib-preset ampr --ampr-index /path/to/APPXXXX
Inspect existing emulator files in a raw dump:
./ps5-mountaneer emulation-info /path/to/APPXXXX
./ps5-mountaneer emulation-info --json /path/to/APPXXXX
Create UFS2 / .ffpkg explicitly:
./ps5-mountaneer create --format ufs2 /path/to/APPXXXX ./PPSA12345.ffpkg
Create exFAT / .exfat explicitly:
./ps5-mountaneer create --format exfat /path/to/APPXXXX ./PPSA12345.exfat
Create direct PFS / .ffpfs explicitly:
./ps5-mountaneer create --format pfs /path/to/APPXXXX ./PPSA12345.ffpfs
Create PFSC / .ffpfsc from a game root explicitly. This creates an
intermediate UFS2 .ffpkg by default, wraps it with MkPFS, and removes the
intermediate file:
./ps5-mountaneer create --format pfsc /path/to/APPXXXX ./PPSA12345.ffpkg.ffpfsc
./ps5-mountaneer create --format pfsc --base-format exfat /path/to/APPXXXX ./PPSA12345.exfat.ffpfsc
Create the balanced auto format. With an extensionless stem, the tool writes
.ffpkg, .exfat, .ffpkg.ffpfsc, or .exfat.ffpfsc after applying the
selected policy. With --format auto and a final image suffix, the suffix
constrains the output family:
./ps5-mountaneer create /path/to/APPXXXX ./PPSA12345
./ps5-mountaneer create --format auto /path/to/APPXXXX ./PPSA12345
./ps5-mountaneer create --format auto /path/to/APPXXXX ./PPSA12345.ffpkg
./ps5-mountaneer create --format auto --base-format exfat /path/to/APPXXXX ./PPSA12345
./ps5-mountaneer --progress never create --format auto /path/to/APPXXXX ./PPSA12345
Wrap an existing .ffpkg or .exfat as PFSC:
./ps5-mountaneer wrap --format pfsc ./PPSA12345.ffpkg ./PPSA12345.ffpfsc
./ps5-mountaneer wrap --format pfsc ./PPSA12345.ffpkg ./PPSA12345.ffpkg.ffpfsc
./ps5-mountaneer wrap --format pfsc ./PPSA12345.exfat ./PPSA12345.exfat.ffpfsc
Verify or inspect:
./ps5-mountaneer verify ./PPSA12345.ffpkg
./ps5-mountaneer verify ./PPSA12345.exfat
./ps5-mountaneer verify ./PPSA12345.ffpfs
./ps5-mountaneer verify ./PPSA12345.ffpkg.ffpfsc
./ps5-mountaneer info ./PPSA12345.ffpkg.ffpfsc
./ps5-mountaneer info --json ./PPSA12345.pkg
./ps5-mountaneer verify --sha256 ./PPSA12345.pkg
./ps5-mountaneer verify --full ./PPSA12345.pkg
./ps5-mountaneer extract ./PPSA12345.pkg ./PPSA12345-extracted
FPKG quick verification checks container ranges, CNT entry digests, PlayGo,
filesystem metadata, and the SI directory. --full also verifies payload block
hashes and decodes every file using bounded memory without extraction.
--sha256 additionally hashes the package; it does not replace full verification.
Extraction checks the package first, writes application files at the root, and
restores rebuild metadata (including param.json, keystone, and PlayGo) under
sce_sys. Pass --include-package-metadata to also retain raw CNT/SI records
under .fpkg/cnt and .fpkg/si. The default passcode is 32 zeroes; provide
--fpkg-passcode to verify or extract for another passcode. These host checks
do not establish console install or launch compatibility.
Inspect backend availability:
./ps5-mountaneer setup
./ps5-mountaneer setup --install-bundled --write-config
./ps5-mountaneer plan --json /path/to/APPXXXX ./PPSA12345
./ps5-mountaneer plan --json --jobs 2 --temp-dir /fast/tmp --verify full /path/to/APPXXXX ./PPSA12345.ffpkg.ffpfsc
./ps5-mountaneer doctor
./ps5-mountaneer doctor --format ufs2
./ps5-mountaneer doctor --format fakelib
./ps5-mountaneer doctor --json
Stage helper payloads from sibling checkouts into vendor/:
python3 tools/vendor_helpers.py
./ps5-mountaneer setup --install-bundled --write-config
The vendor layout is vendor/<platform>/bin for launchers/binaries,
vendor/src for bundled source, and vendor/licenses for notices. Explicit
config/env paths still override everything. Otherwise, system tools found on
PATH are preferred, and bundled/cache helpers are used only as fallbacks.
Create and inspect a persistent config:
./ps5-mountaneer config path
./ps5-mountaneer config init
./ps5-mountaneer config show
./ps5-mountaneer --config ./mountaneer.ini config show --json
Behavior
UFS2:
- Uses FreeBSD
newfs -O 2 -b 65536 -f 65536 -m 0 -S 4096. - Auto-tunes
-ifrom source file/directory count. - Adds
SM_UFS2_EXTRA_PERCENT=2headroom by default. - Preflights output free space and optional FreeBSD cache free space.
- Auto backend order is: UFS2Tool, native FreeBSD, host QEMU/FreeBSD, then
Docker/Podman FreeBSD. Set
SM_UFS2_BACKEND=ufs2tool|freebsd-native|qemu|container, use--ufs-backend, or configure[ufs2] backend=.... - UFS2Tool verification runs
fsck_ufs -nplus root-filestatchecks. - FreeBSD-backed verification runs
fsck_ffs -n, mounts read-only, and checkseboot.binplussce_sys/param.jsonat image root.
exFAT:
- Uses 64 KiB clusters.
- Frozen releases use MkPFS's userspace exFAT writer by default, avoiding
mounts, elevation, filesystem drivers,
mkfs.exfat, andrsync. - Auto-sizes the image using 64 KiB allocation, metadata estimates, and safety margin.
- Linux uses
mkfs.exfat -F -c 64K, copies withrsync --info=progress2, and verifies withfsck.exfat -n. - Linux exFAT create/verify should be run as the normal user. The tool prompts
with
sudo -vonly for mount/umount operations, so MkPFS and Python dependencies still resolve from the user's environment. - macOS uses
hdiutilplusnewfs_exfat -b 65536. - Windows uses OSFMount plus
format.com /FS:exFAT /A:64K. - Set
SM_EXFAT_BACKEND=mkpfs|linux-kernel|linux-fuse|macos-hdiutil|windows-osfmountor use--exfat-backend.
PFS/PFSC:
- Delegates to MkPFS.
- Requires a current MkPFS whose
pack file -handpack folder -hexpose--skip-executable-compression,--max-compressed-ratio,--min-compress-size, and--temp-folder. - Detects newer MkPFS
--no-spooland--no-adjust-output-file-extensionsupport. Single-file PFSC wrapping uses no-spool mode when available to reduce peak temporary disk usage for very large.ffpkgor.exfatinputs. - Uses
--compress --skip-executable-compressionby default. - Uses
SM_PFS_COMPRESSION_LEVEL=9,SM_PFS_MAX_COMPRESSED_RATIO=95,SM_PFS_MIN_COMPRESS_SIZE=65536,SM_PFS_BLOCK_SIZE=auto,SM_PFS_VERSION=PS5, andSM_PFS_INODE_BITS=32by default. - Single-file PFSC wraps over 8 GiB default to MkPFS
--cpu-count 6unless--jobs/SM_PFS_CPU_COUNTis set. This avoids the current MkPFS block-parallel path being killed by memory pressure on huge.ffpkgor.exfatinputs. Tune withSM_PFS_SINGLE_FILE_SAFE_CPU_COUNTandSM_PFS_SINGLE_FILE_SAFE_CPU_THRESHOLD_GIBif you want a different default. - When
SM_MKPFS_TEMP_DIR/--temp-diris not set, each output gets its own.ps5-mountaneer-mkpfs-tmp.<output-name>temp directory and ps5-mountaneer removes it after the MkPFS child exits. Explicit temp directories are left alone unless you delete them yourself. plan --jsonapplies the same--jobs,--temp-dir, and--verifyoverrides ascreate, so the reported MkPFS profile and temp directory match the eventual packaging run.- Generated PFSC outputs use
.ffpkg.ffpfscor.exfat.ffpfscto make the nested base format visible. Plain.ffpfscoutput paths remain accepted for manual create/wrap commands. createinfers.ffpkg,.exfat,.ffpfs,.ffpkg.ffpfsc,.exfat.ffpfsc, and plain.ffpfscoutput paths when--formatis omitted. Explicit--formatvalues are still accepted, but contradictory suffixes are rejected before any image work starts.- MkPFS post-pack verification is disabled by default because the current MkPFS
verifier can materialize each decoded payload in memory. Large PFSC wrappers
around
.ffpkgfiles can therefore be killed after the image has already been written. SetSM_MKPFS_VERIFY=1to opt into that upstream verifier.
AMPR index:
--ampr-index,SM_AMPR_INDEX=1, or[ampr] index=1generatesampr_emu.indexfrom the game root before packaging. The source file is restored afterward, so a previously absent index is removed and an existing one is put back.SM_AMPR_INDEX=autois the default. Auto mode enables the index only when the source already contains a strong AMPR signal such asfakelib/libSceAmpr.sprx, or when packaging-time injection uses--fakelib-preset ampr|all. PlayGo and DLC helpers alone do not trigger AMPR index generation.--no-ampr-index,SM_AMPR_INDEX=0, or[ampr] index=0disables index generation even if AMPR helpers are detected.- The generated index is included at image root, which AMPR treats as
/app0/ampr_emu.index. Use it when creating AMPR-targeted.ffpkg,.exfat, or.ffpfscimages from a game root.wrapcannot add an index to an already-built base image. ampr-index ftp://host/path/to/app0 --output ./ampr_emu.index --uploadcan build the same index from a console FTP view and upload it back to the FTP root. Omit--uploadto generate a local file only.- Paths are matched case-insensitively. By default, files that differ only by
case fail index generation; use
--ampr-allow-case-collisionsorSM_AMPR_ALLOW_CASE_COLLISIONS=1to keep the first sorted entry.
Fakelib helpers:
--fakelib-preset none|ampr|playgo|dlc|allinjects vendored helper SPRX files intofakelib/while packaging. The default isnone.--ampr-impl ng|drakmor,SM_FAKELIB_AMPR_IMPL, or[fakelib] ampr_implpicks the AMPR emulator build. The default isng: ampr-emu-ngv0.1.0, a GPL-3.0 Rust hard fork of Drakmor's emulator focused on speed and memory use. It reads the sameampr_emu.indexand LZ4AMPRPAK4packs this tool generates, plus its own zstd packs (made by its separate ps5-dump-forge tool, not by ps5-mountaneer). It is a new0.1.0release; use--ampr-impl drakmorto go back to Drakmor's0.4.2.1if a title misbehaves. Upstream asks that ShadowMountPlus fakelib updates be disabled so its copy is not replaced.--fakelib-variant release|debug|packedselects the build. Withng, one release build serves both loose files and packs, soreleaseandpackedare the same file, anddebugadds a metrics/tuning endpoint on TCP port 9090 that anyone on the console's network can reach (a warning is printed). Withdrakmor, they are the no-pack release, debug pack-capable, and non-debug pack-capable payloads. PlayGo and DLC use their no-log files forpacked.- Drakmor's vendored AMPR payloads are version
0.4.2.1from the exactdrakmor/ampr_emuGit tag and release assets. Upstream labels this a test release and reports a remaining crash issue when working with saves. - Packaging-time injection builds a temporary hardlink staging tree. The raw
game folder is not modified. If hardlinks are not possible, use
--allow-copy-stagingorSM_FAKELIB_ALLOW_COPY_STAGING=1. --playgo-dat PATHandSM_FAKELIB_PLAYGO_DATstage a root-level/app0/playgo_stub.dat. If absent, PlayGo stub 0.6 uses its defaults: 1000 chunks, all five scenarios, and all languages.--dlc-config PATHandSM_FAKELIB_DLC_CONFIGstage a root-level/app0/dlc_emu.ini. Existingdlc_emu.inifiles are preserved unless--force-fakelibis used for packaging-time staging.emulation-inforeports detected fakelib roles, hashes matched againstvendor/ampr-lib/MANIFEST.json, AMPR index headers, PlayGo support-file status, and DLC mount-point warnings.prepare-fakelibintentionally copies helpers into the raw dump for users who want to managefakelib/manually before packaging.fakelib import --role ampr|playgo|dlc-entitlement|dlc-appcontent|dlc-game-update FILEreplaces a vendored helper payload and updatesvendor/ampr-lib/MANIFEST.jsonwith the new SHA-256. The manifest keeps the redistribution warning unless you manually verify provenance and rights.fakelib export --fakelib-preset all /path/to/global-fakelibwrites helper SPRX files directly into a ShadowMountPlus global fakelib folder. This is the quickest way to test updated helpers without rebuilding existing images.make-playgo-dat <game_root> ./playgo_stub.datwrites a PlayGo stub config.--chunks autousesstreaminginstall.iniwhen available and falls back to 1000 chunks.--scenarios 0..5is optional; when omitted the line is left out so the stub enables all five scenarios. Since 0.6 the stub rejects requests for unavailable scenarios, so0now makes those calls fail.--languagestakes a0xhex mask or a list such asenglish_us,8,english_gb.dlc-config validate ./dlc_emu.ini --root <game_root>validates DLC emulator sections, content IDs, duplicate labels, and PSAC mount-point folders.- The current
vendor/ampr-lib/MANIFEST.jsonrecords the exact official ampr-emu-ng 0.1.0, Drakmor AMPR 0.4.2.1, PlayGo 0.6, and DLC 0.3 release identities and Git source tags. Its aggregate redistribution status intentionally remains unverified until the complete binary/corresponding-source delivery is reviewed. Do not remove that warning from release artifacts; these projects are GPL-3.0.
Patching existing images:
patch-image <image.ffpkg> --output <updated.ffpkg> --fakelib-preset allupdates helper files by writing a patched copy. Use--in-placeonly when you intentionally want the original path atomically replaced after a successful patch.- Add
--source-root <game_root> --ampr-indexwhen the patch must refresh/app0/ampr_emu.index. The source root is required because the AMPR index must represent the whole final/app0tree, not just the helper SPRX files. .ffpkgpatching uses UFS2Toolstat/add/replacewithfsck_ufs -nbefore and after..exfatpatching mounts a copy read-write, writes only the payload files, unmounts, and runsfsck.exfat -n..ffpfscpatching is a rewrap workflow: ps5-mountaneer uses--base-imagewhen provided, otherwise unpacks the PFSC, finds exactly one nested.ffpkgor.exfat, patches it, then wraps a new PFSC. Direct nested.ffpfsorpfs_image.datpayloads are rejected for patching; rebuild those from source.
Auto recommendation:
- Uses UFS2 /
.ffpkgas the default compatibility base because it is the ShadowMountPlus recommended default. --profile balanced|compat|smallest|fastcontrols the auto tradeoff.balancedis the default,compatandfastkeep the plain base image unless compression is forced, andsmallestaccepts any positive PFSC gain.--compression auto|on|offcontrols PFSC wrapping.autoapplies the selected profile,onwraps the base unconditionally, andoffkeeps the base format.SM_AUTO_BASE_FORMAT=exfator[auto] base_format=exfatcan change the auto/recommendation base when you already know a title needs external-drive style behavior.recommendis a fast estimate and policy report. It does not select PFSC unless--probe-pfscis provided.recommend --probe-pfscandcreate --format autobuild a temporary base image, run a MkPFS PFSC dry-run, then choose.ffpkg.ffpfscor.exfat.ffpfsconly when MkPFS reports at leastSM_AUTO_PFSC_MIN_SAVINGS_PERCENT=5actual gain and at least one compressed file.create <game_root> <extensionless_stem>is equivalent tocreate --format auto <game_root> <extensionless_stem>.create --format auto <game_root> <final_image_path>treats the final suffix as a constraint:.ffpkgand.exfatproduce plain base images, while.ffpkg.ffpfsc,.exfat.ffpfsc, and plain.ffpfscforce PFSC wrapping.- If PFSC does not meet the threshold, auto keeps the base as
.ffpkgor.exfat. - Direct
.ffpfsremains explicit/report-only because ShadowMountPlus runtime compatibility is still more experimental than.ffpkg,.exfat, or PFSC wrapping. - Set
SM_PFSC_KEEP_BASE=1or[auto] keep_base=1with auto to keep the base image alongside a selected.ffpkg.ffpfscor.exfat.ffpfsc.
Progress:
--progress auto|always|nevercontrols ps5-mountaneer-managed progress output.autoenables progress when stderr is a terminal.- Source scans report file, directory, and byte totals when progress is enabled.
- The long-running packaging steps render a live bar: UFS2Tool population, exFAT rsync copy, and MkPFS pack/wrap show a percentage/bytes/ETA bar when the tool reports progress, and fall back to a spinner with elapsed time and a final throughput summary when it does not.
- The setting propagates to the FreeBSD helper, so
--progress neverdisables thepvmeter in QEMU/container UFS2 builds.
Logging:
- Every
createandwraprun writes a timestamped.log(mirroring console and sub-tool output) plus a machine-readable.jsonmetrics summary capturing input/output sizes, compression savings, per-step timings, the chosen format/backend, and whether system or vendored helpers were used. - Logs default to the platform state directory:
${XDG_STATE_HOME:-~/.local/state}/ps5-mountaneer/logson Linux,~/Library/Logs/ps5-mountaneeron macOS, and%LOCALAPPDATA%\ps5-mountaneer\logson Windows. Override with--log-file <path>,SM_LOG_DIR, or[logging] dir; disable with--no-log,SM_LOG_ENABLE=0, or[logging] enable=0. - Manage logs with
./ps5-mountaneer logs path,logs show(add--jsonfor the metrics array), andlogs clear --keep N(keep the N newest runs). - When invoked through
sudo, log files are chowned back to the original user.
Sample integration tests:
samples/is gitignored and must be supplied locally. The current real-sample test expectssamples/PPSA17221-appwitheboot.binandsce_sys/param.json.- Run the default unit suite with
python3 -m unittest discover -s tests; the real-sample tests are skipped unless explicitly enabled. - Run the Minecraft packaging matrix with:
sudo -v
SM_SAMPLE_INTEGRATION=1 python3 -m unittest tests.test_sample_packaging
- The opt-in suite creates
.ffpkg,.exfat,.ffpfs,.ffpkg.ffpfsc, and.exfat.ffpfscoutputs under/tmp/ps5-mountaneer-sample-*, verifies each output, and removes them on success. It also creates and patches--fakelib-preset allvariants for.ffpkg,.exfat,.ffpkg.ffpfsc, and.exfat.ffpfsc, then checks that the AMPR, PlayGo, and DLC emulator SPRX files exist underfakelib/inside the generated image. SetSM_SAMPLE_KEEP_OUTPUT=1to keep the generated images for inspection. - exFAT coverage is mandatory when
SM_SAMPLE_INTEGRATION=1; on Linux the test requires exFAT tooling plus root or cached sudo credentials.
Compatibility Wrappers
Old command style still works:
./mkufs2_freebsd_docker.sh /path/to/APPXXXX ./PPSA12345.ffpkg
./mkufs2_freebsd_docker.sh --estimate /path/to/APPXXXX ./PPSA12345.ffpkg
./mkufs2_freebsd_docker.sh --verify ./PPSA12345.ffpkg
sudo ./mkexfat_linux.sh /path/to/APPXXXX ./PPSA12345.exfat
./mkexfat_linux.sh --estimate /path/to/APPXXXX ./PPSA12345.exfat
sudo ./mkexfat_linux.sh --verify ./PPSA12345.exfat
Environment
CLI flags override environment variables; environment variables override
config.ini; config values override built-in defaults. The default config path
is ${XDG_CONFIG_HOME:-~/.config}/ps5-mountaneer/config.ini on Linux and other
POSIX hosts, ~/Library/Application Support/ps5-mountaneer/config.ini on
macOS, and %APPDATA%\ps5-mountaneer\config.ini on Windows. Set SM_CONFIG or
pass --config <path> to use another file.
SM_PROGRESS=never ./ps5-mountaneer create --format ufs2 /path/to/APPXXXX ./PPSA12345.ffpkg
SM_LOG_DIR=/var/log/ps5-mountaneer ./ps5-mountaneer create --format auto /path/to/APPXXXX ./PPSA12345
SM_LOG_ENABLE=0 ./ps5-mountaneer create --format ufs2 /path/to/APPXXXX ./PPSA12345.ffpkg
SM_AUTO_BASE_FORMAT=exfat ./ps5-mountaneer recommend /path/to/APPXXXX
SM_AUTO_PFSC_MIN_SAVINGS_PERCENT=10 ./ps5-mountaneer create --format auto /path/to/APPXXXX ./PPSA12345
FORCE=1 ./ps5-mountaneer create --format ufs2 /path/to/APPXXXX ./PPSA12345.ffpkg
KEEP_PARTIAL_OUTPUT=1 ./ps5-mountaneer create --format ufs2 /path/to/APPXXXX ./PPSA12345.ffpkg
UFS2TOOL_BIN="../UFS2Tool/bin/Debug/net8.0/UFS2Tool" ./ps5-mountaneer create --format ufs2 /path/to/APPXXXX ./PPSA12345.ffpkg
SM_UFS2_BACKEND=qemu ./ps5-mountaneer create --format ufs2 /path/to/APPXXXX ./PPSA12345.ffpkg
FREEBSD_CACHE_DIR_HOST="$PWD/.ufs2-cache/freebsd-mkufs2" ./ps5-mountaneer create --format ufs2 /path/to/APPXXXX ./PPSA12345.ffpkg
SM_UFS2_EXTRA_MB=4096 ./ps5-mountaneer create --format ufs2 /path/to/APPXXXX ./PPSA12345.ffpkg
FREEBSD_MEMORY=8192 FREEBSD_CPUS=4 ./ps5-mountaneer create --format ufs2 /path/to/APPXXXX ./PPSA12345.ffpkg
SM_DOCKER_SELINUX_LABEL=0 ./ps5-mountaneer create --format ufs2 /path/to/APPXXXX ./PPSA12345.ffpkg
SM_EXFAT_BACKEND=linux-fuse ./ps5-mountaneer create --format exfat /path/to/APPXXXX ./PPSA12345.exfat
MKPFS_BIN="../MkPFS/.venv/bin/mkpfs" ./ps5-mountaneer create --format pfs /path/to/APPXXXX ./PPSA12345.ffpfs
SM_MKPFS_VERIFY=1 ./ps5-mountaneer wrap --format pfsc ./PPSA12345.ffpkg ./PPSA12345.ffpkg.ffpfsc
SM_PFS_CPU_COUNT=4 ./ps5-mountaneer wrap --format pfsc ./PPSA12345.exfat ./PPSA12345.exfat.ffpfsc
SM_PFSC_KEEP_BASE=1 ./ps5-mountaneer create --format pfsc /path/to/APPXXXX ./PPSA12345.ffpkg.ffpfsc
SM_AUTO_PFSC_MIN_SAVINGS_PERCENT=1 ./ps5-mountaneer create --format auto /path/to/APPXXXX ./PPSA12345
SM_AMPR_INDEX=auto ./ps5-mountaneer create /path/to/APPXXXX ./PPSA12345.ffpkg
SM_FAKELIB_PRESET=ampr ./ps5-mountaneer create /path/to/APPXXXX ./PPSA12345.ffpkg
Set FORCE=1 to overwrite an existing output file. Set
SM_PFSC_KEEP_BASE=1 to keep the intermediate .ffpkg or .exfat file used
by create --format pfsc. For very large single-file PFSC wraps, leave the
safe default in place for reliability or set --jobs N or
SM_PFS_CPU_COUNT=N after confirming your system has enough RAM. Set
SM_MKPFS_VERIFY=1 only when you want MkPFS to run its full post-pack verifier;
you can also run ./ps5-mountaneer verify later against the completed .ffpfs
or .ffpfsc.