🎉 MkPFS 1.0.0 is released!
🤖 What's Changed
- Several improvements and fixes related to image packing, unpacking, and verification.
- Implemented a simple GUI
🚀 Quick Start
# Install/Update using pip
python -m pip install -U "mkpfs"
# Creating Images: Option 1: .exfat -> .ffpfsc (Works with ShadowMountPlus) (Maximum compatibility)
python -m mkpfs pack file './BREW1234.exfat' './BREW1234.ffpfsc'
# Creating Images: Option 2: .ffpkg -> .ffpfsc (Works with ShadowMountPlus)
python -m mkpfs pack file './BREW1234.ffpkg' './BREW1234.ffpfsc'
# Creating Images: Option 3: Game folder -> .ffpfsc in one pass (default: exFAT-wrapped, no temp file)
python -m mkpfs pack folder './BREW1234-app' './BREW1234.ffpfsc'
# Creating Images: Option 4: Game folder packed directly as PFS (advanced single-pass)
python -m mkpfs pack folder --raw './BREW1234-app/' './BREW1234.ffpfs'
# Creating Images: Option 5: Game folder wrapped twice into PFS (advanced two-pass)
python -m mkpfs pack folder --raw --no-compress --no-adjust-output-file-extension './BREW1234-app' './pfs_image.dat'
python -m mkpfs pack file './pfs_image.dat' './BREW1234.ffpfsc'
rm './pfs_image.dat'
# Extracting Existing Images (Reverse operation; --deep lists/extracts inside a wrapped exFAT)
python -m mkpfs unpack --deep './BREW1234.ffpfsc' './BREW1234-extracted/'⚠️ Limitations and Known Issues
exfat->ffpfscis the most stable format for compressed game backups.pack folderproduces this layout by
default: it wraps the folder in an exFAT image and compresses that into the.ffpfscin a single pass, with no
temporary.exfaton disk.pack folder --rawpacks the folder directly into a PFS image without the exFAT wrapper. When file compression is
enabled, the image is created and verification passes, but the console reads the files incorrectly due to technical
limitations, so this advanced option provides no practical benefit for game backups. Prefer the default wrapped
layout.- With the default
--block-size 65536, very small files can cause significant block-alignment waste, which may make
the resulting image larger than the source in corner cases.- For small-file-heavy folders, prefer the two-pass strategy (
raw-folder -> .dat -> .ffpfsc) or try a smaller
block size such as--block-size 16384or--block-size 32768.
- For small-file-heavy folders, prefer the two-pass strategy (
- Antivirus scanning can reduce conversion speed, especially during the write phase or when processing many loose
files. If you trust this software in your environment and need higher throughput, temporarily disabling real-time
scanning can help. If you are unsure, keep antivirus enabled and expect slower conversions.
💖 Sponsorship
MkPFS is easier to sustain when users who benefit from it help fund it.
☕ Contributions
Breaking
- Add graphical interface prototype (#73) @RenanGBarreto, @Phoenixx1202
New
- Add verbose per-item output and guardrails to batch convert (#118) @RenanGBarreto
- Default exFAT cluster to 64 KiB (#109) @RenanGBarreto
- Add batch conversion support for converting multiple games with a single command (#100) @RenanGBarreto, @dependabot[bot]
- Perfomance Improvement: Add compression backend adapter module with ISAL support (#93) @RenanGBarreto, @Copilot
- Add Pack exFAT panel and sync GUI progress (#89) @RenanGBarreto
- Skip AMPR index regeneration when a valid index already exists (#88) @RenanGBarreto
- Set default compression level to 7 (#87) @RenanGBarreto
Bug Fixes
- Use native monospaced font on macOS and Linux (#119) @RenanGBarreto
- Fix exfat panel crash and remove dead UI options (#111) @RenanGBarreto
- Fix macOS GUI build to bundle customtkinter and set installer title (#80) @RenanGBarreto
Maintenance
- Fix silent mode fallthrough, private CTkTextbox API access, missing hover feedback, and multi-size ICO generation (#102) @copilot-swe-agent[bot], @Copilot, @RenanGBarreto
- Fix icon generation crash with newer Pillow versions (#98) @RenanGBarreto
- Catch only Pillow import failures in icon generation (#91) @copilot-swe-agent[bot], @Copilot
- Complete contributor update map and normalize
./tmp/path (#90) @copilot-swe-agent[bot], @Copilot - Split the monolith gui.py into a focused package (#84) @RenanGBarreto
- Make docs/skills easier to discover and follow, reduce duplication (#72) @RenanGBarreto
- Streamline rules, add worktree map, and expand related-projects index (#71) @RenanGBarreto
Dependency Updates
12 changes
- chore(deps-dev): bump ruff from 0.16.1 to 0.16.4 (#116) @dependabot[bot]
- chore(deps): bump actions/setup-python from 6 to 7 (#105) @dependabot[bot], @RenanGBarreto
- chore(deps-dev): bump ruff from 0.16.0 to 0.16.1 (#108) @dependabot[bot]
- chore(deps): bump actions/stale from 10 to 11 (#107) @dependabot[bot], @RenanGBarreto
- chore(deps-dev): bump ruff from 0.15.21 to 0.16.0 (#106) @dependabot[bot]
- chore(deps-dev): bump ruff from 0.15.20 to 0.15.21 (#96) @dependabot[bot]
- chore(deps-dev): update hatchling requirement from <1.30 to <1.32 (#97) @dependabot[bot]
- chore(deps): bump actions/setup-python from 4 to 6 (#82) @dependabot[bot]
- chore(deps): bump actions/checkout from 4 to 7 (#74) @dependabot[bot]
- chore(deps): bump actions/upload-artifact from 6 to 7 (#76) @dependabot[bot]
- chore(deps): bump actions/download-artifact from 6 to 8 (#75) @dependabot[bot]
- chore(deps): bump pozil/auto-assign-issue from 1 to 4 (#77) @dependabot[bot]
Other changes
- Handle StrEnum import for different Python versions (#115) @cocoon
- GUI: Auto populate output form fields (#110) @RenanGBarreto
- Faster file discovery for large source trees (#86) @RenanGBarreto
- Consolidate rules into CLAUDE.md and fix broken agent paths (#85) @RenanGBarreto
Full Changelog: 0.0.9...1.0.0