- Delete stale HANDOFF.md (superseded by PRODUCTION + README + CI) - Move findings/ into docs/research/ (incl retired-tables); fix all cross-links (DAEMON, injecting, README, fw.h, PROGRESS_LOG) - New docs/README.md index; new BUILDING.md (toolchain, SDK rule, scripts, CI jobs, tests); new CONFIG.md (full key reference, verified against cfg_defaults) - Rewrite TROUBLESHOOTING.md from tester history (first-run flow, nanoDNS 127.0.0.1 step, connection checklist, known issues) - INSTALLER.md: PKG not shipped with test builds; PRODUCTION.md: drop dead-webhook line, fix readiness note
17 KiB
OrbisRPC Migration Progress Log
Started: 2026-09-29
Repo: C:\Users\user\Documents\GitHub\orbisRPC
SDK Reference: ps4-payload-sdk-reference (local checkout, not committed)
Old Project: PS4-Rich-Presence-for-Discord/goldhen-rich-presence-bin (local, not committed)
Session 1: Understanding the Codebase (2026-09-29)
What we reviewed
- orbisRPC — complete self-contained Discord Rich Presence daemon running on PS4 via GoldHEN
- Architecture: Payload ELF → direct TLS WebSocket → Discord gateway (no PC client needed)
- Key modules: daemon.c (loop), detect.c (sandbox mount + eboot count), discord.c/ws.c/tls.c (gateway), art.c/tmdb.c (artwork), updater.c (self-update), cfg.c (config + self-learning titles)
- Installer: One-tap PKG that stages payload + evict.elf + config, prompts for Discord token
Key differences from old project (goldhen-rich-presence-bin)
| Aspect | Old | orbisRPC |
|---|---|---|
| Transport | Payload → TCP:8000 → Python PC → Discord IPC | Payload → TLS WebSocket → Discord Gateway |
| Detection | kern.msgbuf polling | /mnt/sandbox/TITLEID_000 + eboot count |
| Game names | Title ID only | Multi-source: config → app.db → SFO → TMDB |
| Artwork | None | mp: proxy via external-assets (Sony CDN) |
| Timer | PC-side | Console-side (SNTP), survives reconnects/restarts |
| Updates | Manual | Self-updating from GitHub with rollback |
| Installer | Manual ncat send | PKG (OrbisRPC-Setup.pkg) |
Known issues (from HANDOFF.md — file since deleted, content merged into docs/)
- Cover art shows "?" — mp: proxy works but asset propagation needs work
- Stale title on fresh launches — cloud sync bulk-touches save mtimes
- Game crashes (CE-34878-0) on some titles with daemon running
- IME keyboard never opens (token pre-seeded via FTP)
- Rest Mode wake/resume untested
- Updater drill untested
- Plugin path (PRX) untested — must ship in PKG
Session 2: Removed Plugin/PRX Support (2026-09-29)
Decision: Keep payload-only, remove all PRX plugin code.
Changes made
| File | Change |
|---|---|
plugin/ |
Deleted entirely |
orbisrpc/daemon.h |
Removed fixed_game_name param from daemon_run() |
orbisrpc/daemon.c |
Removed plugin path from health check targets; removed plugin-mode logic |
orbisrpc/main.c |
daemon_run(NULL) → daemon_run() |
orbisrpc/detect.h/c |
Removed "(plugin mode)" comments |
orbisrpc/tls.h |
Removed "and plugin processes" |
orbisrpc/ws.c |
Removed "(plugin_unload joins this thread)" |
orbisrpc/updater.h/c |
Removed plugin asset download/stage logic |
orbisrpc/updater_util.c |
Removed updater_self_ok() (SELF check for PRXs) |
orbisrpc/compat.c/log.c/sfo.c |
Removed "plugin" references |
Session 3: Flat Binary Build (2026-09-29)
Request: Convert build to produce flat .bin for BinLoader one-shot injection (like old project).
Change to scripts/build_sdk.sh
Added objcopy -O binary after linking:
"$CC" -o "$OUT/orbisrpc_sdk.elf" "$OUT"/*.o
"$SDK/bin/orbis-objcopy" -O binary "$OUT/orbisrpc_sdk.elf" "$OUT/orbisrpc_sdk.bin"
Build command (run in WSL)
PS4_PAYLOAD_SDK=/mnt/c/Tools/ps4-payload-sdk-reference ./scripts/build_sdk.sh
Fixed
- Line endings (CRLF → LF) on
scripts/build_sdk.shandscripts/build_evict.sh
Caveats to test
.bsshandling — flat binary drops.bss; large static buffers will crash- SDK libc — global constructors may not run in flat binary
- Relocations — works if position-independent (
-fPIC/-fpie)
Correction (2026-09-29, after review)
Sessions 3 and 4 above went in the wrong direction. Fixed:
- Wrong SDK.
ps4-payload-sdk-referenceis Scene-Collective libPS4 (no libc, runtime-resolved functions), the SDK of the old goldhen-rich-presence-bin project. orbisRPC needs libc, BSD sockets, mbedTLS and sqlite, so it builds with the ps4-payload-dev SDK instead (ps4-payload-sdk.zip, see.github/workflows/ci.yml, jobsdk-payload). The OpenOrbis toolchain is for PKG apps and does not provide theorbis-clangthatbuild_sdk.shcalls. - Flat
.binreverted. The daemon ELF is dynamically linked (CI gate requires NEEDEDlibkernel_web.sprx,libSceLibcInternal.sprx,libSceNet.sprx).objcopy -O binarydiscards the dynamic section and relocations, and BinLoader has no dynamic linker, so the flat file would most likely not run (inference, untested). Theobjcopylines were removed fromscripts/build_sdk.sh; it outputsbuild-sdk/orbisrpc_sdk.elfagain. Line endings verified LF,sh -npasses. - The ELF is meant for elfldr (port 9021 per the repo docs) or Payload Guest.
Correct SDK install (WSL)
sudo apt update && sudo apt install -y clang lld llvm unzip curl
mkdir -p ~/ps4-payload-sdk
curl -L -o /tmp/sdk.zip https://github.com/ps4-payload-dev/sdk/releases/latest/download/ps4-payload-sdk.zip
unzip -o /tmp/sdk.zip -d ~/ps4-payload-sdk
export PS4_PAYLOAD_SDK=$HOME/ps4-payload-sdk/ps4-payload-sdk
ls $PS4_PAYLOAD_SDK/bin
cd /mnt/c/Users/user/Documents/GitHub/orbisRPC
./scripts/build_sdk.sh
Open question
How to move features from the old kern.msgbuf payload (AppFocusChanged / Kill App close detection, Home/Settings screen states) into orbisRPC. To be decided after the ELF builds and runs via elfldr.
Session 4: Toolchain Setup (2026-09-29)
Goal: Install OpenOrbis LLVM toolchain (orbis-clang, orbis-objcopy) in WSL for building the flat .bin.
Attempted approaches
- Prebuilt release URL (404) —
llvm-15.0.7release not found on GitHub - Build from source —
OpenOrbis-PS4-Toolchainrepo only contains headers/stubs;build-toolchain.shdoesn't exist - System clang + lld — Ubuntu's clang 18 lacks FreeBSD/PS4 targets
- Prebuilt v0.5.4 release —
toolchain-llvm-18.tar.gz(LLVM 18 with FreeBSD targets) — correct path
Commands to run in WSL
cd /opt
sudo wget https://github.com/OpenOrbis/OpenOrbis-PS4-Toolchain/releases/download/v0.5.4/toolchain-llvm-18.tar.gz
sudo tar -xf toolchain-llvm-18.tar.gz
sudo ln -sf /opt/toolchain-llvm-18/bin/clang /usr/local/bin/orbis-clang
sudo ln -sf /opt/toolchain-llvm-18/bin/llvm-objcopy /usr/local/bin/orbis-objcopy
sudo ln -sf /opt/toolchain-llvm-18/bin/ld.lld /usr/local/bin/orbis-ld
sudo ln -sf /opt/toolchain-llvm-18/bin/llvm-ar /usr/local/bin/orbis-ar
orbis-clang --version
Environment setup
export OO_PS4_TOOLCHAIN=/opt/OpenOrbis-PS4-Toolchain
export PATH="$OO_PS4_TOOLCHAIN/bin/linux:$PATH"
Then build
cd /mnt/c/Tools/ps4-payload-sdk-reference
make -C libPS4
cd /mnt/c/Users/user/Documents/GitHub/orbisRPC
PS4_PAYLOAD_SDK=/mnt/c/Tools/ps4-payload-sdk-reference ./scripts/build_sdk.sh
Session 5: ELF vs flat bin on high firmware (2026-09-29)
- User reports ELF payloads do not work on high PS4 firmwares like 13.52 (cause not investigated). The repo docs (
docs/injecting.md,docs/research/loader.md) say BinLoader 9020 and elfldr 9021 take the ELF, but that was only observed on 9.00 / GoldHEN 2.4. - Context from web search: PS4 13.52 got a public WebKit jailbreak on 2026-09-19 and GoldHEN 2.4b18.11 support on 2026-09-20 (beta; other 13.xx builds planned later).
- Conclusion: a flat
.bin(libPS4 style, like the old kern.msgbuf payload) is needed for this console. - Extra risk: the daemon has only ever run on 9.00.
orbisrpc/detect.creads the process table with hard-coded offsets (name at 447, record size 479, pid at 72); these may differ on 13.52, so detection needs verifying even after a flat port. - Approach agreed in principle: do NOT port the whole daemon at once. Grow the old flat payload into orbisRPC step by step, in a new folder, leaving the old payload and the repo daemon untouched.
Step plan
- Network probe: resolve
gateway.discord.gg, plain TCP connect to :443 from a flat payload. - TLS handshake with mbedTLS (libc shims, /dev/urandom entropy, stack/heap size). Biggest risk.
- WebSocket + Discord gateway (HELLO, IDENTIFY, heartbeats).
- Presence from the old payload's detection, copied as-is (kern.msgbuf AppFocusChanged / Kill App logic,
closed_latch, shared mmap buffer). DECIDED by user 2026-09-29: orbisRPC'sdetect.c(process-table offsets, save/atime scans) is NOT ported. - Names and art (SFO / pronunciation first, then TMDB over TLS, mp: proxy).
- Persistence: config, session, timer.
Other flat-image constraints to watch: no relocations in a flat image, so static pointer tables (host allowlist, media table, protos) need rewriting or a small self-relocator; sqlite/appdb can be dropped (appdb_title is already commented out in detect.c).
Decisions
- Port scope: connectivity (DNS/TCP/TLS), WebSocket + gateway, clock/timer first; names (config map, SFO, pronunciation) and art (mp: proxy, TMDB) second. Skip updater, manifest, health, installer, evict, lock, sqlite/appdb.
- Detection: user's kern.msgbuf method from goldhen-rich-presence-bin (see step 4). This also removes the 9.00-specific process-table risk for the port.
- Firmware detection: user's logic from goldhen-rich-presence-bin is carried over as-is (firmware string parsed from
libc.sprxin the sandbox path, then/system/common/lib/libc.sprx, with the system API as fallback). Runs at startup, is logged, and is available for any firmware-specific branches. Added 2026-09-29 at user's request. - Open concern raised: orbisRPC needs a raw Discord user token on the console and identifies as a desktop client (against Discord ToS, ban risk); suggested a throwaway account, or keeping the PC relay. Steps 1-2 need no token.
Pending
- User go-ahead for step 1 and where the new folder goes (inside orbisRPC repo or next to the old project).
- Current state of repo:
scripts/build_sdk.shis ELF-only again; plugin/PRX code removed; nothing else changed.
Session 6: Port step 1, network probe (2026-09-29)
User chose to build the port inside the existing project directory (goldhen-rich-presence-bin), not a new folder. Existing files (Makefile, source/main.c, icon_embedded.h) are untouched; the probe is additive.
New files:
source/probe_net.c: flat-BIN probe using libPS4. Reuses the firmware detection frommain.cunchanged. Tests (1) TCP to literal1.1.1.1:443, (2) DNS forgateway.discord.ggvia libSceNet resolver (sceNetPoolCreate+sceNetResolverCreate+sceNetResolverStartNtoa; libPS4 has no DNS of its own), (3) TCP to the resolved IP on 443. Non-blocking connect polled up to 15 s. Output: klog,/user/data/rpc_probe.log(FTP :2121), and a final notification. No TLS, no token.Makefile.probe: separate build target so the working payload's Makefile is not modified. OutputDiscord_RPC_Probe.bin/Discord_RPC_Probe.map. Tabs and LF line endings verified.
Not compiled by Claude (user prefers to run builds). Update: user built it in WSL, build OK (no errors), now testing on console. If -Werror trips on a redeclared sceNet* symbol, paste the error.
Build and run (WSL):
cd /mnt/c/Tools/PS4-Rich-Presence-for-Discord/goldhen-rich-presence-bin
export PS4SDK=/mnt/c/Tools/ps4-payload-sdk-reference
make -f Makefile.probe clean && make -f Makefile.probe
ncat PS4_IP 9090 --send-only < Discord_RPC_Probe.bin
Then read /user/data/rpc_probe.log over FTP (:2121) or the klog.
What the result decides: if DNS fails, try other resolver setup (skip sceNetInit, different pool size); if TCP by IP fails, the payload's network context is the problem; if all pass, go to step 2 (mbedTLS handshake).
Session 6 result: step 1 passed on firmware 13.52 (2026-09-29)
Probe output from the console:
- literal-ip: TCP 1.1.1.1:443 OK after ~100 ms
- dns: pool create rc=0x00000bc2, resolver create rc=0x0000001b (both non-zero, but the lookup worked anyway)
- dns: gateway.discord.gg -> 162.159.133.234
- gateway: TCP 162.159.133.234:443 OK after ~200 ms
Conclusion: DNS, sockets and outbound TCP all work from a flat libPS4 payload on 13.52. Step 1 done, no token involved.
Session 7: step 2a, self-relocating flat BIN (2026-09-29)
Why: mbedTLS is full of static pointer tables (vtables, cipher/md info structs, function-pointer tables). A flat image has no dynamic relocations, so those point at link-time addresses and break when the loader places the image anywhere except address 0. Before compiling mbedTLS in, prove the fix on the console.
New files in goldhen-rich-presence-bin (additive; Makefile, Makefile.probe, source/main.c, source/probe_net.c untouched):
crt0_reloc.s: entry point that walks a table appended at__file_endand adds the runtime load base to each listed 64-bit word, then jumps to_main. Only r8-r10 and rax are touched, so rdi (thread arg) is preserved.linker_reloc.x: like libPS4'slinker.xbut links at address 0, keeps.got, broadens.rodata/.datapatterns for-fdata-sections, and defines__file_end.tools/mkreloc.py: reads the ELF (--emit-relocs), collects R_X86_64_64 words in loaded sections plus non-zero.gotwords, appendsu32 count + u32 offsetsto the.bin. Fails loudly on unsupported relocation types or a relocation inside.bss.source/reloc_test.c: console test with a const table of strings and function pointers plus a writable pointer to a global. Logs to/user/data/rpc_reloc.log, shows one notification, prints PASS or FAIL.Makefile.reloc: separate target, outputDiscord_RPC_RelocTest.bin.
Tested off-console only: a toy program at a randomized non-zero load address relocated correctly, and a negative control with the table emptied failed as expected. Not yet built with the real SDK or run on the console.
Build and send (WSL):
cd /mnt/c/Tools/PS4-Rich-Presence-for-Discord/goldhen-rich-presence-bin
export PS4SDK=/mnt/c/Tools/ps4-payload-sdk-reference
make -f Makefile.reloc clean && make -f Makefile.reloc
ncat PS4_IP 9090 --send-only < Discord_RPC_RelocTest.bin
Then read /user/data/rpc_reloc.log over FTP (:2121). Expect relocation test PASS and a non-zero entry count. If the build fails, paste the error. Note mkreloc.py needs python3 in WSL.
What the result decides: PASS means pointer tables work in a flat BIN, so go on to step 2b (mbedTLS handshake). FAIL means look at the logged base/entry count first.
Build error and fix (2026-09-29)
First WSL build failed in mkreloc.py: unsupported relocation type 11 at 0x7f in .text (R_X86_64_32S).
Cause: reloc_test.o and libPS4.a are compiled -fPIC, so they load extern symbols with mov reg, [rip+sym@GOTPCREL] (R_X86_64_REX_GOTPCRELX). In a static non-PIE link the linker relaxes those into mov reg, imm32 with an absolute 32-bit address. A 32-bit immediate can't take a 64-bit base added to it, so the self-relocator can't fix it.
Fix: add -Wl,--no-relax to LFLAGS in Makefile.reloc, so the GOT loads stay and the addresses live in .got as 64-bit words, which the relocator does handle. Checked in a scratch link with the same reloc_test.o and libPS4.a: 138 R_X86_64_32S relocations before, 0 after; mkreloc.py then reports 131 relocation words (.data: 5, .got: 126), 7,856 bytes total. Not run on the console yet.
This matters for step 2b too: mbedTLS code will hit the same thing, and the same flag covers it.
Two more relocator bugs found in code review (2026-09-29)
Found by linking a toy program and running it at random load addresses in a scratch harness (not on the console):
- Table overlapped
.bss..bssstarts at__file_end, which is exactly wheremkreloc.pyappends the table, so zero-initialised globals started out holding table bytes (for examplerpc_log_startedbegan as the entry count, so the log was appended to instead of truncated). Fix:crt0_reloc.snow zeroes the table after applying it. - Zero-valued GOT slot skipped. With
--no-relax,(unsigned long)_startis loaded through a GOT slot whose link-time value is 0, andmkreloc.pyonly relocated non-zero GOT words, sobaseread as 0 andreloc_testwould have reported a false FAIL. Fix:mkreloc.pynow also finds GOT slots from the GOTPCREL relocations in the code.
Scratch results: before the fixes the toy returned failure bits at every base; after, 5 of 5 random bases pass, and a negative control with an empty table fails. The real reloc_test.o + libPS4.a link now gives 132 relocation words (was 131). Files changed: crt0_reloc.s, tools/mkreloc.py. Rebuild with the same commands; expect the entry count in rpc_reloc.log to be 132.
Next Steps (Pending User Direction)
- Test the flat binary on PS4 via BinLoader (port 9020)
- If crashes: Check
.bsssize in map, move large statics to runtimemmap - Migrate features incrementally from old project as needed:
- kern.msgbuf fallback detection?
- Different Discord auth (OAuth/Social SDK)?
- Other?
Reference: Old Project Status (goldhen-rich-presence-bin)
Last session (2026-09-29) applied patches:
.bss→ runtimemmapfor kern.msgbuf buffer- False
closedevents fixed (return uncertain when log wraps) - kern.msgbuf > 128 KB handled (dynamic size query)
- Title stays after closing app fixed (closed_latch)
Next steps noted: rebuild in WSL, send to GoldHEN, test on console, capture klog.