mirror of
https://github.com/mihawk-99/PS5_RetroArch.git
synced 2026-10-18 23:09:29 -05:00
A home screen tile is a title of its own (PPSA99170 to PPSA99269) that starts one
game in RetroArch. Titles cannot launch titles (sceSystemServiceLaunchApp returns
0x8094000F from one, sceLncUtilLaunchApp is a null import), so the tile hands a
payload to the console's ELF loader on 127.0.0.1:9021 and exits:
- forwarder/tile.c: the tile's eboot.bin. Reads its title id from
/app0/sce_sys/param.json, stamps it into /app0/launch.elf's slot, sends it to
the loader, logs /app0/tile.log, and leaves through LoadExec("exit") (a return
from main ends in a SIGSYS error notice).
- forwarder/launch.c: the payload. Reads /data/homebrew/<tile>/forward.txt (one
argument a line: --rom, --core, --exit-after-game, src/frontend_mode_ps5.cpp),
waits for the tile to leave, and starts PPSA99169 with those arguments through
sceLncUtilLaunchApp (sceSystemServiceLaunchApp as the fallback).
- tools/build-forwarder.sh builds both; tools/build-title.sh puts them in
dist/PPSA99169/forwarder/ and counts them in the title's identity; the notices
cover both files.
Evidence:
- host: python3 -m unittest tests.test_forwarder (the tile stamps and sends the
payload byte for byte, refuses a lowercase id, a missing or a doubled slot; the
payload passes the five arguments, falls back to SystemService, and an
unstamped payload starts nothing) - OK.
- console (base PS5, 13.40, ShadowMountPlus 1.7-beta5fix1), the test tile
PPSA99170 registered through ShadowMountPlus's manual list:
tile.log "tile PPSA99170: launch payload 110832 bytes, 110832 sent to
127.0.0.1:9021 (errno 0)"; launch.log five arguments, sceLncUtilLaunchApp
00002018; RetroArch's trace "forwarder: /app0/content/nes/<game> with
/app0/cores/fceumm_libretro.so, closing after it"; the tile exited cleanly
(no error notice), back to the home screen after the game.
- gates: format, unit (206 tests), build (tile 11,123 B, payload 110,832 B),
integration (206 tests; a first run timed out starting two scraper test
servers under load, both passed alone and on the rerun), evidence - PASS.
39 lines
1.4 KiB
C
39 lines
1.4 KiB
C
/* PS5 RetroArch - what a Game Forwarder tile (forwarder/tile.c) and its launch payload
|
|
* (forwarder/launch.c) share.
|
|
*
|
|
* Copyright (C) 2026 Mihawk
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*
|
|
* A tile tells the payload which tile it is by writing its title id over
|
|
* FORWARDER_SLOT_MARKER in the payload's bytes before it sends them; the payload then reads
|
|
* that tile's forward.txt. No file is written for the hand-over, so two tiles cannot race.
|
|
*/
|
|
#ifndef PS5_RETROARCH_FORWARDER_H
|
|
#define PS5_RETROARCH_FORWARDER_H
|
|
|
|
#include <stddef.h>
|
|
|
|
/* The payload's slot holds this until a tile writes its title id over it. */
|
|
#define FORWARDER_SLOT_MARKER "PS5RA-FORWARDER-TILE-ID-SLOT"
|
|
#define FORWARDER_SLOT_SIZE 32
|
|
/* A title id and its NUL: four capitals and five digits (PPSA99170). */
|
|
#define FORWARDER_ID_SIZE 10
|
|
/* The arguments a tile's forward.txt may hold, one a line, and the longest line. */
|
|
#define FORWARDER_MAX_ARGUMENTS 16
|
|
#define FORWARDER_MAX_ARGUMENT 512
|
|
|
|
static inline int forwarder_valid_id(const char *id, size_t length)
|
|
{
|
|
if (!id || length != 9)
|
|
return 0;
|
|
for (size_t i = 0; i < 9; i++)
|
|
if (i < 4 ? !(id[i] >= 'A' && id[i] <= 'Z') : !(id[i] >= '0' && id[i] <= '9'))
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
int forwarder_title_id(const char *param, char id[FORWARDER_ID_SIZE]);
|
|
int forwarder_stamp(char *payload, long size, const char *id);
|
|
|
|
#endif
|