store: add NoPayStation source (PSP + PS1 Classics .pkg)

New 'NoPayStation' option in the Store tab lists PSP_GAMES.tsv and
PSX_GAMES.tsv, downloads each item's encrypted .pkg and decrypts/extracts
it with pkg2zip into a configurable output dir (<dir>/PSP/<TITLE_ID>/ and
<dir>/PSX/<TITLE_ID>/). Downloaded PSP games and PS1 Classics appear in the
Library (games/eboot and ps1/eboot respectively) and copy to the PSP as
PSP/GAME folders.

- app/nopaystation.py: TSV fetch/parse (cached) + pkg2zip discovery/extract.
- app/transfers.py: NoPayStationSource (scan + download).
- Settings: NPS output dir + pkg2zip path (QSettings nps_dir/pkg2zip_path).
- StorePage: NPS source + content-type combo (PSP Games / PS1 Classics),
  per-item cover system, TSV release dates, nps-download job kind.
- Library: _nps_library_items ingest, on-PSP detection, folder copy/delete,
  PPSSPP play disabled for encrypted PSP EBOOTs.
- README: document the source, pkg2zip + npdrm_free requirements.
This commit is contained in:
2026-09-07 21:18:55 -04:00
parent 4b6e407b3f
commit 53f671d09a
5 changed files with 444 additions and 42 deletions
+35 -4
View File
@@ -1,6 +1,6 @@
# PSP Preservation Tool
the name is terrible, i know.
![AI Generated](https://raw.githubusercontent.com/dotnetdave/ai-usage-badges/refs/heads/main/badges/png/1x/ai-generated.png)
Native Linux GUI (PySide6) for preserving PSP UMD **games** and **videos** as
@@ -18,9 +18,9 @@ converts PlayStation 1 ISO/CUE/BIN rips into PSP `EBOOT.PBP` homebrew.
- **Library** — scan folders of `.iso` discs, verify against the DAT catalog,
browse with cover art, search/filter, see per-game details (developer,
publisher, genre, release date, synopsis, trailer), and launch discs in PPSSPP.
- **Store** — browse and download discs from three sources: a local 7z folder,
your own HTTP store server, or an archive.org item (see
[Store](#store--archiveorg-and-local-folder)).
- **Store** — browse and download discs from four sources: a local 7z folder,
your own HTTP store server, an archive.org item, or NoPayStation (PSP/PS1
PSN `.pkg` content) (see [Store](#store--archiveorg-and-local-folder)).
- **Queue** — background transfers with progress, cancel, per-row delete, etc.
- **PSP Sync** — detect a connected PSP (USB) or a mounted UMD, inventory what's
installed (games / UMD videos / homebrew / PKG), copy discs to the PSP, delete
@@ -38,6 +38,8 @@ converts PlayStation 1 ISO/CUE/BIN rips into PSP `EBOOT.PBP` homebrew.
- Linux + Python 3
- `PySide6` — the only Python dependency (`pip install -r requirements.txt`)
- `7z` (p7zip) — used to peek/extract disc images from store archives
- `pkg2zip` (optional) — decrypts NoPayStation `.pkg` files (see
[NoPayStation](#4-nopaystation))
- PPSSPP (optional) — to launch discs from the details panel
## Install
@@ -132,6 +134,9 @@ QSettings under `PSPPreserve`) taking precedence where noted.
| `PSP_ARCHIVE_ITEM` | `psp-redump-roms321.com` | archive.org item identifier |
| `PSP_ARCHIVE_LOGGED_IN_SIG` | *(empty)* | archive.org `logged-in-sig` cookie |
| `PSP_ARCHIVE_LOGGED_IN_USER` | *(empty)* | archive.org `logged-in-user` cookie |
| `PSP_NPS_DIR` | `<state>/nps` | NoPayStation output folder |
| `PSP_NPS_TSV_BASE` | `https://nopaystation.com/tsv/` | NoPayStation TSV base URL |
| `PSP_PKG2ZIP_PATH` | *(empty)* | pkg2zip binary path (else auto-detected) |
| `PSP_API_TOKEN` | *(empty)* | server API bearer token (unset = open) |
| `PSP_CREDENTIALS` | `$PSP_DATA_DIR/credentials.json` | credentials file |
| `PSP_LIBRETRO_COVERS_URL` | *(empty)* | direct URL for `libretro-covers.zip` (else derived from store server) |
@@ -258,6 +263,32 @@ If the item's files are marked **private** (login required), set the
from a logged-in archive.org browser session). Without them, private files are
skipped — and you'll get a clear error if *everything* in the item is private.
### 4. NoPayStation
The **NoPayStation** source lists PSN content from
[NoPayStation](https://nopaystation.com/) — **PSP games** (`PSP_GAMES.tsv`) and
**PS1 Classics** (`PSX_GAMES.tsv`), selectable from the content-type dropdown
next to the source selector.
Requirements & behaviour:
1. Install [`pkg2zip`](https://github.com/mmozeiko/pkg2zip) (the same tool the
pkgi family uses) and either put it on `PATH` or set its path in
**Settings → Store**. NoPayStation `.pkg` files are encrypted PSN packages,
not ZIPs — `pkg2zip` decrypts them.
2. Set **NoPayStation output dir** in **Settings → Store** (default
`$PSP_STATE_DIR/nps`).
3. Downloading a PSP game writes `PSP/<TITLE_ID>/EBOOT.PBP`; a PS1 Classic
writes `PSX/<TITLE_ID>/EBOOT.PBP`. Both then show up in the **Library**
(PS1 Classics under **PS1**, PSP games under **Games**) and can be copied to
the PSP like any other item.
4. The TSV lists are cached in the state dir and refreshed on each store scan.
> **DRM note:** NPS content is PSN-DRM'd. To *run* it on the PSP you need the
> [`npdrm_free`](https://github.com/qwikrazor87/npdrm_free) plugin (ARK and most
> CFW already ship it). The desktop app only downloads and decrypts; it doesn't
> strip DRM.
## Server setup
The catalog + store API is a single-file, stdlib-only HTTP server