Releases carry the frontends, with their notices and sources

A release build (PS5_RELEASE_TAG set) now builds the picker and ES-DE
unless PS5_FRONTENDS says otherwise (tools/build-title.sh). A
development build still carries them only when asked.

tooling/notices/components.json lists what the frontends ship:
- ES-DE 3.5.0 (MIT) with its own licenses folder;
- the Alekfull NX theme (CC BY-NC-SA 2.0, marked non-commercial; the
  picker's EmulationStation picture shows it);
- SDL2 (Zlib, the ps5-payload-dev fork);
- PS5_OpenGL (GPL-3.0-or-later, Mesa and its other parts in LICENSES/);
- FFmpeg (LGPL-2.1-or-later: no GPL parts configured), curl, Mbed TLS,
  FreeType, HarfBuzz, ICU, pugixml, libwebp and stb;
- the picker, with the notices the template staged for it.
The port, the payload SDK and the LLVM runtime list the frontends'
executables beside eboot.bin.

tools/stage-notices.py and tools/check-notices.py treat es-de/es-de.bin
and picker/picker.bin as executables: each must belong to a part, with
its digest recorded. tools/source-bundle.py archives a part's extra
sources (a library's tarball, a git tree at a pinned or fixed revision)
even when the part has no archive of its own. The bundle then holds
ES-DE's commit, the libraries' tarballs, the SDL fork, PS5_OpenGL, the
template, the UI kit and the template's SDK pin.

Checked: tests/test_notices.py PASS (a frontend executable must belong
to a part); a build with both frontends staged 46 parts, and
check-notices "covers every shipped executable"; source-bundle --list
names every frontend source. The release-tagged build and its
--release check follow this commit.
Gates: tools/verify.sh PASS (format unit build integration evidence).
This commit is contained in:
Mihawk committed 2026-10-04 23:20:37 -04:00
1 parent 2646f03cad
commit bdf8c3c605
6 files changed
+209 -13

No files matched your search

+17
View File
@@ -138,6 +138,23 @@ class Notices(unittest.TestCase):
problems = check.check(self.title, release=True)
self.assertEqual(problems, ["port: built from uncommitted source"])
def test_a_frontend_executable_must_belong_to_a_part(self):
# The frontends beside eboot.bin (es-de/es-de.bin, picker/picker.bin) are
# executables like it: each must belong to a part, with its digest recorded.
(self.title / "es-de").mkdir()
(self.title / "es-de/es-de.bin").write_bytes(b"frontend")
self.run_stage()
problems = check.check(self.title)
self.assertIn("es-de/es-de.bin belongs to no listed part", problems)
self.assertIn("es-de/es-de.bin has no recorded digest", problems)
table = json.loads(self.table.read_text())
table["components"][0]["artifacts"].append("es-de/es-de.bin")
self.table.write_text(json.dumps(table))
staged = self.run_stage()
self.assertEqual(check.check(self.title), [])
port = next(c for c in staged if c["id"] == "port")
self.assertEqual(port["executables"]["es-de/es-de.bin"], digest(b"frontend"))
def test_the_repository_table_names_existing_build_scripts(self):
table = json.loads((ROOT / "tooling/notices/components.json").read_text())
ids = [c["id"] for c in table["components"]]
+171 -3
View File
@@ -16,7 +16,7 @@
"name": "PS5 RetroArch (this port: title code, platform integration, build scripts and patches)",
"kind": "code",
"always": true,
"artifacts": ["eboot.bin", "retroarch.cfg", "LEGAL.txt", "sce_sys/param.json"],
"artifacts": ["eboot.bin", "retroarch.cfg", "LEGAL.txt", "sce_sys/param.json", "es-de/es-de.bin", "picker/picker.bin"],
"licence": "GPL-3.0-or-later",
"copyright": [
"Copyright (C) 2026 Mihawk",
@@ -54,7 +54,7 @@
"name": "PS5 payload SDK fork and its platform layer (libps5platform.a, headers, import stubs)",
"kind": "code",
"always": true,
"artifacts": ["eboot.bin", "cores/*.so"],
"artifacts": ["eboot.bin", "cores/*.so", "es-de/es-de.bin"],
"licence": "GPL-3.0-or-later",
"copyright": ["Copyright (C) 2022-2026 John Törnblom and ps5-payload-dev contributors", "Copyright (C) 2026 Mihawk (the platform layer)"],
"texts": [
@@ -82,7 +82,7 @@
"name": "LLVM libc++, libc++abi, libunwind and compiler-rt builtins (statically linked into eboot.bin; the cores resolve them from it)",
"kind": "code",
"always": true,
"artifacts": ["eboot.bin"],
"artifacts": ["eboot.bin", "es-de/es-de.bin"],
"licence": "Apache-2.0 WITH LLVM-exception",
"copyright": ["Copyright (c) 2003-2026 University of Illinois at Urbana-Champaign and the LLVM project contributors"],
"texts": [{"from": ["${LLVM}/llvm/LICENSE.TXT", "../PS5_LLVM/llvm/LICENSE.TXT"], "to": "LICENSE.TXT"}],
@@ -505,6 +505,174 @@
"remote": "https://github.com/libretro/overlay-borders"
},
"modifications": "Exact path corrections and exclusions recorded in video-assets.json and tooling/video-assets/collections.json. Full source trees and individual notices accompany the assets."
},
{
"id": "es-de",
"name": "ES-DE (EmulationStation Desktop Edition) 3.5.0, the EmulationStation frontend, and its own theme Linear",
"kind": "code",
"artifacts": ["es-de/es-de.bin", "es-de/LICENSE", "es-de/resources/**", "es-de/themes/linear-es-de/**"],
"licence": "MIT (ES-DE; what it bundles under the licences in licenses/)",
"copyright": ["Copyright (c) 2024-2026 Northwestern Software AB", "Copyright (c) 2020-2024 Leon Styhre", "Copyright (c) 2014 Alec Lofquist"],
"texts": [{"from": "build/es-de/src/LICENSE", "to": "LICENSE"}, {"from": "build/es-de/src/licenses", "to": "licenses"}],
"source": {"kind": "pin", "file": "tools/build-esde.sh", "var": "esde_commit", "url": "https://gitlab.com/es-de/emulationstation-de/-/tree/{rev}",
"extra": [{"name": "emulationstation-de", "git": ".deps/es-de", "pin": {"file": "tools/build-esde.sh", "var": "esde_commit"}, "remote": "https://gitlab.com/es-de/emulationstation-de/-"}]},
"modifications": "frontends/es-de/patches/0001-ps5-port.patch and frontends/es-de/ps5/ (PS5_RetroArch): built for the PS5, its systems and game lists from RetroArch's playlists, every game started in RetroArch (game mode)."
},
{
"id": "alekfull-nx-es-de",
"name": "Alekfull NX for ES-DE (the default EmulationStation theme on the PS5)",
"kind": "asset",
"artifacts": ["es-de/themes/alekfull-nx-es-de/**", "picker/previews/es-de.rgba"],
"licence": "CC-BY-NC-SA-2.0",
"noncommercial": true,
"copyright": ["Artwork and layouts by fagnerpc (AlekFull NX); the ES-DE port by anthonycaccese and the authors its README credits"],
"texts": [{"from": ".deps/alekfull-nx-es-de/README.md", "to": "README.md"}],
"source": {"kind": "pin", "file": "tools/build-esde.sh", "var": "alekfull_commit", "url": "https://github.com/anthonycaccese/alekfull-nx-es-de/tree/{rev}"},
"modifications": "Shipped as it is, without the artwork sources (.psd, .afdesign); the picker's EmulationStation card is a picture of it on the console."
},
{
"id": "sdl2",
"name": "SDL 2.30.12 (ps5-payload-dev's PS5 fork), as ES-DE's window, input and sound",
"kind": "code",
"artifacts": ["es-de/es-de.bin"],
"licence": "Zlib",
"copyright": ["Copyright (C) 1997-2025 Sam Lantinga"],
"texts": [{"from": ".deps/ps5-sdl/LICENSE.txt", "to": "LICENSE.txt"}],
"source": {"kind": "fixed", "revision": "8c56053f13ca13a0c050de613706ff69eb615836", "url": "https://github.com/ps5-payload-dev/SDL/tree/{rev}",
"extra": [{"name": "SDL", "git": ".deps/ps5-sdl", "revision": "8c56053f13ca13a0c050de613706ff69eb615836", "remote": "https://github.com/ps5-payload-dev/SDL"}]},
"modifications": "Built by PS5_OpenGL's integration/SDL2 (static-ps5.patch, ps5-joystick.patch, its OpenGL video bridge, the fork's PS5 audio driver)."
},
{
"id": "ps5-opengl",
"name": "PS5_OpenGL: OpenGL 4.6 for ES-DE (Mesa's Gallium, GLSL and NIR on the console's GPU), and its SDL2 integration",
"kind": "code",
"artifacts": ["es-de/es-de.bin"],
"licence": "GPL-3.0-or-later (PS5_OpenGL) AND MIT (Mesa) AND others stated in LICENSES/",
"copyright": ["Copyright (C) 2026 BlackBearReloaded", "Copyright (C) 2026 Mihawk", "Copyright the Mesa contributors (per-file notices in the source)"],
"texts": [{"from": "../PS5_OpenGL/LICENSE", "to": "GPL-3.0.txt"}, {"from": "../PS5_OpenGL/LICENSES", "to": "LICENSES"}, {"from": "../PS5_OpenGL/THIRD_PARTY_NOTICES.md", "to": "THIRD_PARTY_NOTICES.md"}],
"source": {"kind": "git", "path": "../PS5_OpenGL", "remote": "https://github.com/mihawk-99/ps5-opengl"},
"modifications": "mihawk-99's fork of blackbearreloaded/ps5-opengl; its dependencies.json pins the Mesa and OpenGNM sources it builds."
},
{
"id": "ffmpeg",
"name": "FFmpeg 8.1.1 (ES-DE's video previews: decoders and filters, no GPL parts)",
"kind": "code",
"artifacts": ["es-de/es-de.bin"],
"licence": "LGPL-2.1-or-later",
"copyright": ["Copyright the FFmpeg developers"],
"texts": [{"from": "build/ffmpeg-esde-ps5/src/COPYING.LGPLv2.1", "to": "COPYING.LGPLv2.1"}, {"from": "build/ffmpeg-esde-ps5/src/LICENSE.md", "to": "LICENSE.md"}],
"source": {"kind": "pin", "file": "tools/build-ffmpeg-esde.sh", "var": "version", "url": "https://ffmpeg.org/releases/ffmpeg-{rev}.tar.xz",
"extra": [{"tarball": ".deps/downloads/ffmpeg-8.1.1.tar.xz"}]},
"modifications": "Configured by tools/build-ffmpeg-esde.sh and linked statically into es-de.bin; ES-DE's and this port's source (both in the source archives) relink it."
},
{
"id": "curl",
"name": "curl 8.22.0 (ES-DE's scraper and downloads)",
"kind": "code",
"artifacts": ["es-de/es-de.bin"],
"licence": "curl",
"copyright": ["Copyright (c) 1996 - 2026, Daniel Stenberg and many contributors"],
"texts": [{"from": "build/curl-ps5/curl/COPYING", "to": "COPYING"}],
"source": {"kind": "pin", "file": "tools/build-curl.sh", "var": "curl_version", "url": "https://curl.se/download/curl-{rev}.tar.bz2",
"extra": [{"tarball": ".deps/downloads/curl-8.22.0.tar.bz2"}]},
"modifications": "Configured by tools/build-curl.sh, with mbedTLS for TLS."
},
{
"id": "mbedtls",
"name": "Mbed TLS 3.6.7 (curl's TLS)",
"kind": "code",
"artifacts": ["es-de/es-de.bin"],
"licence": "Apache-2.0 OR GPL-2.0-or-later",
"copyright": ["Copyright The Mbed TLS Contributors"],
"texts": [{"from": "build/curl-ps5/mbedtls/LICENSE", "to": "LICENSE"}],
"source": {"kind": "pin", "file": "tools/build-curl.sh", "var": "mbedtls_version", "url": "https://github.com/Mbed-TLS/mbedtls/releases/download/mbedtls-{rev}/mbedtls-{rev}.tar.bz2",
"extra": [{"tarball": ".deps/downloads/mbedtls-3.6.7.tar.bz2"}]},
"modifications": "Built as it is by tools/build-curl.sh."
},
{
"id": "freetype",
"name": "FreeType 2.13.3 (ES-DE's fonts)",
"kind": "code",
"artifacts": ["es-de/es-de.bin"],
"licence": "FTL OR GPL-2.0-or-later",
"copyright": ["Portions of this software are copyright (C) The FreeType Project (www.freetype.org)"],
"texts": [{"from": "build/freetype-ps5/src/LICENSE.TXT", "to": "LICENSE.TXT"}, {"from": "build/freetype-ps5/src/docs/FTL.TXT", "to": "FTL.TXT"}],
"source": {"kind": "pin", "file": "tools/build-freetype.sh", "var": "version", "url": "https://download.savannah.gnu.org/releases/freetype/freetype-{rev}.tar.xz",
"extra": [{"tarball": ".deps/downloads/freetype-2.13.3.tar.xz"}]},
"modifications": "Built as it is by tools/build-freetype.sh, under the FreeType License."
},
{
"id": "harfbuzz",
"name": "HarfBuzz 14.5.1 (ES-DE's text shaping)",
"kind": "code",
"artifacts": ["es-de/es-de.bin"],
"licence": "MIT-Modern-Variant",
"copyright": ["Copyright the HarfBuzz authors (see COPYING)"],
"texts": [{"from": "build/harfbuzz-ps5/src/COPYING", "to": "COPYING"}],
"source": {"kind": "pin", "file": "tools/build-harfbuzz.sh", "var": "version", "url": "https://github.com/harfbuzz/harfbuzz/releases/download/{rev}/harfbuzz-{rev}.tar.xz",
"extra": [{"tarball": ".deps/downloads/harfbuzz-14.5.1.tar.xz"}]},
"modifications": "Built as it is by tools/build-harfbuzz.sh."
},
{
"id": "icu",
"name": "ICU 78.3 (ES-DE's Unicode text handling)",
"kind": "code",
"artifacts": ["es-de/es-de.bin"],
"licence": "Unicode-3.0",
"copyright": ["Copyright © 2016-2025 Unicode, Inc.", "Copyright (c) 1995-2016 International Business Machines Corporation and others"],
"texts": [{"from": "build/icu-ps5/src/LICENSE", "to": "LICENSE"}],
"source": {"kind": "pin", "file": "tools/build-icu.sh", "var": "version", "url": "https://github.com/unicode-org/icu/releases/tag/release-{rev}",
"extra": [{"tarball": ".deps/downloads/icu4c-78.3-sources.tgz"}, {"tarball": ".deps/downloads/icu4c-78.3-data.zip"}]},
"modifications": "Built by tools/build-icu.sh with its data linked in."
},
{
"id": "pugixml",
"name": "pugixml 1.16 (ES-DE's XML; the port's game lists)",
"kind": "code",
"artifacts": ["es-de/es-de.bin"],
"licence": "MIT",
"copyright": ["Copyright (c) 2006-2026 Arseny Kapoulkine"],
"texts": [{"from": "build/pugixml-ps5/src/LICENSE.md", "to": "LICENSE.md"}],
"source": {"kind": "pin", "file": "tools/build-pugixml.sh", "var": "version", "url": "https://github.com/zeux/pugixml/releases/tag/v{rev}",
"extra": [{"tarball": ".deps/downloads/pugixml-1.16.tar.gz"}]},
"modifications": "Built as it is by tools/build-pugixml.sh."
},
{
"id": "libwebp",
"name": "libwebp 1.6.0 (the WebP pictures ES-DE's themes use)",
"kind": "code",
"artifacts": ["es-de/es-de.bin"],
"licence": "BSD-3-Clause",
"copyright": ["Copyright (c) 2010, Google Inc."],
"texts": [{"from": "build/libwebp-ps5/src/COPYING", "to": "COPYING"}, {"from": "build/libwebp-ps5/src/PATENTS", "to": "PATENTS"}],
"source": {"kind": "pin", "file": "tools/build-libwebp.sh", "var": "version", "url": "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-{rev}.tar.gz",
"extra": [{"tarball": ".deps/downloads/libwebp-1.6.0.tar.gz"}]},
"modifications": "Its decoder only, built by tools/build-libwebp.sh."
},
{
"id": "stb",
"name": "stb_image and stb_image_write (ES-DE's pictures, in place of FreeImage)",
"kind": "code",
"artifacts": ["es-de/es-de.bin"],
"licence": "MIT OR Unlicense",
"copyright": ["Copyright (c) 2017 Sean Barrett"],
"texts": [{"from": ".deps/stb-2c980bb59875b0d32144a71867fbdebb2f77cd20/LICENSE", "to": "LICENSE"}],
"source": {"kind": "pin", "file": "tools/build-esde.sh", "var": "stb_commit", "url": "https://github.com/nothings/stb/tree/{rev}"},
"modifications": "Used as it is by frontends/es-de/ps5/freeimage_stb.cpp."
},
{
"id": "frontend-picker",
"name": "The frontend picker: a program of PS5_VulkanTemplate's UI module (BlackBearReloaded's kit via PS5_VKHomebrewUI), with RADV",
"kind": "code",
"artifacts": ["picker/**"],
"licence": "GPL-3.0-or-later AND MIT AND others (picker-licenses/ lists each part, as the template staged them)",
"copyright": ["Copyright (C) 2026 Mihawk", "Copyright (C) 2026 BlackBearReloaded (the UI kit)", "Copyright (C) 2016-2026 Sascha Willems (the example base)"],
"texts": [{"from": "build/picker/title/dist/PPSA99168/licenses", "to": "picker-licenses"}, {"from": "build/picker/title/dist/PPSA99168/LEGAL.txt", "to": "LEGAL.txt"}, {"from": "assets/picker/NOTICE.md", "to": "previews-NOTICE.md"}],
"source": {"kind": "pin", "file": "tools/build-picker.sh", "var": "template_commit", "url": "https://github.com/mihawk-99/PS5_VulkanTemplate/tree/{rev}",
"extra": [{"name": "PS5_VulkanTemplate", "git": "../PS5_VulkanTemplate", "pin": {"file": "tools/build-picker.sh", "var": "template_commit"}, "remote": "https://github.com/mihawk-99/PS5_VulkanTemplate"},
{"name": "PS5_VKHomebrewUI", "git": "../PS5_VKHomebrewUI", "pin": {"file": "../PS5_VulkanTemplate/ps5/ui/setup-kit.sh", "var": "revision"}, "remote": "https://github.com/mihawk-99/PS5_VKHomebrewUI"},
{"name": "PS5_PayloadSDK", "git": "../PS5_PayloadSDK", "pin": {"file": "../PS5_VulkanTemplate/ps5/tools/setup-sdk.sh", "var": "sdk_revision"}, "remote": "https://github.com/mihawk-99/PS5_PayloadSDK"}]},
"modifications": "frontends/picker/picker.cpp (PS5_RetroArch), built as the one program of a title the template generates (tools/build-picker.sh)."
}
]
}
+9 -3
View File
@@ -428,9 +428,15 @@ PY_WEBUI
# Pinned production effects, with dependency and development-fixture checks.
python3 "$root/tools/video-assets.py" stage "$dist"
# Frontend executables beside eboot.bin (frontends/, tools/build-frontend.sh), only
# those PS5_FRONTENDS names: they need ../PS5_OpenGL's SDK and its SDL2 build, and a
# default title carries none yet. Built before the manifest so it covers them.
# Frontend executables beside eboot.bin (frontends/, tools/build-frontend.sh), those
# PS5_FRONTENDS names: they need ../PS5_OpenGL's SDK and its SDL2 build, and
# ../PS5_VulkanTemplate for the picker. A development build carries none unless asked;
# a release carries both (their notices and sources are listed with the rest:
# tooling/notices/components.json, docs/RELEASING.md), unless PS5_FRONTENDS is set,
# empty included. Built before the manifest so it covers them.
if [[ -n ${PS5_RELEASE_TAG:-} && -z ${PS5_FRONTENDS+set} ]]; then
PS5_FRONTENDS="es-de picker"
fi
if [[ -n ${PS5_FRONTENDS:-} ]]; then
read -r -a frontends <<< "$PS5_FRONTENDS"
for frontend in "${frontends[@]}"; do
+5 -3
View File
@@ -6,7 +6,8 @@
python3 tools/check-notices.py [dist/PPSA99169] [--release]
What it establishes, and nothing more:
- every executable file (eboot.bin, *.prx, *.so) and every core .info file belongs
- every executable file (eboot.bin, the frontends' es-de/es-de.bin and
picker/picker.bin, *.prx, *.so) and every core .info file belongs
to at least one listed part, and the sha256 recorded for it is the file's own;
- every listed licence text is present and not empty, and a text marked verbatim
(FBNeo's, Snes9x's, Genesis Plus GX's) is byte for byte the one staged;
@@ -24,8 +25,9 @@ import json
import sys
from pathlib import Path
COVERED = ("eboot.bin", "sce_module/*.prx", "cores/*.so", "cores/*.info", "info/*.info")
EXECUTABLE = ("eboot.bin", "*.prx", "*.so")
COVERED = ("eboot.bin", "es-de/*.bin", "picker/*.bin", "sce_module/*.prx", "cores/*.so", "cores/*.info",
"info/*.info")
EXECUTABLE = ("eboot.bin", "es-de.bin", "picker.bin", "*.prx", "*.so")
def sha256(path):
+5 -3
View File
@@ -137,14 +137,16 @@ def plan(component, root):
if sha256(tarball) != revision:
raise BundleError("libmicrohttpd: source archive differs from the build pin")
steps.append((tarball.name, ("copy", tarball), source.get("url", "")))
else:
return [] # a part with no source to archive here (see SOURCES.txt)
# Otherwise no archive of its own (see SOURCES.txt); its extra sources, if any,
# are what the build used: the frontends' libraries' tarballs and trees.
for extra in spec.get("extra", []):
if "tarball" in extra:
tarball = root / extra["tarball"]
if not tarball.is_file():
raise BundleError(f"{cid}: {extra['tarball']} is not there")
steps.append((tarball.name, ("copy", tarball), f"used by {cid}"))
else:
rev = pinned(extra["pin"], root)
rev = extra["revision"] if "revision" in extra else pinned(extra["pin"], root)
steps.append((f"{extra['name']}-{rev[:12]}.tar.gz",
("git", root / extra["git"], rev, tuple(extra.get("paths", ()))),
f"{extra.get('remote', '')}/tree/{rev} (used by {cid})"))
+2 -1
View File
@@ -33,7 +33,8 @@ from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
TABLE = ROOT / "tooling/notices/components.json"
EXECUTABLE = ("eboot.bin", "*.prx", "*.so")
# The title's executables: eboot.bin, the frontends beside it, modules and cores.
EXECUTABLE = ("eboot.bin", "es-de.bin", "picker.bin", "*.prx", "*.so")
class NoticeError(Exception):