diff --git a/README.md b/README.md index 66e53e9..4998f35 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# PS4RP — Discord Rich Presence for the PS4 +# orbisRPC — Discord Rich Presence for the PS4 A background daemon that runs **entirely on your jailbroken PS4** and posts what you're playing to your Discord profile as Rich Presence — "Playing *Call of Duty: Black @@ -14,17 +14,17 @@ It's Discord's "now-playing" integration, the way the PS5 does it — but for a The PS4 only runs one foreground app at a time, so a normal homebrew app gets suspended the moment you launch a game and can't report your activity while you -play. PS4RP avoids that by running as a **GoldHEN payload daemon**: it loads at +play. orbisRPC avoids that by running as a **GoldHEN payload daemon**: it loads at boot (from `GoldHEN/payloads/`) and keeps running in the background while games launch in the foreground. ``` +--------------------------+ HTTPS/WebSocket +-------------------+ - | PS4RP (payload daemon) | wss://gateway.discord.gg | Discord | + | orbisRPC (payload daemon) | wss://gateway.discord.gg | Discord | | on your PS4 @ 192.168.1.136 | <-- presence --> | (your profile) | +-------------+--------------+ +-----------------+ | - detects running game (process list + app.db) | config + token (/data/PS4RP) + detects running game (process list + app.db) | config + token (/data/orbisRPC) v +--------------------------+ | /user/app/CUSAxxxx | @@ -54,7 +54,7 @@ Everything stays on the PS4. Your Mac only touches this repo to *build* it. | M5 — GoldHEN autoload + package + install | pending (needs on-console test) | | On-console validation (M1's TLS + detection against live FW) | pending | -`build/ps4rp.elf` (169 KB) and `build/ps4rp.fself` (175 KB) link successfully +`build/orbisrpc.elf` (169 KB) and `build/orbisrpc.fself` (175 KB) link successfully against OpenOrbis v0.5.4; the TLS layer uses `libSceLibreSSL`'s OpenSSL-ABI exports (`SSL_CTX_new` / `SSL_connect` / `SSL_write` / `SSL_read`). @@ -79,27 +79,27 @@ brew install llvm # clang 21 OO_PS4_TOOLCHAIN=~/PS4Toolchain/OpenOrbis/PS4Toolchain \ LLD=/Users/mac/lldbuild/build/bin/ld.lld \ ./scripts/build.sh -# -> build/ps4rp.elf, build/ps4rp.fself, build/eboot.bin +# -> build/orbisrpc.elf, build/orbisrpc.fself, build/eboot.bin ``` -The runtime artifact is `build/ps4rp.fself` (GoldHEN payload) or +The runtime artifact is `build/orbisrpc.fself` (GoldHEN payload) or `build/eboot.bin` (PKG route). No toolchain = no build. --- ## Installing on the PS4 (no PC after first build) -1. Build `ps4rp.pkg` (or grab the `.elf` payload) on any Mac/computer. +1. Build `orbisrpc.pkg` (or grab the `.elf` payload) on any Mac/computer. 2. Transfer to the PS4 over FTP, or on a USB stick. -3. **Daemon route (recommended):** put `ps4rp.fself` in +3. **Daemon route (recommended):** put `orbisrpc.fself` in `/data/GoldHEN/payloads/` — it auto-loads on every boot and runs in the background while you game. (GoldHEN 2.2.) -4. Or install `ps4rp.pkg` like any homebrew app if you prefer a foreground +4. Or install `orbisrpc.pkg` like any homebrew app if you prefer a foreground launcher (note: it suspends once a game opens, so the daemon route is what powers presence-during-play). -Config lives at `/data/PS4RP/config.json` — edit it over FTP or on a USB stick. -Logs go to `/data/PS4RP/log.txt`. +Config lives at `/data/orbisRPC/config.json` — edit it over FTP or on a USB stick. +Logs go to `/data/orbisRPC/log.txt`. --- @@ -111,9 +111,9 @@ account automating itself (which Discord bans on the user account — see notes repo). Steps: 1. Open https://discord.com/developers/applications → **New Application** → name it - `PS4RP` (or whatever) → **Create**. + `orbisRPC` (or whatever) → **Create**. 2. Copy the **Application ID** (Client ID) and **Client Secret** into - `/data/PS4RP/config.json` (`client_id`, `client_secret`). + `/data/orbisRPC/config.json` (`client_id`, `client_secret`). 3. In the app → **OAuth2 → Redirects**, add: `https://example.com/callback` 4. In the app → **OAuth2 → Scopes**, add `rpc.activities.write` (and `identify`). @@ -133,7 +133,7 @@ After that it just runs. No PC needed at runtime. A registered application acting on your permission is the supported integration path. - Discord may require your application to be verified to use `rpc.activities.write`. For a personal, low-traffic app it usually works unverified; worst case it labels - the activity "via PS4RP". + the activity "via orbisRPC". --- diff --git a/deploy/SETUP.md b/deploy/SETUP.md index 1083dce..bf77115 100644 --- a/deploy/SETUP.md +++ b/deploy/SETUP.md @@ -1,4 +1,4 @@ -# PS4RP — Deploy + setup guide +# orbisRPC — Deploy + setup guide Target: GoldHEN 2.2 jailbroken PS4 (FW 9.00), daemon route. @@ -7,7 +7,7 @@ Target: GoldHEN 2.2 jailbroken PS4 (FW 9.00), daemon route. Via FTP (the console must be awake and online): ``` -put build/ps4rp.fself -> /data/GoldHEN/payloads/ps4rp.fself +put build/orbisrpc.fself -> /data/GoldHEN/payloads/orbisrpc.fself ``` GoldHEN auto-loads payloads from `/data/GoldHEN/payloads/` at boot and keeps @@ -16,8 +16,8 @@ them running in the background while games run in the foreground. Also make the config dir + seed the config: ``` -mkdir /data/PS4RP -put config/config.json -> /data/PS4RP/config.json +mkdir /data/orbisRPC +put config/config.json -> /data/orbisRPC/config.json ``` ## 2. First boot check @@ -25,14 +25,14 @@ put config/config.json -> /data/PS4RP/config.json Reboot (or run the payload from the GoldHEN loader) and check: ``` -get /data/PS4RP/log.txt +get /data/orbisRPC/log.txt ``` Expected lines: ``` -[..] config not found at /data/PS4RP/config.json; defaults applied (only first run) -[..] FATAL: set client_id + auth_code (or refresh) in /data/PS4RP/config.json +[..] config not found at /data/orbisRPC/config.json; defaults applied (only first run) +[..] FATAL: set client_id + auth_code (or refresh) in /data/orbisRPC/config.json ``` The FATAL exit is expected until you supply Discord credentials (step 3). @@ -40,13 +40,13 @@ The FATAL exit is expected until you supply Discord credentials (step 3). ## 3. One-time Discord app setup 1. Open https://discord.com/developers/applications -> New Application -> name it - (e.g. `PS4RP`) -> Create. + (e.g. `orbisRPC`) -> Create. 2. Copy **Application ID** and **Client Secret**. 3. In the app -> **OAuth2 -> General**, add a Redirect URL: `http://localhost:6770/callback` 4. In the app -> **OAuth2 -> Scopes**, enable `rpc.activities.write` and `identify` (and `rpc` if prompted). -5. Edit `/data/PS4RP/config.json` over FTP/USB: +5. Edit `/data/orbisRPC/config.json` over FTP/USB: - `client_id`: your Application ID - `client_secret`: your Client Secret 6. Generate an authorization code on any device (phone/PC — one time only): @@ -89,7 +89,7 @@ The daemon exchanges the `auth_code` once for an access + refresh token (`token_expires_at`, `refresh_token` in config). It refreshes automatically before expiry. The one-time `auth_code` is blanked after use. -Config lives on the PS4 at `/data/PS4RP/config.json` — no PC needed at runtime. +Config lives on the PS4 at `/data/orbisRPC/config.json` — no PC needed at runtime. ## Troubleshooting @@ -108,5 +108,5 @@ Config lives on the PS4 at `/data/PS4RP/config.json` — no PC needed at runtime OO_PS4_TOOLCHAIN=~/PS4Toolchain/OpenOrbis/PS4Toolchain \ LLD=/Users/mac/lldbuild/build/bin/ld.lld \ ./scripts/build.sh -# -> build/ps4rp.fself +# -> build/orbisrpc.fself ``` diff --git a/PS4RP/b64.c b/orbisrpc/b64.c similarity index 100% rename from PS4RP/b64.c rename to orbisrpc/b64.c diff --git a/PS4RP/b64.h b/orbisrpc/b64.h similarity index 100% rename from PS4RP/b64.h rename to orbisrpc/b64.h diff --git a/PS4RP/cfg.c b/orbisrpc/cfg.c similarity index 100% rename from PS4RP/cfg.c rename to orbisrpc/cfg.c diff --git a/PS4RP/cfg.h b/orbisrpc/cfg.h similarity index 81% rename from PS4RP/cfg.h rename to orbisrpc/cfg.h index a1f966f..93eab88 100644 --- a/PS4RP/cfg.h +++ b/orbisrpc/cfg.h @@ -1,10 +1,10 @@ -/* cfg.h - /data/PS4RP/config.json load/save */ +/* cfg.h - /data/orbisRPC/config.json load/save */ #ifndef CFG_H #define CFG_H #include -#define CFG_PATH "/data/PS4RP/config.json" -#define LOG_PATH "/data/PS4RP/log.txt" -#define DATA_DIR "/data/PS4RP" +#define CFG_PATH "/data/orbisRPC/config.json" +#define LOG_PATH "/data/orbisRPC/log.txt" +#define DATA_DIR "/data/orbisRPC" typedef struct { char client_id[64]; /* Discord application client id */ char client_secret[128]; /* only needed to exchange code / refresh */ diff --git a/PS4RP/detect.c b/orbisrpc/detect.c similarity index 98% rename from PS4RP/detect.c rename to orbisrpc/detect.c index 417388f..ed32c43 100644 --- a/PS4RP/detect.c +++ b/orbisrpc/detect.c @@ -151,7 +151,7 @@ int detect_current_game(char *out_name, size_t cap, char *out_path, size_t p_cap }else{ strncpy(out_name, "(unknown game)", cap-1); out_name[cap-1]=0; } - if(out_path){ snprintf(out_path, p_cap, "/data/PS4RP/.lastgame/%s", titleId[0]?titleId:"unknown"); } + if(out_path){ snprintf(out_path, p_cap, "/data/orbisRPC/.lastgame/%s", titleId[0]?titleId:"unknown"); } log_msg("detect: active name=%s tid=%s", out_name, titleId); return 0; } \ No newline at end of file diff --git a/PS4RP/detect.h b/orbisrpc/detect.h similarity index 100% rename from PS4RP/detect.h rename to orbisrpc/detect.h diff --git a/PS4RP/discord.c b/orbisrpc/discord.c similarity index 100% rename from PS4RP/discord.c rename to orbisrpc/discord.c diff --git a/PS4RP/discord.h b/orbisrpc/discord.h similarity index 100% rename from PS4RP/discord.h rename to orbisrpc/discord.h diff --git a/PS4RP/http.c b/orbisrpc/http.c similarity index 91% rename from PS4RP/http.c rename to orbisrpc/http.c index bd5ada8..9544da9 100644 --- a/PS4RP/http.c +++ b/orbisrpc/http.c @@ -28,7 +28,7 @@ static int http_init(void){ if((r=sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_HTTP))<0){log_msg("load HTTP fail %d",r);return -2;} if((r=sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_SSL))<0){log_msg("load SSL fail %d",r);return -3;} if((r=sceNetInit())<0){log_msg("sceNetInit %d",r);return -4;} - s_http_mem=(int)sceNetPoolCreate("ps4rpN",NET_POOL,0); if(s_http_mem<0){log_msg("netpool %d",s_http_mem);return -5;} + s_http_mem=(int)sceNetPoolCreate("orbisrpcN",NET_POOL,0); if(s_http_mem<0){log_msg("netpool %d",s_http_mem);return -5;} s_ssl_mem=(int)sceSslInit(SSL_PL); if(s_ssl_mem<0){log_msg("sslinit %d",s_ssl_mem);return -6;} if((r=sceHttpInit(s_http_mem,s_ssl_mem,HTTP_PL))<0){log_msg("httpinit %d",r);return -7;} s_http_ctx=r; @@ -70,11 +70,11 @@ int http_oauth_token(const char *client_id,const char *client_secret, "&grant_type=refresh_token&refresh_token=%s", refresh_token); else blen+=snprintf(body+blen,sizeof body-blen,"&grant_type=client_credentials&scope=applications.commands"); const char *URL="https://discord.com/api/oauth2/token"; - tpl=sceHttpCreateTemplate(s_http_ctx, "PS4RP/1.0", ORBIS_HTTP_VERSION_1_1, 0); if(tpl<0){log_msg("tmpl %d",tpl);rc=-1;goto done;} + tpl=sceHttpCreateTemplate(s_http_ctx, "orbisRPC/1.0", ORBIS_HTTP_VERSION_1_1, 0); if(tpl<0){log_msg("tmpl %d",tpl);rc=-1;goto done;} conn=sceHttpCreateConnectionWithURL(tpl, URL, 0); if(conn<0){log_msg("conn %d",conn);rc=-2;goto done;} req=sceHttpCreateRequestWithURL(conn, ORBIS_METHOD_POST, URL, (uint64_t)blen); if(req<0){log_msg("req %d",req);rc=-3;goto done;} sceHttpAddRequestHeader(req,"Content-Type","application/x-www-form-urlencoded",0); - sceHttpAddRequestHeader(req,"User-Agent","PS4RP/1.0",0); + sceHttpAddRequestHeader(req,"User-Agent","orbisRPC/1.0",0); if((rc=sceHttpSendRequest(req,body,blen))<0){log_msg("send %d",rc);rc=-4;goto done;} if((rc=sceHttpGetStatusCode(req,&status))<0){log_msg("stat %d",rc);rc=-5;goto done;} char resp[2048]; int total=0,len; @@ -96,10 +96,10 @@ done: int http_get(const char *url,char *out,size_t cap){ if(http_init()) return -10; int32_t tpl=0,conn=0,req=0,rc=0; - tpl=sceHttpCreateTemplate(s_http_ctx,"PS4RP/1.0",ORBIS_HTTP_VERSION_1_1,0); if(tpl<0)return -1; + tpl=sceHttpCreateTemplate(s_http_ctx,"orbisRPC/1.0",ORBIS_HTTP_VERSION_1_1,0); if(tpl<0)return -1; conn=sceHttpCreateConnectionWithURL(tpl,url,0); if(conn<0){rc=-2;goto done;} req=sceHttpCreateRequestWithURL(conn,ORBIS_METHOD_GET,url,0); if(req<0){rc=-3;goto done;} - sceHttpAddRequestHeader(req,"User-Agent","PS4RP/1.0",0); + sceHttpAddRequestHeader(req,"User-Agent","orbisRPC/1.0",0); if((rc=sceHttpSendRequest(req,0,0))<0){rc=-4;goto done;} int total=0,len; while((len=sceHttpReadData(req,out+total,cap-1-total))>0){total+=len; if(total>(int)cap-1)break;} diff --git a/PS4RP/http.h b/orbisrpc/http.h similarity index 100% rename from PS4RP/http.h rename to orbisrpc/http.h diff --git a/PS4RP/jsonlite.c b/orbisrpc/jsonlite.c similarity index 100% rename from PS4RP/jsonlite.c rename to orbisrpc/jsonlite.c diff --git a/PS4RP/jsonlite.h b/orbisrpc/jsonlite.h similarity index 100% rename from PS4RP/jsonlite.h rename to orbisrpc/jsonlite.h diff --git a/PS4RP/log.c b/orbisrpc/log.c similarity index 100% rename from PS4RP/log.c rename to orbisrpc/log.c diff --git a/PS4RP/log.h b/orbisrpc/log.h similarity index 100% rename from PS4RP/log.h rename to orbisrpc/log.h diff --git a/PS4RP/main.c b/orbisrpc/main.c similarity index 94% rename from PS4RP/main.c rename to orbisrpc/main.c index 61c4f64..11cb284 100644 --- a/PS4RP/main.c +++ b/orbisrpc/main.c @@ -1,4 +1,4 @@ -/* main.c - PS4RP daemon: detect game -> Discord presence. Runs as GoldHEN payload. */ +/* main.c - orbisRPC daemon: detect game -> Discord presence. Runs as GoldHEN payload. */ #include "cfg.h" #include "log.h" #include "http.h" @@ -44,14 +44,14 @@ static void set_game_presence(discord_t *d, const char *name){ "On PS4", /* state */ name, /* details = game name */ 1, 1, /* party */ - "ps4rp:playing", /* large_image key (asset) */ + "orbisrpc:playing", /* large_image key (asset) */ name); /* large_text */ log_msg("presence: %s", name); } int main(int argc, char **argv){ (void)argc;(void)argv; - /* GoldHEN payloads: write to /data/PS4RP */ + /* GoldHEN payloads: write to /data/orbisRPC */ cfg_load(CFG_PATH, &g_cfg); if(!g_cfg.enabled){ log_msg("disabled in config; exiting"); return 0; } if(!g_cfg.client_id[0] || strcmp(g_cfg.client_id,"SET_ME")==0){ diff --git a/PS4RP/ws.c b/orbisrpc/ws.c similarity index 97% rename from PS4RP/ws.c rename to orbisrpc/ws.c index a6cffd9..dda1d3a 100644 --- a/PS4RP/ws.c +++ b/orbisrpc/ws.c @@ -58,7 +58,7 @@ static int net_ensure(void){ uint32_t ur = sceSysmoduleLoadModuleInternal(ORBIS_SYSMODULE_INTERNAL_NET); if((int)ur < 0){ log_msg("load NET fail %d", (int)ur); return -1; } if(sceNetInit() < 0){ log_msg("sceNetInit fail"); return -2; } - s_net_mem = (int)sceNetPoolCreate("ps4rpNet", 128*1024, 0); + s_net_mem = (int)sceNetPoolCreate("orbisrpcNet", 128*1024, 0); if(s_net_mem < 0){ log_msg("net pool fail %d", s_net_mem); return -3; } s_net_ready = 1; return 0; @@ -68,7 +68,7 @@ int ws_connect(ws_t *w, const char *host, int port, const char *resource, const memset(w,0,sizeof(*w)); if(net_ensure()<0) return -1; /* resolve host */ - int32_t rid = sceNetResolverCreate("ps4rpR", 0, 0); + int32_t rid = sceNetResolverCreate("orbisrpcR", 0, 0); OrbisNetInAddr in; memset(&in,0,sizeof in); int resolved = 0; if(rid >= 0){ @@ -82,7 +82,7 @@ int ws_connect(ws_t *w, const char *host, int port, const char *resource, const in.s_addr = ia.s_addr; } /* TCP socket */ - int32_t fd = sceNetSocket("ps4rpWs", ORBIS_NET_AF_INET, ORBIS_NET_SOCK_STREAM, 0); + int32_t fd = sceNetSocket("orbisrpcWs", ORBIS_NET_AF_INET, ORBIS_NET_SOCK_STREAM, 0); if(fd < 0){ log_msg("socket fail %d",fd); return -5; } OrbisNetSockaddr sa; memset(&sa,0,sizeof sa); sa.len = (uint8_t)sizeof(sa); diff --git a/PS4RP/ws.h b/orbisrpc/ws.h similarity index 100% rename from PS4RP/ws.h rename to orbisrpc/ws.h diff --git a/scripts/build.sh b/scripts/build.sh index 4be34f9..83c64c5 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,5 +1,5 @@ #!/bin/bash -# build.sh - PS4RP: compile payload ELF + fself for PS4. +# build.sh - orbisRPC: compile payload ELF + fself for PS4. # Usage: ./scripts/build.sh [elf|fself|all] default: all set -euo pipefail SDK="${OO_PS4_TOOLCHAIN:-/Users/mac/PS4Toolchain/OpenOrbis/PS4Toolchain}" @@ -20,15 +20,15 @@ export OO_PS4_TOOLCHAIN="$SDK" OUT="$ROOT/build"; mkdir -p "$OUT" echo "=== compiling ===" for f in log cfg jsonlite b64 http ws detect discord main; do - "$CC" $CFLAGS -c -o "$OUT/$f.o" "PS4RP/$f.c" || { echo "compile $f FAILED"; exit 1; } + "$CC" $CFLAGS -c -o "$OUT/$f.o" "orbisrpc/$f.c" || { echo "compile $f FAILED"; exit 1; } done echo "=== linking ($LD) ===" -"$LD" $OUT/*.o -o "$OUT/ps4rp.elf" $LDFLAGS || { echo "link FAILED"; exit 1; } -echo "ELF -> $OUT/ps4rp.elf" +"$LD" $OUT/*.o -o "$OUT/orbisrpc.elf" $LDFLAGS || { echo "link FAILED"; exit 1; } +echo "ELF -> $OUT/orbisrpc.elf" MODE="${1:-all}" if [ "$MODE" = "fself" ] || [ "$MODE" = "all" ]; then - "$SDK/bin/macos/create-fself-macos" -in="$OUT/ps4rp.elf" \ - -out="$OUT/ps4rp.fself" --eboot "$OUT/ps4rp.bin" --paid 0x3800000000000011 - echo "FSELF -> $OUT/ps4rp.fself" + "$SDK/bin/macos/create-fself-macos" -in="$OUT/orbisrpc.elf" \ + -out="$OUT/orbisrpc.fself" --eboot "$OUT/orbisrpc.bin" --paid 0x3800000000000011 + echo "FSELF -> $OUT/orbisrpc.fself" fi echo "done." \ No newline at end of file