No description
  • Python 89.9%
  • C# 4.8%
  • Shell 4.6%
  • F# 0.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
RaringM 6efca0e31d
Make ampr-emu-ng 0.1.0 the default AMPR emulator
- 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
2026-11-01 10:59:58 -06:00
.github/workflows Update dependencies: PlayGo Stub 0.6, tomli 2.5.0, CI actions 2026-11-01 10:52:31 -06:00
docs Make ampr-emu-ng 0.1.0 the default AMPR emulator 2026-11-01 10:59:58 -06:00
packaging Make ampr-emu-ng 0.1.0 the default AMPR emulator 2026-11-01 10:59:58 -06:00
ps5_mountaneer Make ampr-emu-ng 0.1.0 the default AMPR emulator 2026-11-01 10:59:58 -06:00
tests Make ampr-emu-ng 0.1.0 the default AMPR emulator 2026-11-01 10:59:58 -06:00
tools Make ampr-emu-ng 0.1.0 the default AMPR emulator 2026-11-01 10:59:58 -06:00
vendor Make ampr-emu-ng 0.1.0 the default AMPR emulator 2026-11-01 10:59:58 -06:00
.gitattributes Upgrade FPKG engine and validate package workflows 2026-10-06 14:30:59 -05:00
.gitignore Add single-file release builds 2026-09-14 08:37:07 -05:00
AGENTS.md Make ampr-emu-ng 0.1.0 the default AMPR emulator 2026-11-01 10:59:58 -06:00
mkexfat_linux.sh add more formats 2026-06-03 09:42:46 -05:00
mkufs2_freebsd_docker.sh work on migrating to ps5 & cross-platform support 2026-06-05 09:22:05 -05:00
ps5-mountaneer work on migrating to ps5 & cross-platform support 2026-06-05 09:22:05 -05:00
ps5-mountaneer.cmd work on migrating to ps5 & cross-platform support 2026-06-05 09:22:05 -05:00
pyproject.toml Update dependencies: PlayGo Stub 0.6, tomli 2.5.0, CI actions 2026-11-01 10:52:31 -06:00
README.md Make ampr-emu-ng 0.1.0 the default AMPR emulator 2026-11-01 10:59:58 -06:00
THIRD_PARTY_NOTICES.md Make ampr-emu-ng 0.1.0 the default AMPR emulator 2026-11-01 10:59:58 -06:00

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 .ffpkg or .exfat image. This is the recommended compression path; generated names include the nested base format, such as .ffpkg.ffpfsc or .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 -i from source file/directory count.
  • Adds SM_UFS2_EXTRA_PERCENT=2 headroom 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 -n plus root-file stat checks.
  • FreeBSD-backed verification runs fsck_ffs -n, mounts read-only, and checks eboot.bin plus sce_sys/param.json at image root.

exFAT:

  • Uses 64 KiB clusters.
  • Frozen releases use MkPFS's userspace exFAT writer by default, avoiding mounts, elevation, filesystem drivers, mkfs.exfat, and rsync.
  • Auto-sizes the image using 64 KiB allocation, metadata estimates, and safety margin.
  • Linux uses mkfs.exfat -F -c 64K, copies with rsync --info=progress2, and verifies with fsck.exfat -n.
  • Linux exFAT create/verify should be run as the normal user. The tool prompts with sudo -v only for mount/umount operations, so MkPFS and Python dependencies still resolve from the user's environment.
  • macOS uses hdiutil plus newfs_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-osfmount or use --exfat-backend.

PFS/PFSC:

  • Delegates to MkPFS.
  • Requires a current MkPFS whose pack file -h and pack folder -h expose --skip-executable-compression, --max-compressed-ratio, --min-compress-size, and --temp-folder.
  • Detects newer MkPFS --no-spool and --no-adjust-output-file-extension support. Single-file PFSC wrapping uses no-spool mode when available to reduce peak temporary disk usage for very large .ffpkg or .exfat inputs.
  • Uses --compress --skip-executable-compression by 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, and SM_PFS_INODE_BITS=32 by default.
  • Single-file PFSC wraps over 8 GiB default to MkPFS --cpu-count 6 unless --jobs / SM_PFS_CPU_COUNT is set. This avoids the current MkPFS block-parallel path being killed by memory pressure on huge .ffpkg or .exfat inputs. Tune with SM_PFS_SINGLE_FILE_SAFE_CPU_COUNT and SM_PFS_SINGLE_FILE_SAFE_CPU_THRESHOLD_GIB if you want a different default.
  • When SM_MKPFS_TEMP_DIR / --temp-dir is 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 --json applies the same --jobs, --temp-dir, and --verify overrides as create, so the reported MkPFS profile and temp directory match the eventual packaging run.
  • Generated PFSC outputs use .ffpkg.ffpfsc or .exfat.ffpfsc to make the nested base format visible. Plain .ffpfsc output paths remain accepted for manual create/wrap commands.
  • create infers .ffpkg, .exfat, .ffpfs, .ffpkg.ffpfsc, .exfat.ffpfsc, and plain .ffpfsc output paths when --format is omitted. Explicit --format values 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 .ffpkg files can therefore be killed after the image has already been written. Set SM_MKPFS_VERIFY=1 to opt into that upstream verifier.

AMPR index:

  • --ampr-index, SM_AMPR_INDEX=1, or [ampr] index=1 generates ampr_emu.index from 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=auto is the default. Auto mode enables the index only when the source already contains a strong AMPR signal such as fakelib/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=0 disables 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 .ffpfsc images from a game root. wrap cannot add an index to an already-built base image.
  • ampr-index ftp://host/path/to/app0 --output ./ampr_emu.index --upload can build the same index from a console FTP view and upload it back to the FTP root. Omit --upload to 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-collisions or SM_AMPR_ALLOW_CASE_COLLISIONS=1 to keep the first sorted entry.

Fakelib helpers:

  • --fakelib-preset none|ampr|playgo|dlc|all injects vendored helper SPRX files into fakelib/ while packaging. The default is none.
  • --ampr-impl ng|drakmor, SM_FAKELIB_AMPR_IMPL, or [fakelib] ampr_impl picks the AMPR emulator build. The default is ng: ampr-emu-ng v0.1.0, a GPL-3.0 Rust hard fork of Drakmor's emulator focused on speed and memory use. It reads the same ampr_emu.index and LZ4 AMPRPAK4 packs this tool generates, plus its own zstd packs (made by its separate ps5-dump-forge tool, not by ps5-mountaneer). It is a new 0.1.0 release; use --ampr-impl drakmor to go back to Drakmor's 0.4.2.1 if a title misbehaves. Upstream asks that ShadowMountPlus fakelib updates be disabled so its copy is not replaced.
  • --fakelib-variant release|debug|packed selects the build. With ng, one release build serves both loose files and packs, so release and packed are the same file, and debug adds a metrics/tuning endpoint on TCP port 9090 that anyone on the console's network can reach (a warning is printed). With drakmor, they are the no-pack release, debug pack-capable, and non-debug pack-capable payloads. PlayGo and DLC use their no-log files for packed.
  • Drakmor's vendored AMPR payloads are version 0.4.2.1 from the exact drakmor/ampr_emu Git 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-staging or SM_FAKELIB_ALLOW_COPY_STAGING=1.
  • --playgo-dat PATH and SM_FAKELIB_PLAYGO_DAT stage 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 PATH and SM_FAKELIB_DLC_CONFIG stage a root-level /app0/dlc_emu.ini. Existing dlc_emu.ini files are preserved unless --force-fakelib is used for packaging-time staging.
  • emulation-info reports detected fakelib roles, hashes matched against vendor/ampr-lib/MANIFEST.json, AMPR index headers, PlayGo support-file status, and DLC mount-point warnings.
  • prepare-fakelib intentionally copies helpers into the raw dump for users who want to manage fakelib/ manually before packaging.
  • fakelib import --role ampr|playgo|dlc-entitlement|dlc-appcontent|dlc-game-update FILE replaces a vendored helper payload and updates vendor/ampr-lib/MANIFEST.json with 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-fakelib writes 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.dat writes a PlayGo stub config. --chunks auto uses streaminginstall.ini when available and falls back to 1000 chunks. --scenarios 0..5 is 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, so 0 now makes those calls fail. --languages takes a 0x hex mask or a list such as english_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.json records 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 all updates helper files by writing a patched copy. Use --in-place only when you intentionally want the original path atomically replaced after a successful patch.
  • Add --source-root <game_root> --ampr-index when the patch must refresh /app0/ampr_emu.index. The source root is required because the AMPR index must represent the whole final /app0 tree, not just the helper SPRX files.
  • .ffpkg patching uses UFS2Tool stat/add/replace with fsck_ufs -n before and after. .exfat patching mounts a copy read-write, writes only the payload files, unmounts, and runs fsck.exfat -n.
  • .ffpfsc patching is a rewrap workflow: ps5-mountaneer uses --base-image when provided, otherwise unpacks the PFSC, finds exactly one nested .ffpkg or .exfat, patches it, then wraps a new PFSC. Direct nested .ffpfs or pfs_image.dat payloads are rejected for patching; rebuild those from source.

Auto recommendation:

  • Uses UFS2 / .ffpkg as the default compatibility base because it is the ShadowMountPlus recommended default.
  • --profile balanced|compat|smallest|fast controls the auto tradeoff. balanced is the default, compat and fast keep the plain base image unless compression is forced, and smallest accepts any positive PFSC gain.
  • --compression auto|on|off controls PFSC wrapping. auto applies the selected profile, on wraps the base unconditionally, and off keeps the base format.
  • SM_AUTO_BASE_FORMAT=exfat or [auto] base_format=exfat can change the auto/recommendation base when you already know a title needs external-drive style behavior.
  • recommend is a fast estimate and policy report. It does not select PFSC unless --probe-pfsc is provided.
  • recommend --probe-pfsc and create --format auto build a temporary base image, run a MkPFS PFSC dry-run, then choose .ffpkg.ffpfsc or .exfat.ffpfsc only when MkPFS reports at least SM_AUTO_PFSC_MIN_SAVINGS_PERCENT=5 actual gain and at least one compressed file.
  • create <game_root> <extensionless_stem> is equivalent to create --format auto <game_root> <extensionless_stem>.
  • create --format auto <game_root> <final_image_path> treats the final suffix as a constraint: .ffpkg and .exfat produce plain base images, while .ffpkg.ffpfsc, .exfat.ffpfsc, and plain .ffpfsc force PFSC wrapping.
  • If PFSC does not meet the threshold, auto keeps the base as .ffpkg or .exfat.
  • Direct .ffpfs remains explicit/report-only because ShadowMountPlus runtime compatibility is still more experimental than .ffpkg, .exfat, or PFSC wrapping.
  • Set SM_PFSC_KEEP_BASE=1 or [auto] keep_base=1 with auto to keep the base image alongside a selected .ffpkg.ffpfsc or .exfat.ffpfsc.

Progress:

  • --progress auto|always|never controls ps5-mountaneer-managed progress output. auto enables 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 never disables the pv meter in QEMU/container UFS2 builds.

Logging:

  • Every create and wrap run writes a timestamped .log (mirroring console and sub-tool output) plus a machine-readable .json metrics 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/logs on Linux, ~/Library/Logs/ps5-mountaneer on macOS, and %LOCALAPPDATA%\ps5-mountaneer\logs on 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 --json for the metrics array), and logs 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 expects samples/PPSA17221-app with eboot.bin and sce_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.ffpfsc outputs under /tmp/ps5-mountaneer-sample-*, verifies each output, and removes them on success. It also creates and patches --fakelib-preset all variants for .ffpkg, .exfat, .ffpkg.ffpfsc, and .exfat.ffpfsc, then checks that the AMPR, PlayGo, and DLC emulator SPRX files exist under fakelib/ inside the generated image. Set SM_SAMPLE_KEEP_OUTPUT=1 to 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.