../PS5_Proton found that a title can have Sony's service start a fresh
executable as a child of its application (sceSystemServiceAddLocalProcess
with the libc-only preload mask, a socket at the child's descriptor 3,
sceSystemServiceKillLocalProcess). This probe asks what that is worth
here.
- frontends/child-probe: a frontend program (SDL2, PS5_OpenGL) that the
title hands over to with LoadExec, as it does ES-DE. It holds the
display while running a headless child, keeps a child alive across
its own LoadExec, then releases the display and starts a graphics
child. "nogpu" mode starts one without ever opening the display.
- frontends/child-probe-helper: the headless child, freestanding C with
only libkernel, reporting its PID and the memory it sees.
- tooling/native: --preload-prx-flags writes the preload mask into the
process parameters (0x50), as PS5_Proton's patch to the same tool
does. Without it the output is unchanged.
Result on the base PS5 (13.40): a headless child starts in 0.12 s and
closes cleanly (kill 0, gone from the list). It reads the same flexible
memory figure as the parent (one budget), and it does not survive the
parent's LoadExec. A graphics child fails before its code runs
(gbase_gvmsw_open 6978, PRX_PROCESS_STARTUP_FAILURE), whether or not
the parent ever opened the display, and Sony then kills the whole
application.
Evidence: evidence/child-processes/ (capture.json, expectation.json,
probe-run-1.jsonl, probe-run-2-nogpu.jsonl). Command:
PS5_FRONTENDS='es-de picker child-probe' tools/build-title.sh
tools/run-title.sh --no-build --relaunch-test=1 \
--relaunch-image=es-de/child-probe.bin --watch 120
Gates: tools/verify.sh PASS (format unit build integration evidence).
EmulationStation is to be its own executable in the title, drawing with
../PS5_OpenGL (mihawk-99's fork of blackbearreloaded/ps5-opengl), whose Mesa
cannot share an image with RADV's. tools/build-frontend.sh builds a program in
frontends/ the way PS5_OpenGL builds its SDL2 consumers: its runtime shims,
heap and linker script over this project's base layout and C runtime, SDL2
from its bridge (built against this project's payload SDK from
ps5-payload-dev/SDL 8c56053), its OpenGL SDK and AGC import stubs, and a
256 MiB libc heap (the native tool's link takes --libc-heap-size; eboot.bin
keeps the largest). The result is es-de/<program>.bin, built by
tools/build-title.sh before the manifest for each program PS5_FRONTENDS names
(none by default). frontends/common supplies __memset_chk, which this host's
clang 23 builtins (emutls) call.
tools/deploy-title.py verifies a signed executable other than eboot.bin by its
stored bytes, on a connection with ftpsrv's SELF transfer mode off; it used to
compare the decoded download and upload twice. tools/run-title.sh's
--relaunch-image uses a built image at that path rather than a copy.
frontends/sdl-probe opens an SDL window with an OpenGL 3.3 core context,
shows red, green and blue for two seconds each, reads the centre back, counts
controller events, records /app0/es-de/sdl-probe.json and restarts eboot.bin
with the argument it was given.
Verified:
TMPDIR=build/tmp bash tools/verify.sh -> PASS (format unit build
integration evidence), default title unchanged
PS5_FRONTENDS=sdl-probe tools/build-title.sh -> es-de/sdl-probe.bin
(23,401,527 bytes) in the manifest, check-manifest PASS, build c1383963
tools/run-title.sh --no-build --relaunch-test=1
--relaunch-image=es-de/sdl-probe.bin --watch 45 on the base PS5: kernel
log EXEC eboot.bin, es-de/sdl-probe.bin, eboot.bin; GL "4.6 (Core
Profile) Mesa 26.2.0" on "PS5 AGC", 1920x1080, 121/120/120 frames in two
seconds each with every centre pixel right, a joystick and a button
press; relaunch PASS; the owner saw red, green, blue, then RetroArch
deploy of the probe alone after the fix: one upload, verified as stored
Evidence: evidence/sdl-probe/ (python3 tools/evidence.py compare)
The frontend now builds into a signed title, and the PS5 driver is in
RetroArch's table in the image that ships, not only in the source.
bash tools/build-title.sh
-> 225 of 225 sources compiled, archived into build/ra/libretroarch.a
-> dist/PPSA99169/eboot.bin, 8,026,239 bytes
container: signed, plaintext; 12 segments; integrity: valid
digest 71c88975040535a02b462618dd394a7a378034272c9bffa43ce0ca4b717ab9b7
(identical across two consecutive builds)
readelf -r build/ra/obj/gfx_video_driver.c.o
-> .rela.data.video_drivers holds exactly two entries: video_ps5, video_null
nm build/llvm-pie.elf
-> video_ps5, video_null, rarch_main and a single main
bash tools/check-manifest.sh
-> 7 files match their digests, none extra, eboot.bin magic 4f153d1d, and it
fails as it should when one byte of the image is changed
tools/verify.sh
-> PASS (format unit build integration evidence)
Registration and entry point. The port's changes are applied by
tools/apply-port-patches.py to the configured copy under build/ra-conf and never
to vendor/retroarch; patches/series names both. RetroArch's own main is compiled
out with -DHAVE_MAIN, the flag its desktop build passes, so src/main.cpp supplies
the only one and calls rarch_main.
Five faults fixed on the way, each recorded in docs/PHASE_LOG.md: the build read
sources from vendor/ and headers from build/ra-conf, so the driver table in the
image had no ps5 entry; 36 hand-written -DHAVE_* flags included six features
configure had turned off; config.h alone is not enough because a source can test a
feature before it is reached (libchdr without zlib); five Linux-only subsystems
were in the object list and are now off at their own configure switches; and two
link-time stubs the pipeline refuses needed -DNDEBUG and -DZSTD_TRACE=0.
The abandoned route is removed: deploy.py, console-launch.sh, check-payload.sh,
scaffold-native.sh, build-native-app.sh, install-title.sh and deploy.sh. Every
tool named by another tool now exists - tools/fetch-retroarch.sh was named by
three tools and three documents and had never been committed, and it now pins
RetroArch at v1.22.2 (69a4f0e) and drops the history so upstream cannot be
committed into. The gate scripts that had never been written are written:
lint-shell, lint-format, check-manifest. The template's unit test, which built a
test for a file that does not exist here, is replaced by tests/test_frontend.py.
The title has not run yet. It is built, signed and manifested; the folder has to
reach /data/homebrew/PPSA99169, and writes from this machine do not take on that
console.
Sets up this project as the native pipeline's scaffolding plus RetroArch's
sources, so RetroArch is compiled for the title pipeline rather than converted
into it.
- tools/scaffold-native.sh builds the scaffold from
../ps5-native-app-boilerplate-main: tooling, runtime (digest verified),
Makefile and its tools, merged into this repository's tools/ rather than
replacing them. An earlier version replaced tools/ wholesale and deleted this
project's own scripts; the copy is now additive and the reason is in the file.
- tools/fetch-retroarch.sh clones the pinned upstream tag into vendor/ and
records the revision, so "built from RetroArch 1.22.2" is checkable.
- src/display.{hpp,cpp} owns the console's display: VideoOut, direct memory, two
registered buffers, present-and-wait. The sequence and its two load-bearing
details come from the sibling application that proved it on hardware.
- src/main.cpp draws a moving bar: the cheapest thing that proves build, title
format, launcher, VideoOut and the direct-memory path together.
- sce_sys/param.json is this project's identity, PPSA99169.
Evidence: src/display.cpp compiles through the pipeline's compiler
(tooling/prospero-clang18 with PS5_CLANG=/usr/bin/clang, -std=c++20), and a
RetroArch source file compiles the same way with its include paths.