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.
75 lines
3.6 KiB
Python
75 lines
3.6 KiB
Python
"""Central configuration, driven by environment variables."""
|
|
import os
|
|
from pathlib import Path
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
|
|
|
DATA_DIR = Path(os.environ.get("PSP_DATA_DIR", str(PROJECT_ROOT / "data")))
|
|
DATS_DIR = Path(os.environ.get("PSP_DATS_DIR", str(DATA_DIR / "dats")))
|
|
|
|
|
|
def _default_state_dir():
|
|
"""Local state directory (fast, reliable local disk).
|
|
|
|
SQLite locking is unreliable over network filesystems (SMB/FUSE), so the
|
|
library DB and the cover cache live on local storage while DATs, manual
|
|
covers and credentials stay in ``DATA_DIR`` (which may be a network share).
|
|
"""
|
|
xdg = os.environ.get("XDG_STATE_HOME")
|
|
base = Path(xdg) if xdg else Path.home() / ".local" / "state"
|
|
return base / "psp-preserve"
|
|
|
|
|
|
STATE_DIR = Path(os.environ.get("PSP_STATE_DIR", str(_default_state_dir())))
|
|
DB_PATH = Path(os.environ.get("PSP_DB_PATH", str(STATE_DIR / "library.sqlite")))
|
|
COVERS_DIR = Path(os.environ.get("PSP_COVERS_DIR", str(STATE_DIR / "covers")))
|
|
LEGACY_DB_PATH = DATA_DIR / "library.sqlite"
|
|
LEGACY_COVERS_DIR = DATA_DIR / "covers"
|
|
|
|
# Redump 7z store (browsable in the Store tab). Env override; GUI setting wins.
|
|
STORE_ROOT = Path(os.environ.get("PSP_STORE_DIR", "/media/downloads/Sony - PlayStation Portable"))
|
|
|
|
# Remote store server (HTTPS). Used by the Store tab as the primary source.
|
|
STORE_SERVER_URL = os.environ.get("PSP_STORE_SERVER", "https://psp.ceaf.dev")
|
|
STORE_TOKEN = os.environ.get("PSP_STORE_TOKEN", "")
|
|
|
|
# Optional direct URLs for the offline cover bundle zips. When unset, the GUI
|
|
# derives them from the store server URL (/api/covers/<name>.zip).
|
|
LIBRETRO_COVERS_URL = os.environ.get("PSP_LIBRETRO_COVERS_URL", "")
|
|
OVGDB_COVERS_URL = os.environ.get("PSP_OVGDB_COVERS_URL", "")
|
|
|
|
# archive.org item hosting the same Redump 7z set (identifier or full URL).
|
|
ARCHIVE_ITEM = os.environ.get("PSP_ARCHIVE_ITEM", "psp-redump-roms321.com")
|
|
|
|
# Optional archive.org login cookies (for items whose files are "private" /
|
|
# login-required). Grab these from a logged-in browser session on archive.org.
|
|
ARCHIVE_LOGGED_IN_SIG = os.environ.get("PSP_ARCHIVE_LOGGED_IN_SIG", "")
|
|
ARCHIVE_LOGGED_IN_USER = os.environ.get("PSP_ARCHIVE_LOGGED_IN_USER", "")
|
|
|
|
# NoPayStation: where extracted .pkg content lands, and the TSV source base.
|
|
# PSP games go to <NPS_OUTPUT_DIR>/PSP/<TITLE_ID>/; PS1 Classics to .../PSX/.
|
|
NPS_OUTPUT_DIR = Path(os.environ.get("PSP_NPS_DIR", str(STATE_DIR / "nps")))
|
|
NPS_TSV_BASE = os.environ.get("PSP_NPS_TSV_BASE", "https://nopaystation.com/tsv/")
|
|
|
|
# pkg2zip binary used to decrypt/extract NPS .pkg files (blank = auto-detect).
|
|
PKG2ZIP_PATH = os.environ.get("PSP_PKG2ZIP_PATH", "")
|
|
|
|
# Scan roots (used by the scanner phase). Comma-separated in env.
|
|
GAMES_ROOTS = [Path(p) for p in os.environ.get("PSP_GAMES_ROOTS", "/data/umd_games").split(",") if p.strip()]
|
|
VIDEO_ROOTS = [Path(p) for p in os.environ.get("PSP_VIDEO_ROOTS", "/data/umd_videos").split(",") if p.strip()]
|
|
|
|
# PS1: source folder (raw ISO/BIN/CUE) and converted EBOOT.PBP output folder.
|
|
PS1_ROOTS = [Path(p) for p in os.environ.get("PSP_PS1_ROOTS", "/data/ps1").split(",") if p.strip()]
|
|
PS1_OUTPUT_DIR = Path(os.environ.get("PSP_PS1_OUTPUT_DIR", "/data/ps1_converted"))
|
|
|
|
# Only .iso discs are tracked; everything below is explicitly ignored.
|
|
DISC_EXTENSIONS = {".iso"}
|
|
IGNORED_EXTENSIONS = {".pkg", ".pbp", ".cso"}
|
|
|
|
# PS1 source images (scanned separately from PSP .iso discs).
|
|
PS1_EXTENSIONS = {".cue", ".iso", ".img", ".bin"}
|
|
|
|
# Parallel hashing workers for the scanner. Keep at 1 on spinning disks
|
|
# (concurrent reads cause seek thrash); raise it for SSD / fast arrays.
|
|
SCAN_WORKERS = int(os.environ.get("PSP_SCAN_WORKERS", "1"))
|