Audit log, Connection, Game activity and Processes showed a different icon in
their header than in the menu; Cheats shared the Games gamepad, Edit game image
shared the Volumes drive, Processes shared the Console CPU. Now: audit log
shield-check, connection cable, game activity clock, processes layers, cheats
wand, edit game image file-pen, games gamepad.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Screens sat in a mix of centered 3xl/4xl/5xl columns with 16 or 24 px padding,
leaving half a wide window empty on some and not others. All screen roots (and
the tabbed shell) now use the shared app-page frame: one max width, 24 px
padding, 16 px on phones. Convert puts the game and its options beside
building and the queue at xl widths. The queue's Start button only shows when
something is waiting.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The browser build showed developer errors ("'faq_load' requires the Tauri desktop
client… Guard the call site…") on FAQ and in Settings → Keep awake, and its
Capture button could only fail. FAQ/CHANGELOG are bundled into the web app as
lazy chunks; Keep awake reports unsupported there; Capture is desktop-only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Registration copies sce_sys into /user/appmeta/<id>; Sony's uninstall doesn't
know about that copy, and the app lists every appmeta folder as installed, so
an uninstalled folder game stayed in Games. Once Sony confirms the uninstall
of our own registration, the flat folder is removed (files only, no recursion).
Verified on the Phat: register → unregister → appmeta gone, not listed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add this game / Add games from a folder… queue builds on this computer, one at
a time, each shown by the Convert screen's own stage view. After converting:
keep the package, or Stream & install / Upload & install - the package is
handed to the console queue and the next build starts while it installs
(a console dump still swaps inside its build). Optional delete after a
verified install. Reorder, remove, stop after the current build; a build
interrupted by a restart is built again, and the engine now clears an
interrupted build's stale .pkg.partial instead of refusing the rebuild.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two or more sources (multi-select pickers, a multi drop, or Add games from a
folder…, which lists a folder's children with games checked) switch Upload to
a review list: each row is inspected in the background (four at a time) and
shows its kind, size and where it lands; an encrypted .rar asks for its
password inline. Before adding: rows landing in the same place block, rows
already queued are skipped, and space per drive blocks only when it clearly
won't fit (warns when it can't tell). Shared destination, resume/overwrite and
only the options the list needs; Add N to queue / Upload N now. One source
still behaves exactly as before; a package dropped on Upload is uploaded and
installed (it no longer jumps to Install Package).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One app-wide viewer. A package, image or folder dropped on a screen without
its own drop zone opens it with Install… / Convert… (a drop no longer jumps
straight to Install Package); Convert views its game and its package; queue
rows view their package or source; File System and Connections → Browse get
View on packages, images and game folders (read on the console / server).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The client writes a request and its newline separately; a fake that answered
after the first segment closed over unread bytes, and the reset beat the
reply to the client (hello_over_socket flaked under load).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The viewer reads remote:// and ps5:// sources through the engine's opener, and
.pkg parsing now works over any reader, so a staged package opens straight
from the console: every Install Package row gets View details, reading the
local original when there is one. New GET /api/game/inspect/files lists a
package's entries or a tree's files (a windowed list for 200k-file dumps);
Images shows and saves every artwork; Related groups the title's other
library and queued packages base → update → DLC, each viewable.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A dump on the PS5 and its package share a title id, and ShadowMountPlus
re-registers a dump over an install, so a console source is never installed
beside its dump. The swap journals each step to /data/ps5upload/swap first,
parks the dump on its own volume (outside every scan root), waits for SMP to
let go, removes the leftover registration, installs through the queue, and
moves the dump back if anything fails. A running game stops it untouched.
The result offers Delete the old dump / Keep it parked (dropping its
manual.lst line); an interrupted swap is listed on Convert to put back or
finish.
Verified on the Phat (5.10) with a disposable fixture title: a failed install
rolled back (dump restored, SMP re-registered); a good one parked the dump and
left a real app.pkg install; Delete the old dump removed it and the journal.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A server folder or image is built straight off the server through the
engine's server file system (8 MiB read-ahead, retries) - no copy stage;
only a server archive is still copied, then unpacked. 'On the PS5' browses
the console and reads a dump through ftpsrv (:2121) as ps5://host/path;
installed games under /user/app are refused as encrypted. source::open
resolves remote:// and ps5:// through an opener the engine registers, so
build, estimate, inspect and the viewer all read them. Compression still
copies a server image first (it reads local disk).
Verified on the Phat (5.10): inspect + build of an image on the console
over ps5://, same package size as the local build; /user/app refused.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An archive is unpacked into .ps5upload-extract-<job> in the output folder as
its own Convert stage (progress, Cancel), the game found inside - a folder
however wrapped, or a single .exfat/.ffpkg/.ffpfsc image - is built, and the
unpack is removed when the run ends. Space for the files plus the package is
checked first; unpack folders left by an earlier run are swept. RAR takes a
password (never stored); a wrong one on a content-encrypted RAR now says so
instead of 'File CRC error', for uploads too. zip/7z are built without their
encryption features, so a protected one is refused with that reason. A server
archive is copied, then unpacked.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PfscReader is Read + Seek over a .ffpfsc's inner file, decoding 64 KiB zlib
blocks on demand with a small cache; the single-file layout parser is shared
with verify and bounds-checked for images users bring. exFAT and UFS2 sources
now open from any reader. A package built from a .ffpfsc is byte-identical
to the one built from its image.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Convert graduated; the switch revealed nothing and the README still told users
to enable Convert there. Stream install is Stream & install everywhere.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Cache key covers a folder's PARAM files and a package's split parts, and a
hit keeps its token alive.
- Content-id slicing can't panic; text read from an image or folder is capped;
a failing OS random source is an error, never a guessable token.
- SFO counts and levels show in decimal (flags and versions stay hex).
- "Entries" for a package, "Parental level" for PS4; Copy uses the shared
clipboard helper; a reply for an earlier path or console is ignored.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An accepted socket inherits the listener's O_NONBLOCK on BSD/macOS, so a read
before the client wrote returned WouldBlock and the request went unrecorded.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The library row already shows an upload failure; its queue row's Retry would
stage a copy nothing waits for. A browser-staged stream copy is deleted after
a failure, so its row (and the Retry via upload hint) could never work.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A second identical install now awaits the queued one instead of failing, and
Install Package rows show Queued/Installing and block Delete while their
install waits in the console queue.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A fresh single-file upload pre-sizes its .ps5up2-tmp to the full transfer
(posix_fallocate); a resume reopened it with O_APPEND, so the resumed
shards were written past the pre-sized end. A 1 GiB upload that dropped
and resumed grew to 1 GiB + the unsent remainder and COMMIT refused it
with size_mismatch (seen on the Android emulator).
Resume now opens without appending and seeks to entry->bytes_received
(the journal's acknowledged byte count). direct_open.h is header-only so
the new host self-test drives the same code on a real file.
Hardware (Phat 5.10): 1 GiB upload, engine killed at ~300 MB, resumed
with the same tx id — before: size_mismatch at 1,879,048,192 bytes;
after: committed at 1,073,741,824, SHA-256 identical to the source.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stream install → Stream & install (primary, first); Add package → Upload &
install (secondary). Install Package's description and empty state lead
with streaming; dropping a package streams it; Upload's .pkg card offers
Stream & install as the recommended route; Convert uses the same label.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A PS4 package's minimum firmware is PS4 firmware: never compared with the
PS5's (was a false red "can't run").
- Installed check comes from the preflight: unknown is no verdict (never
"not installed"), installed-without-version reads as installed, DLC and
updates are checked as themselves and say when the base game is missing,
an unknown package version is not compared.
- Space is checked against the roomiest single drive, not the sum.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Stop and Clear leave a running install running (Sony's install can't be
stopped); a new drain waits for it instead of re-queueing and running it
a second time, and its outcome is recorded even after Stop.
- The saved queue loads at app start; nothing is saved before it loads,
and anything queued before the load is kept.
- Reconnect-resume never re-runs a failed install; Retry failed resets
install rows cleanly.
- A failed install never stops the installs queued after it.
- Retry via upload installs after uploading and wins over a staged
variant (the old dialog's options), and drops the row only once the
upload is accepted.
- Rest mode after uploads ignores installs and an Install Package upload
whose install is queued next.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hardware (Phat, FW 5.10, web UI via Playwright):
1. Jak X base (3.6 GB) stream install running; its patch and a third
package queued behind it as Queued (#1)/(#2) — no refusal. Base then
patch installed; the game launched patched. PASS
2. Star Wars base + patch stream installs in sequence; launched. PASS
3. The third package's file was renamed before its turn: only that row
failed, with the reason and Retry; the others finished. PASS
4. Page reload mid-queue: not exercised on hardware (covered by the
browser-build unit test).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Queue panel sat below the link box and two info cards, out of view.
The activity bar and task list also mirrored install items as "Upload"
rows next to the install's own task, so every queued install showed twice.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stream install, Add package, Install all, Install link and External
Packages' Install used to disable while any install ran, so a second
stream install could not be queued from the screen. Installs queue per
console now; only deleting staged packages still waits.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Install rows say where the package comes from and their place in line,
show install progress, and offer Retry (and Retry via upload when the PS5
couldn't reach this computer). A running install has no Cancel: Sony's
installer can't be stopped halfway. The panel is now titled Queue in all
20 languages (several old titles read "Upload the queue").
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
addAndUpload keeps its checks (split sets, duplicates, variants, package
drive) and hands the transfer to the queue, mirroring the item's progress
onto the library row; its own port wait, transfer loop and watchdog are
gone. The install after upload is queued like any other.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A second install is queued instead of refused, and installs from any
source order base → update → DLC together. Each entry point keeps its
signature: it queues the install and resolves when that item finishes.
Download-first links download right away and queue the finished file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat(pkg): choose which drive install packages are kept on
Uploaded packages always went to internal storage
(/user/data/ps5upload/pkg_library), which fills the console's own drive.
The Volumes screen now lets you mark a drive "Use for packages"; new
packages are staged under <drive>/ps5upload/pkg_library on it.
- Per console, remembered on this device. Internal stays the default.
- Falls back to internal storage, with a notice, when the chosen drive
isn't connected.
- The package library lists packages on every drive; rows show the drive.
- The folder chain on the drive is created one level at a time.
- The External Packages scan skips a drive's ps5upload/ folder, so staged
packages aren't listed twice.
Hardware (Phat, FW 5.10): Star Wars Racer Revenge base+patch staged on
/mnt/ext0 installed, patched 01.00->01.02 and launched in 2 of 3 trials
(80 MB/s); the first stalled after the header read and is covered by the
daemon-recycle fix that follows. Internal control: 1/1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(install): recycle the installer daemon after a stalled delivery
A console-path install that stalls leaves the daemon's loopback job
"serving" until Sony reads every byte, which never happens, so every later
install was refused as "an install is already in progress" until the
daemon restarted, although the failure told the user to retry.
Measured on the Phat (FW 5.10). A stalled daemon-served install now stops
the daemon the same way a wedged stream refusal already did, and the next
install's ensure brings up a fresh one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* PS5Upload v5.36.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
release-posts.js
- Reads whole changelog groups (bold heading + wrapped bullets), not just
the first line of each bullet.
- X: link counted as 23 chars, replies packed to fit 280, markdown stripped.
- Discord: full bullets when they fit 2000 chars, short ones otherwise;
Reddit: real markdown sections instead of a code block.
- Says "pre-release" when GitHub does (gh), --prerelease/--stable to
override; --only and --out to pick a platform and write files.
- make release-post calls it directly; the .sh wrapper is gone.
Removed (outdated)
- ps5-install-trace.py, ps5-install-watch.py, fpkg-mount-test.py: drove
/api/pkg/install/start and the dpi-* routes, which no longer exist.
- gather-fakelibs.py: superseded by the app's Backport scan.
- pull_ps5_debug.py: pulled a debug dir the helper no longer writes to.
hw-test-loop.sh ran cargo from the repo root (no workspace there); it now
points at engine/Cargo.toml.
README: a Highlights section up top (unified install, Convert to FPKG,
sleep and wake), Android/web in the platforms badge, tested firmware 5.10 &
9.60.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The payload artifact keeps payload/installer/ps5upload-installer.elf as
installer/ps5upload-installer.elf; the image jobs still copied it from the
old dpi/ path and failed on the v5.35.0 tag.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>