- Edit tab (replaces Inspect): rename, delete and add files in a game
folder or image, applied in place behind an undo journal or by a
verified rebuild; Extract copies files out of any source; additional
content (DLC, updates) is recognised and packaged as fpkg.
- Storage tab (replaces Library): the Library plus a File explorer that
renames, moves and deletes at once and opens a folder or image in Edit
or Convert.
- PS5: ShadowMount+'s mounted games are hidden and locked in every
write path; Forge's own files are protected; L2/R2 switch tabs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
At every start the app and the PS5 page ask GitHub's releases/latest and show a green toast
(bottom corner, "v{v} is available", Update / Later) only after a successful check found an
installable update: a newer vX.Y.Z tag, this platform's exact asset uploaded and not empty,
and on the PS5 elfldr answering (GET /api/elfldr). Any failure is silent; no setting,
nothing stored (Later hides it for the session).
- Desktop: Update opens the platform's release archive in the browser (update_target,
open_update, shared open_url; CSP allows api.github.com). No new dependencies.
- PS5: POST /api/self_update asks elfldr for GET /?uri=<release .elf?args=serve&pipe=0>;
the server keeps serving and the page waits one minute in all for a new instance.
- Takeover: a newly loaded Forge of any version closes an idle running one and takes the
port: quit {"if_idle": true} for copies with session handover, GET /api/jobs then quit
for v0.1.1 and older. Running jobs always block ("Can't close Dump Forge - some jobs are
still running.", 11 console languages); "already running" is gone.
- Self copy saves hold a cross-process flock, so two copies starting together keep the
newest; trace downloads count as busy; admission waits are bounded to 1 s.
- Locales (11), AGENTS.md, ps5/README.md, README.md, DESIGN.md; tests in serve.rs, api.rs,
self_copy.rs and app/scripts/check-update.mjs. Reviewed with Codex (3 rounds, clean).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Vendor: ps5upload v6.1.2 -> v7.0.22 (01afdf8), patch series 27 -> 19:
- Eleven patches upstream took are dropped; the rest are rebased onto v7.
- The .pkg builder now always rebuilds ampr_emu.index from the packaged files (upstream: a
stale index crashes the game); a case clash refuses the build.
- 0016: an LZ4-packed source keeps its own index byte for byte (ampr_emu checks each record
against the pack manifest by file id); a missing or unreadable one refuses the build.
- 0017: eboot.bin is scanned for libSceAmpr once per job instead of three times.
- 0018: prepare reports files visited in its check and plan passes.
- 0019: the test trim redone for v7's new tests.
- lz4_flex pinned to Forge's 0.14 (one copy in the lock); the patches rebuild vendor/
exactly from upstream (recipe uses --binary for deleted fixtures).
Forge:
- KrakenLevel::Stored (--kraken stored, UI picker): an uncompressed package, upstream's
fallback for consoles that install a compressed package but won't start it.
- Archive reader: drains up to 64 MiB of the current entry instead of restarting the
session for a later one, and keeps every entry's first 64 bytes; a 7,169-file RAR's
check stage went from 10+ minutes to 33 s.
- One bar through check and plan (a small, bounded share); Event::Stages announces every
step a job will run (job://stages, the server's jobs[i].stages).
- UI: a step row (done / current / upcoming), a sheen on the bar while a job runs, the time
in the current step, speed and time left only for byte-streaming stages, no nested
scroll in the job list; 11 languages.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- UI languages: English, Russian, Simplified Chinese, German, Spanish, French,
Japanese, Brazilian Portuguese, Italian, Korean and Arabic. Messages in
app/src/locales/<lang>.tsx (en.tsx is the source and the Messages type), each
its own chunk; i18n.ts loads, detects and switches; the choice is kept in
localStorage. About's language dropdown sits in the card header.
- Arabic is right-to-left: logical CSS properties plus [dir=rtl] overrides,
paths and runtime values isolated, Latin digits.
- Game titles from param.json's localizedParameters (title_names).
- The PS5 server's notices follow the console language (notice.rs); the start
notice is "Dump Forge is launched"; the stopped page says to relaunch the app.
- UI copy says "game" instead of "dump" and "icon" instead of "tile".
- macOS window no longer private, so the language choice persists.
- Tests cut to the critical ~half: crates 446 -> 241, vendor 270 -> 144
(vendor/patches/0027-trim-tests.patch), node check assertions 217 -> 111.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Folder output: plain fsync per file, one full flush before the rename (macOS 44 -> 11 s)
- .fpkg build 60.6 -> 40.5 s: Kraken skips hopeless blocks (0024), CRC32C slicing-by-8 (0025),
per-file SHA3 on its own thread (0026), the source .pkg decoded 4 MiB ahead
- LZ4 profile rules compiled once with an exact-path index (preflight 8 s -> 0.03 s)
- Library: liquid-glass LZ4 label on packed games; PS5 shows free space of /data
- PS5 payload renamed "Dump Forge", home /data/dumpforge (one-time migration with a link,
old tile owner records accepted)
- Windows CI: the library test names the system drive root
- Docs: README benchmarks (PC + PS5 column), docs/LZ4.md, AGENTS.md and DESIGN.md trimmed,
TODO.md removed; release archives ship docs/LZ4.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Core: library.rs scans for game dumps (folders with eboot.bin +
sce_sys/param.json, and .exfat/.ffpkg/.ffpfs/.ffpfsc/.pkg images):
bounded breadth-first walk (depth 6, per-root dir/entry caps, 15 s
cooperative budget, partial results flagged), probes on up to 4
threads, links never followed, sorted by title. scan_library_folder
scans one chosen folder on any filesystem (a linked root is resolved
first); only /, the Windows system drive root, OS system folders and
~/Library / ~/AppData are refused (/private/tmp and /run/media
allowed). scan_library is the PS5's automatic scan of the server's
roots (statfs MNT_LOCAL, ufs/msdosfs/exfat/exfatfs/bfs/nullfs/...,
never /mnt/shadowmnt). library_cover reads icon0.png lazily (<= 512 KiB)
through a PNG data-URL helper shared with Inspect.
Server: POST /api/library_scan ({} on the PS5, {"root"} on a computer)
and POST /api/library_cover, through the shared read cap; 409 while
stopping. Tauri: library_scan {root}, library_cover.
UI: Library tab after LZ4 (books icon): cards or list with title, game
code, format and icon-only Inspect / Convert / Delete (shared delete
dialog in delete.tsx; Inspect and Convert get the dump through App).
On a computer the user picks a folder ("Pick a folder with your library
to scan"); a refused or failed pick shows "Can't scan this folder"; a
failed Refresh keeps the list. The PS5 scans on first open. The page
reads the platform from the server's session. Header: two rows under
900 px, tighter tabs under 420 px, no horizontal scroll. LZ4 tab:
Pack/Unpack first and the default; Pack targets .ffpkg by default.
Docs: AGENTS.md, DESIGN.md, README.md, TODO.md (native and hardware
Library checks), ps5/README.md routes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Core: Jobs::delete_path deletes a picked file or folder with the job
table locked through check and removal. It refuses links (also spelled
`alias/` or `alias/.`), special files, drive roots, mount points, browse
roots or folders holding them, and anything an unfinished job uses.
Server POST /api/delete_path (400/404/409/500), Tauri delete_path; a
No / Yes, delete dialog on Inspect. Linux bind mounts are not caught
(TODO).
LZ4 pack into an image no longer fills the bar early: auto-loose
sampling, measure and the verify passes reserve the passes after them
(Ctx::reserve), one bar to 100% only at the end. Inspection reports the
bundled runtime version; Convert offers to install or replace an
unknown or missing AMPR runtime (lz4: "unpatch", on by default).
Server: session `url`, GET /api/qr (the url as an SVG QR code, qrcode
crate); the PS5 start notice names the tile only. Desktop: open_repo
opens the GitHub page in the default browser.
UI: tabs [Convert Inspect] | LZ4 | About; LZ4 tab in yellow with a new
empty source card, Pack/Unpack (folder, ffpkg, exfat, ffpfs), green
packed tile, neon Save as profile, fakelib warning, a short How LZ4
works; LZ4 job tags. The PS5 header shows its address (opens How to
connect with the QR code); About has a feature list and, on the PS5, a
How to connect card. Format names without the dot, bold in text.
Borderless cards, bigger glow, 14px tabs, 18px card titles.
Docs: AGENTS.md (delete as the third explicit exception), DESIGN.md,
README.md, ps5/README.md routes, TODO.md hardware checks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New crate ps5-dump-forge-lz4: AMPRPAK4 manifest writer and validating
reader (volumes, CRC sidecar, runtime profile), AMPRIDX3 and AMPRCMD1
readers, pack rules (TOML profile subset, traces, built-in keep-loose
list, auto-loose), embedded ampr_emu 0.4.2.1 release and trace runtimes
(vendor/ampr_emu, pinned by SHA-256; vendor patch 0023).
Core: trace (in-place folder patch/unpatch, image rebuild + replace),
pack into an LZ4 folder or straight into .ffpkg/.exfat/.ffpfs/.ffpfsc
(measure pass, no staging), unpack any packed source, traces zip
download and reader, Save as profile, LZ4 inspection facts. Every file
and folder written on the PS5 is 0777 (the app loader refuses game files
without world-execute, CE-107750-0). Traces only narrow the keep-loose
list: engine files opened before AMPR starts (.pak/.utoc/.ini) stay loose.
CLI --lz4-* flags and lz4-patch/lz4-unpatch/lz4-profile; server routes
lz4_patch, lz4_unpatch, lz4_traces (streamed zip), lz4_plan_profile;
LZ4 tab in the app. Trace room 256 MiB default, 1 GiB max (measured).
Fuzz targets, scripts/check-lz4.sh upstream cross-check, docs.
Console: Stellar Blade traced, packed (5 .ucas) and played; unpack and
0777 folders boot. Other titles and long sessions are still open (TODO).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Generated names are [GAME_TITLE]-[TITLE_ID] (no firmware). SMP nmounts every image at
/mnt/shadowmnt[/pfsc]/<stem>_<8 hex> and the PS5's MNAMELEN is 88, so a name without its
extension stays within 63 bytes (58 for .ffpfsc); folders and .pkg keep to the same 63.
The game title is cut first; preflight and the Convert tab refuse a longer typed name.
- An empty output dir means the source's folder, made absolute (a trailing `..` resolved),
never the process's working directory; the CLI routes through it.
- PS5 payload: each launch deletes earlier runs' serve-/log-<pid>.txt whose process is gone,
keeping the newest (and a running Forge's).
- UI: version in the window title (desktop and web); leftover .part card only when some are
found; Full verification and Remove backport in their own boxes; format copy reworked with
Recommended/Experimental colour-coded; .fpkg firmware <= 11.60 warning; the .pkg build-time
estimate removed; About formats is one table (Console speed, Size on disk, Folder row);
newest job in view after a reload; narrow-width and Inspect scroll fixes.
- Docs: README restructured (intro, platforms, features, formats table with the numbers);
PS5 payload internals moved to ps5/README.md; TODO.md and AGENTS.md cleaned up.
- CI: workflow artifacts kept 3 days.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Third-party FPKG reading (a real Oodle Kraken image): sparse extents in the
layout descriptor (vendor 0016), bare entropy-array halves (0017), param.json/NP files kept only
in the container. All 521 files of the test package read back; .pkg -> .exfat -> .pkg kept 520 of
them byte-identical (ampr_emu.index generated, versionFileUri cleared).
- pic1.png/pic2.png are container entries (0x1006/0x2040) and part of the system general
digest, as in a third-party package (vendor 0018).
- .pkg read: Kraken decoder speedups (vendor 0019) and multi-block reads checked and decoded on
every core; a batch is taken only when its stored bytes do not exceed its decoded ones.
A 188 GB package: 371 -> 1,233 MB/s.
- .pkg write/verify: write-stage digests, the builder's block sweep and playgo-chunk.crc on every
core (vendor 0020); fast verification now covers .pkg too, the builder's self-check sampled with
the job's seed (vendor 0021). An 89 GB folder -> .pkg: 11 min -> 5 min.
- Compression levels: .pkg fast (default) / balanced / smallest (picker with icons, --kraken);
.ffpfsc zlib 0-9, default 6, the measured knee (slider, --level; 0 stores raw). The .ffpfsc job
logs its settings and result; inspect shows the zlib level class.
- Every format: verification hashing on a pool of up to 8 threads (writes now at disk speed,
7.2 s -> 2.1 s for 13 GB); exFAT reads consecutive clusters as one run (vendor 0022); .ffpfsc
blocks inflate in parallel (0.66 -> 3.2 GB/s); incompressible blocks skip the zlib search
(.ffpfsc level 7 write 23.8 s -> 16.7 s for 13 GB).
Checked: fmt, clippy -D warnings, 489 tests, UI builds and smoke, PS5 payload build, vendor
series replay, Codex review. Console tests of the new paths are listed in TODO.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- PS5 payload (plain .elf): the core runs on the console, built in Docker against the
ps5-payload-dev SDK v0.43 (ps5/: target JSON, ps5-ai-cli shims, entry.c, compat.c, linker.sh;
FreeBSD 11 ABI via --cfg libc_unstable_freebsd_version="11", struct sizes asserted).
- New crate ps5-dump-forge-server and `ps5-dump-forge serve`: the React UI over HTTP on port 8095
(fetch transport, polling, folder/file browser, Show path, Stop), no access control by design.
Home-screen tile PDFG00001; the payload saves a copy of itself (two-stage build) so the tile's
AppCache'd page can start it through elfldr after a restart.
- FreeBSD platform layer in core: destination probe (dest.rs), publish by link or checked rename
behind a device guard, bounded dirty data with adaptive fsync cadence (durable.rs), read-ahead
(prefetch.rs), drive-removal messages, rest-mode PowerTick. A retried fsync fails the job.
- Fast verification is the default on every platform: structure + sampled BLAKE3 slices;
"Full verification" switch / --full-verify re-reads every byte; .pkg always full. One hash
pass per byte.
- vendor patch 0015: UFS2 range reads (cached pointer blocks, contiguous runs, checked offsets).
- Tests and tooling: scripts/test-freebsd.sh (FreeBSD VM: UFS, FAT32, nullfs),
scripts/release-ps5.sh (ELF, embedded UI, self copy and debug-route checks), CI and release
jobs for the .elf.
- Hardware (PS5 fw 13.60, /data): .ffpkg/folder sources to .exfat and folder pass their checks;
writes ~273 MB/s of the drive's ~288 MB/s; tile launch after a reboot works. Other output
formats and USB output are not console-tested yet (TODO.md).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>