* feat: project skeleton, build system, and CI (#1) Stage 1/6: OpenOrbis Makefile (.pkg verified), SDL2 smoke screen, module loader, logging facade, cJSON + dbglogger vendored, GitHub Actions CI, assets. Title ID RPIN00001. * feat: core services — network monitor, storage, pkg/SFO parsing, HTTP client (#2) * feat: transfer engine — BGFT wrappers, task manager, installer, adaptive prefetch (#3) Stage 3/6: BGFT wrappers (legacy already-installed semantics), AppInstUtil wrappers, task manager with 1 Hz progress poller + speed/percent + completion detection, full install pipeline (direct + ref_pkg_url), adaptive N-segment prefetch engine with shared chunk frontier, create-fself SDK-stub shim build fix. * feat: HTTP server — legacy API 1:1, v2 API, accelerated piece proxy (#4) Stage 4/6: threaded socket server, byte-compatible legacy API, v2 API (system/jobs/install/storage/logs), piece proxy streaming through the adaptive prefetch engine, log ring, netmon-driven server lifecycle. * feat: live on-screen dashboard — transfer cards, controls, activity log (#5) Stage 5/6: embedded bitmap font (generated, tintable atlas), dashboard with status strip + transfer cards (progress/speed/ETA) + activity log pane, controller controls incl. per-item pause/resume/stop/re-transfer, taskman is_ref. * docs: full API reference and README polish (#6) Stage 6/6: docs/API.md (legacy wire-compatible formats + v2 API), README polish (controls table, examples, dev layout), roadmap complete. * fix: audit pass — 8 bug fixes + keep-alive session reuse in transfer engine (#7) * fix: net stack teardown order and bounded SFO key reads - netmon: sceNetPoolDestroy was called with the mem id after it was already reset to -1, so the real pool leaked at shutdown. - sfo: key comparison read up to 64 bytes past the key table on malformed SFO data; bound it to the actual key length. * fix(taskman): reclaim terminal job slots, release already-installed jobs Terminal-state jobs kept their slots forever, so the registry filled up after 32 installs and every new install failed until the app restarted. When full, the oldest terminal slot is now reclaimed (the dashboard keeps showing the most recent jobs). ALREADY_INSTALLED jobs never fired the terminal event, so their proxy slot and temp manifest/icon leaked per attempt; they are now cleaned up and released when the BGFT task reports already-installed (task id -1). Also documents that the event hook runs with the registry lock held. * fix(server,installer): legacy error_code response for BGFT failures The original responds {"status":"fail","error_code":...} (HTTP 200) when BGFT task registration fails; the rewrite returned HTTP 500 with an error message instead. The BGFT error code is now carried through install_result_t and the legacy byte-compatible response is restored. Also: bound the shutdown wait for in-flight connections (a send stuck on a dead link could stall the netmon thread forever and block network-up recovery) and drop a needless 16-byte copy in the /api/v2/jobs/<id> route that truncated long ids. * fix(ui): run the re-transfer pipeline off the UI thread action_retry ran the full install prepare (pkg header, entry table, SFO/icon fetches plus one probe per piece) on the UI thread, freezing the dashboard and controller input for the duration; it now runs in a detached worker thread with the URL copied out of the job snapshot. * perf(http,prefetch): keep-alive session reuse, race-free teardown Every 2 MiB prefetch chunk previously created and destroyed its own template + connection, paying a full TCP/TLS handshake and slow start per chunk (thousands per large package). Workers now hold a reusable keep-alive session for the piece (one handshake), with a single retry on a stale connection. http_client_term() could destroy the HTTP context while prefetch workers were mid-request (network drop mid-transfer = crash risk); teardown is now deferred by an in-flight counter until the last request/session finishes. One-shot requests keep the previous behavior (fresh template per request). Also hoists the duplicated worker_ctx typedef to file scope. * chore(release): bump version to 0.0.1 (#8)
Remote PKG Installer NextGen
A modern rewrite of flatz's ps4_remote_pkg_installer for jailbroken PS4 consoles, built with the OpenOrbis PS4 Toolchain.
Install PKG packages remotely over your network from any device — no USB drives — with a live on-screen dashboard: active transfers with real-time speed and progress, pause/resume/stop/re-transfer controls per item, storage status, and an activity log.
Highlights
- Live dashboard UI (dark tech theme) — no more static splash screen
- Per-item controls — pause, resume, stop, and re-transfer each transfer
- Stability first — works with or without a network connection; the server starts automatically once a link is available, and the app never crashes offline
- Faster transfers — adaptive multi-segment HTTP downloads for staged installs
- Legacy API compatible — the original Web API is preserved 1:1, so existing tools (remote_installer, web frontends, scripts) keep working
- New v2 API — a cleaner REST interface with job management, progress, and logs
- Community friendly — plain C11, one Makefile, CI builds every push
Requirements
- PS4 with HEN (or any kernel payload providing fPKG support +
/datamount), same as the original application - A device on the same network to send commands (PC, phone, ...)
Building
Requires the OpenOrbis PS4 Toolchain
(OO_PS4_TOOLCHAIN env var), clang, lld, and python3.
export OO_PS4_TOOLCHAIN=/path/to/OpenOrbis/PS4Toolchain
make
The final package is IV0000-RPIN00001_00-RPINEXTGEN000000.pkg.
Every push and pull request is built by CI (see .github/workflows/build.yml);
grab the .pkg from the workflow artifacts.
Usage
- Install the package on your PS4 (HEN must be active).
- Launch it — the dashboard shows the console's IP, storage and transfers.
- Send installs from any device on the same network (see below). The app works with or without a network link: the server starts automatically once a link is available, and the app never exits on its own.
- Transfers run through the system's BGFT download manager — they continue even after the app closes.
On-screen controls
| Button | Action |
|---|---|
| D-pad up/down | Select transfer |
| X (cross) | Pause / resume the selected transfer |
| O (circle) | Stop the selected transfer |
| [ ] (square) | Re-transfer (re-run a completed/failed/stopped transfer) |
| OPTIONS | Exit |
Quick start (from a PC)
# Check the server
curl http://<PS4-IP>:12800/api/v2/system
# Install a package (URL served by any web server on your network)
curl -v 'http://<PS4-IP>:12800/api/install' \
--data '{"type":"direct","packages":["http://<PC-IP>:8080/UP0001-CUSA09311_00-GAME.pkg"]}'
# Watch progress (speed, percent, ETA)
curl 'http://<PS4-IP>:12800/api/v2/jobs'
# Pause / resume / stop a job
curl 'http://<PS4-IP>:12800/api/v2/jobs/1/pause' -X POST
curl 'http://<PS4-IP>:12800/api/v2/jobs/1/resume' -X POST
curl 'http://<PS4-IP>:12800/api/v2/jobs/1/stop' -X POST
The full API reference (legacy + v2) is documented in docs/API.md.
Roadmap
- Project skeleton, build system, CI
- Core services (logging, network monitor, storage info, pkg/SFO parsing, HTTP client)
- Transfer engine (BGFT wrappers, task manager, adaptive multi-segment prefetch)
- HTTP server (legacy API 1:1, v2 API, /static/ + accelerated piece proxy)
- Live on-screen dashboard (status strip, transfer cards, activity log, controller controls)
- Docs & polish (API reference)
Development
Host unit tests cover the portable core (util/SFO/pkg parsing) and run on every push:
make test
Fixtures in tests/data/ are generated from a real build (param.sfo and
the first 0x3000 bytes of a real package header).
Regenerate the embedded bitmap font after changing the generator:
python3 tools/gen_font.py # requires Pillow
Project layout:
src/ application code (C11, no framework)
thirdparty/ vendored cJSON + dbglogger (MIT), custom libSceBgft stub
tools/ asset/font generators, host unit tests
tests/data/ unit test fixtures
docs/API.md HTTP API reference (legacy + v2)
Credits
- flatz — the original Remote Package Installer
- OpenOrbis Team — the OpenOrbis PS4 Toolchain and SDL2 port
- DaveGamble — cJSON (MIT)
- bucanero — dbglogger (MIT)
License
GPL-3.0 — see LICENSE.