Archive of https://github.com/blackbearreloaded/ProsperoRadio — A radio player for PS5, possible thanks to RadioBrowser database https://github.com/blackbearreloaded/ProsperoRadio
  • C++ 84.2%
  • Shell 6.9%
  • Python 3.4%
  • PowerShell 3%
  • C 1.5%
  • Other 1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-12 23:15:06 -04:00
.github Publish the compiler cache snapshot from its own workflow 2026-10-10 10:47:41 -04:00
assets Rebuild the interface on ps5-homebrew-ui with libcurl networking, elevation and an update check 2026-10-03 18:52:25 -04:00
docs Remove links to the research repositories (#4) 2026-10-09 15:02:17 -04:00
include Use upstream Lapy for filesystem access and update from inside the app 2026-10-04 23:19:04 -04:00
runtime Make build pipeline self-contained with native C++ 2026-08-26 13:03:44 -04:00
sce_sys No video mode change at launch: declare HDR output and no VRR in param.json (#6) 2026-10-11 13:55:48 -04:00
src Lapy helper: SDK v0.42 and 32-byte credential attributes (#1) 2026-10-06 01:07:46 -04:00
tests Remove the .ffpkg image and its UFS2Tool tooling: the build makes the app folder, CI its ZIP, nothing else 2026-10-08 21:19:57 -04:00
third_party Fall back to the catalog's mirror when homebrew.page can't be reached (#3) 2026-10-08 23:45:56 -04:00
tooling Use upstream Lapy for filesystem access and update from inside the app 2026-10-04 23:19:04 -04:00
tools Build on ps5-opengl SDK 1.0.2 (#8) 2026-10-12 23:15:06 -04:00
ui-kit Rebuild the interface on ps5-homebrew-ui with libcurl networking, elevation and an update check 2026-10-03 18:52:25 -04:00
vendor Rebuild the interface on ps5-homebrew-ui with libcurl networking, elevation and an update check 2026-10-03 18:52:25 -04:00
.clang-format Make build pipeline self-contained with native C++ 2026-08-26 13:03:44 -04:00
.clang-tidy Make build pipeline self-contained with native C++ 2026-08-26 13:03:44 -04:00
.editorconfig Enforce source attribution headers 2026-08-26 01:05:24 -04:00
.env.example Remove the .ffpkg image and its UFS2Tool tooling: the build makes the app folder, CI its ZIP, nothing else 2026-10-08 21:19:57 -04:00
.gitattributes Port PSRadio to the native C++20 template 2026-08-27 22:06:32 -04:00
.gitignore Improve project setup and reproducibility 2026-08-26 20:03:57 -04:00
build.ps1 Remove the .ffpkg image and its UFS2Tool tooling: the build makes the app folder, CI its ZIP, nothing else 2026-10-08 21:19:57 -04:00
CONTRIBUTING.md Rebuild the interface on ps5-homebrew-ui with libcurl networking, elevation and an update check 2026-10-03 18:52:25 -04:00
LICENSE Initial release 2026-08-23 00:07:49 -04:00
Makefile Remove the .ffpkg image and its UFS2Tool tooling: the build makes the app folder, CI its ZIP, nothing else 2026-10-08 21:19:57 -04:00
README.md Remove links to the research repositories (#4) 2026-10-09 15:02:17 -04:00
ROADMAP.md Rebuild the interface on ps5-homebrew-ui with libcurl networking, elevation and an update check 2026-10-03 18:52:25 -04:00
THIRD_PARTY_NOTICES.md Remove the .ffpkg image and its UFS2Tool tooling: the build makes the app folder, CI its ZIP, nothing else 2026-10-08 21:19:57 -04:00

ProsperoRadio icon

ProsperoRadio

A native Internet-radio application for PlayStation 5 homebrew
Browse and search the Radio Browser catalogue with resilient disk-backed caching, native PS5 audio playback, and a controller-first OpenGL interface.

Build Latest release GPL-3.0-or-later

ProsperoRadio's home screen with a station playing: the Now Playing header, the Popular list and the letter rail

The picture shows ProsperoRadio running on a PlayStation 5 with a station on air.

Highlights

  • Browse more than 56,000 supported stations in a validated Radio Browser sync; the live total changes as the public catalogue evolves.
  • Explore 240 countries and hundreds of genres and languages with server-side paging, search, and on-demand filters.
  • Play AAC/AAC+, MP3, and Opus through native PS5 decoder paths, with validated Vorbis, FLAC, and Ogg-FLAC fallbacks.
  • Resolve audio-only AAC HLS, M3U/PLS playlists, and ICY metadata while recovering cleanly from malformed or interrupted streams.
  • Keep the catalogue and favourites fast and persistent in SQLite under /data/prosperoradio, with atomic refreshes and Radio Browser mirror failover.
  • Use a controller-first OpenGL interface built on ps5-homebrew-ui: a Now Playing view with a visualizer, a letter rail on every station list, sound controls (volume, bass, treble, balance), PS5 text input, and station names in every script.

Project foundations

Important

Built on the PS5 Native App Boilerplate. ProsperoRadio preserves the template's modern C++20 structure, .hpp interfaces, reproducible runtime, FSELF tooling, tests, deployment flow, and release automation.

Warning

Filesystem access comes from PS5-Lapy-JB-Daemon. The PS5 jailbreak environment must provide a local ELF loader on TCP port 9021. If a resident Lapy service is running it is used; otherwise ProsperoRadio sends its own packaged, title-specific upstream Lapy helper over that local connection. No separate Lapy payload is required for normal use, and ProsperoRadio contains no kernel code of its own. Without either, the app still runs, with its data in its sandbox (/download0). See src/elevation/README.md.

Important

The interface is built on ps5-homebrew-ui. The kit is a build dependency, not part of this repository: the build fetches a pinned commit of it, the pinned ps5-opengl SDK and the pinned HarfBuzz source into .deps/. See ui-kit/README.md.

Identity Value
Shell title ProsperoRadio
Title ID PPSA99001
Category Media
Current release version 01.000.010
Release-version source sce_sys/param.json
Writable data /data/prosperoradio

Features

  • Browse Popular, Trending, Top rated, Favorites, and Discover views.
  • Search live Radio Browser data by text, country, genre, language, and bitrate, with mirror failover and server-side paging.
  • Keep a large SQLite catalogue and favourites on /data/prosperoradio; a failed sync leaves the last verified catalogue untouched.
  • Navigate entirely with the DualSense D-pad or left analogue stick; the PS5 IME handles text entry.
  • Draw station names in every script (Arabic, Cyrillic, Chinese, Persian and more) with the console's own fonts, HarfBuzz shaping and right-to-left ordering.
  • Update from inside the app: when homebrew.page lists a newer release, ProsperoRadio offers to install it each time it opens; Skip keeps the current version. See Updating.
  • Keep everything it writes in one place outside the app folder, /data/prosperoradio, so an update never touches it. See Where ProsperoRadio keeps its files.
  • Play AAC/AAC+ and MP3 through native PS5 decoding; play Opus through the native Opus/CELT decoder route; play Vorbis and FLAC/Ogg-FLAC with bounded CPU decoders.
  • Resolve bounded M3U/PLS indirection, strip ICY metadata, and support the audio-only AAC HLS subset.

App-specific codec limits and validation are documented in Architecture, Codec investigation, and Roadmap.

Requirements

Build from Linux, WSL, or a Linux CI runner. On Ubuntu, Debian, or WSL:

sudo apt update
sudo apt install curl git make pkg-config python3 python3-venv tar unzip wget zip \
  clang-18 clang-format-18 clang-tidy-18 lld-18 libsqlite3-dev

The repository downloads, verifies, and caches the public PS5 Payload SDK, zlib, PacBrew's SQLite and libcurl ports, the interface kit, the ps5-opengl SDK, HarfBuzz, the pinned upstream Lapy helper sources, and GoogleTest below ignored .deps/. No proprietary SDK, system module, key, or game asset is included or fetched.

Run a read-only prerequisite check before building:

make doctor

See Getting started and Native tooling for build-environment detail.

Build

sce_sys/param.json is the only identity and release-version source. Do not change PPSA99001 when updating ProsperoRadio: changing it produces a separate PS5 title rather than an update.

make

The output is the complete title folder:

dist/PPSA99001/

Releases are that folder as one file, PPSA99001.zip, with its SHA256SUMS. A release ZIP built by the workflow can be checked with gh attestation verify PPSA99001.zip -R blackbearreloaded/ProsperoRadio (GitHub CLI); this covers releases built by GitHub Actions from now on, not earlier ones. A release is made by pushing the version tag: the workflow builds, attests and publishes both files, and nothing is attached by hand. It creates the release, or adds the files to one that has no ZIP yet (notes written in advance, or a draft); a release that already has a ZIP is never changed, and the run says so (Build output and release ZIP). The ZIP is the only release file: the app updates itself in place, and that needs a folder install.

The app is a Media category title. Stage the whole folder, not eboot.bin alone. For a local development loop against an already-running FTP service:

make deploy PS5_HOST=192.168.4.30

Note

The first launch can take a while while ProsperoRadio downloads, validates, and caches the Radio Browser catalogue. Keep the console online and leave the app open until the database finishes loading; later launches use the local cache.

Where ProsperoRadio keeps its files

The app itself stays in /data/homebrew/PPSA99001 (or wherever ShadowMountPlus mounts it from). Everything it writes is in /data/prosperoradio:

/data/prosperoradio/
├── config/     settings.txt, the favourites, the update check's sequence number
├── catalog/    the station catalogue (rebuilt by a refresh)
└── logs/       prosperoradio.log and the previous session's

Favourites and the catalogue an earlier version kept in its sandbox are copied over on the first start. Without filesystem access (no resident Lapy service and no ELF loader on port 9021) the same files stay in the title's sandbox, /download0, as in release 01.000.005.

Updating

From the app

When a newer release is listed on homebrew.page, ProsperoRadio says so each time it opens:

  • Update now downloads the release ZIP from its GitHub release, checks it against the SHA-256 in the catalog's signed list, and unpacks it beside the app. A ring shows how far it is and the time left; Circle cancels, and nothing has changed until the end. Then ProsperoRadio closes, the update helper (self-updater.elf, sent to the console's payload loader on port 9021) replaces the app's files, and the console shows a notification. Open ProsperoRadio again to use the new version.
  • What's new (or Triangle) shows the release's notes, when it has any, in a view that scrolls; Update now is there too.
  • Skip keeps the current version until the next time the app opens.

Your favourites, settings and catalogue are in /data/prosperoradio, outside the app, so an update keeps them; files you put in the app folder yourself stay too. If the download or the unpacking fails, the dialog says why and offers Try again; the app stays as it was. Without a network, or without an answer, nothing is shown. When ProsperoRadio cannot install the release itself (for example a copy installed as an image, which the helper does not rewrite), a notice at the top right says Update available for ten seconds instead, and the manual steps below still work.

By hand

  1. Fully close ProsperoRadio.
  2. From the latest release, download PPSA99001.zip.
  3. Extract it locally, then upload the entire PPSA99001/ folder over FTP so its destination is /data/homebrew/PPSA99001/, and wait for the transfer to finish. Do not upload the ZIP file itself.
  4. If an earlier release was installed as /data/homebrew/PPSA99001.ffpfsc, remove that image: do not keep it beside the folder. Restart ShadowMountPlus cleanly or restart the PS5.
  5. Start the approved services normally, wait for ShadowMountPlus to rediscover PPSA99001, then launch ProsperoRadio and confirm the version shown below the app name.

Do not relaunch immediately after replacing the app: ShadowMountPlus may still have the previous folder mounted. The catalogue, favourites and settings are in /data/prosperoradio, outside the app, so they are kept; Shell presentation metadata may remain cached.

The deployer writes only title-scoped paths below /data/homebrew. It uploads each file through a temporary name, then publishes eboot.bin and sce_sys/param.json last. For console protocol and evidence requirements, see Deployment and Testing.

Test and quality gates

make test            # C++ unit tests, UI/metadata tests, 16 codec/catalogue checks
make lint            # formatting, static analysis, metadata, and shell checks
make check           # lint + all host tests + complete folder build

The test suite runs entirely on the host and never contacts a console. It covers RML/UI asset consistency, catalogue persistence, mirror/query parsing, AAC timing, MP3 framing, ICY metadata, PCM/retry behaviour, Ogg/Opus, Vorbis, FLAC, HLS/MPEG-TS, controller input, and Arabic/RTL text ordering. The PS5-only boundary is documented in Testing.

For pull requests and version tags, GitHub Actions runs linting, every host test, deterministic runtime reproduction, and the app-folder build. A push to main builds nothing: start a build there by hand (Actions, Build, Run workflow). When an exact contentVersion tag is pushed, the workflow archives that folder, verifies the archive, and publishes PPSA99001.zip with its SHA256SUMS file. Every pull request gets an installable build named by its number and commit: see Pull-request builds.

Source layout

src/main.cpp                  Application lifetime, renderer, fonts, and the frame loop
src/app/                      The interface: screens, session state, platform seam
src/radio_http_curl.cpp       The service's HTTP calls on libcurl
src/elevation/                Filesystem access: the client of upstream Lapy
src/update_kit/               The self-update kit's sources, compiled as the app's
ui-kit/                       What the app takes from ps5-homebrew-ui and lays over it
src/radio_text.cpp            C++20 UTF-8 visual-order helper
src/*.hpp                     Private C++ application interfaces
include/*.hpp                 Public codec, catalogue, input, and service interfaces
vendor/                       Checked-in SDL2, decoder, stb, and PS5 SDK inputs
third_party/update_check/     The update check and self-update of the PS5 Native App Boilerplate
third_party/self_update_helper/  The payload that replaces the app's files (self-updater.elf)
tests/console/                Scripted console runs for tools/console-run.py
tools/build.sh                Template-native compile/link/FSELF/folder assembler
tooling/native/               Template-owned native ELF and FSELF tooling
tests/                        GoogleTest and Python integration regressions
sce_sys/param.json            Shell metadata, title identity, and release version
docs/                         Architecture, testing, codec, build, and deployment documentation

ProsperoRadio is a C++20 application throughout. Repository-owned interfaces use the boilerplate's .hpp convention; portable codec, demux, persistence, input, and service modules are independently testable C++ translation units. Vendored single-file decoders retain their upstream filenames and are compiled through small C++ adapters. See Template port notes.

Versioning and releases

contentVersion in sce_sys/param.json drives the packaged metadata, top-bar UI version, Git tag, and GitHub Release name. It uses PS5's exact NN.NNN.NNN format without a v prefix.

# After updating sce_sys/param.json and passing the local gates.
git tag 01.000.005
git push origin main 01.000.005

The workflow rejects a mismatched tag. Full field meanings, Game/Media metadata, and the import-linking configuration are in Configuration.

Credits

Built with the PS5 Payload SDK by John Törnblom (ps5-payload-dev). Third-party components, authors and licenses are listed in THIRD_PARTY_NOTICES.md.

License

Copyright © 2026 BlackBearReloaded. Licensed under GPL-3.0-or-later; see LICENSE. Third-party components keep their own licenses. Binary releases are built from the tagged source in this repository.

Disclaimer

  • No affiliation. This is an independent homebrew project. It is not affiliated with, endorsed by, or sponsored by Sony Interactive Entertainment. "PlayStation", "PS5" and related marks are trademarks of Sony Interactive Entertainment Inc. This project is not affiliated with or endorsed by Radio Browser.
  • No proprietary material. No Sony SDK, firmware, encryption keys or decrypted system modules are included.
  • No warranty. This project is provided "as is", without warranty of any kind, to the extent permitted by law. See sections 15 and 16 of the GPL.
  • Use at your own risk. Running homebrew requires a modified console, which may void its warranty, breach the platform's terms of service, or cause data loss.
  • Legal use only. Use it only with hardware, accounts and content you own. This project does not support or enable piracy.

AI assistance

This project was developed with AI assistance from OpenAI and/or Anthropic tools.