Files
Tushar Rohilla e5295f36aa Add Afterglow 1.0.6, a PS5 internet radio and music visualizer
222 stations in 17 genres, 56 visualizer scenes, Ogg and Opus playback, station logos, crossfade, My Music from USB, a command box and live BPM sync.
2026-10-16 00:59:10 -04:00

6.3 KiB
Raw Permalink Blame History

Native build tooling

The normal build has no C# or .NET dependency. Repository-owned host tools are C++20 and compile natively on Linux/WSL or through WSL from PowerShell.

Division of responsibility

LLVM/Clang and lld handle the standard work that mature native tools already solve: C/C++ compilation, archives, COMDAT, symbol resolution, TLS, unwind records, and x86-64 relocations. The repository-owned converter handles only PS5-specific output requirements:

  • FreeBSD OS ABI 9, ABI version 2, and executable type 0xFE10;
  • execute-only, read-only, RELRO, writable, and flags-zero linking segments;
  • process-parameter and parameter-block records;
  • SDK import discovery from the installed public .so stubs;
  • PS5 NIDs, module/library IDs, SysV hash, and dynamic tags;
  • development FSELF wrapping and integrity metadata.

The converter reads imports directly from the PIE and the SDK stubs. It does not contain a copied import catalog or firmware offsets.

Native third-party libraries are allowed when they solve a standard problem and the build can acquire and link them reproducibly. zlib is used directly by the FSELF tool; LLVM/lld handles standard object linking. This boundary keeps the repository free of managed build tooling without reimplementing mature native libraries such as zlib or OpenSSL. zlib 1.3.2 is downloaded from its fixed upstream archive, SHA-256 verified, and compiled into .deps/native/; the build no longer depends on a changing distribution package.

Files

File Purpose
tooling/native/app_crt.cpp Native C++ process startup and constructor handling
tooling/native/app_cpp_runtime.cpp Minimal new/delete bridge to malloc, free, and posix_memalign
tooling/native/app-symbols.map Keeps replacement allocation operators internal to the application
tooling/native/ps5-pie.ld Non-overlapping intermediate PIE layout
tooling/native/elf_object.* ELF and SDK-stub reader
tooling/native/sce_module_writer.* PS5 executable converter
tooling/native/self_container.* FSELF reader, writer, and verifier
tooling/native/libc_builder.cpp Deterministic clean-room runtime emitter
tooling/native/hash.hpp Project-owned SHA-1/SHA-256 implementation

Build the host utility manually

The normal build invokes the dependency bootstrap automatically. For a manual PowerShell build, use the returned WSL paths rather than a global library:

$deps = ./tools/setup-native-dependencies.ps1 | ConvertFrom-Json
wsl.exe --exec clang++ -std=c++20 -O2 -Wall -Wextra -Werror `
  -I $deps.zlibInclude `
  tooling/native/native_app_builder.cpp `
  tooling/native/self_container.cpp `
  tooling/native/elf_object.cpp `
  tooling/native/sce_module_writer.cpp `
  $deps.zlibArchive -o build/ps5-native-tool

zlib is the only directly linked host library.

Target C++ profile

Application .cpp files compile as C++20 with exceptions and RTTI disabled. The public SDK's libc++ headers provide zero-cost vocabulary types and std::unique_ptr; the build does not link the full libc++, libc++abi, or unwind archives. Repository-owned replacement allocation operators forward to the clean-room runtime and are localized before PS5 conversion, so they do not become loader-visible application exports.

Throwing new deliberately traps on allocation failure. Nothrow allocation returns nullptr. Prefer value semantics and allocation-free RAII in steady state, and do not introduce std::shared_ptr, streams, locale, filesystem, exceptions, or RTTI without a separate runtime and firmware validation.

Source quality

The repository uses the same focused Clang policy as the CPython PS5 project: make format-check enforces .clang-format, while make tidy runs the Clang core and security analyzers configured by .clang-tidy. make lint runs both plus attribution, JSON, shell-syntax, local-path, and whitespace checks.

Commands

ps5-native-tool link --in <llvm-pie> --out <ps5-elf> --stub-dir <sdk-lib>
ps5-native-tool self --sign --in <ps5-elf> --out <fself>
ps5-native-tool self --extract --file <fself> --out <ps5-elf>
ps5-native-tool self --inspect --file <module>

link expects the repository linker script’s page-separated PIE. The normal build invokes it correctly; the command is documented for debugging and CI.

RELRO and 16 KiB PT_LOAD congruence

Every mapped load segment must satisfy p_offset % 0x4000 == p_vaddr % 0x4000. The RELRO segment begins at .data.rel.ro; .got is contained inside that region and must not be used as its file origin. Using the GOT offset can appear to work for a small program, then produce a loader rejection after adding imports or static data because the section layout changes.

The converter anchors RELRO to its first section, which is .data.rel.ro whenever lld keeps that section and otherwise the GOT or an initializer array (a program without relocated read-only data has no .data.rel.ro at all), and fails the host build if any mapped PT_LOAD violates the 16 KiB congruence rule. This validation belongs in the writer rather than in application code because the failure occurs before main() and is independent of the imported API's runtime behavior.

Current hardware-validation baseline

A clean build of the current C++20 graphical Hello World was deployed with make deploy, launched, observed, and closed on firmware 6.02 and 12.70. The exact tested artifacts are:

Raw ELF SHA-256:  6198c82adf9d59f2ae14de4e1410e2482376afc9f9ee148f3d8cf406a952c0ff
FSELF SHA-256:    d791f65c5a62aec4d70c4e9c6b8b0baeeefbf51a41dd774287e1353f66af2966
Runtime SHA-256:  e6ff45d16adf687855cc3b33b0c8a4132b6504360b221e0a34c7e99fb3ba0036

On 6.02 the captured display showed the complete CPU VideoOut scene and the packaged /app0/assets/banner.txt content. On both consoles klog recorded native eboot execution without a loader, fatal-signal, or crash marker. The 12.70 run also recorded transition into AppScreen. Title-aware closure was confirmed by ShadowMount/KStuff, and FTP, klog, and elfldr remained reachable after both runs.

The loader-visible comment record and the unmapped trailing note intentionally have zero memory size. Firmware 6.02 rejects those records before entry when their file size is incorrectly copied into p_memsz; the static validator enforces the tested convention.