Files
TiagoVal97--cheatspecter/payload
Tiago Valente 252ccd2e4c CheatSpecter 0.3.0
Browser-based real-time modding tool for offline single-player games on a
jailbroken PS5, served by a payload on the console.

- Value search, memory and code views, find what writes to a value
- Cheats as patches, held values, injected code, calls and scripts
- .cspector cheat files, saved on the PS5 or on your device
- Community tables in JSON, SHN and MC4 from three repositories
- Game library with names, logos and sizes; start a game from the browser
- MCP server for assistants
2026-10-10 10:16:57 -07:00
..
2026-10-10 10:16:57 -07:00
2026-10-10 10:16:57 -07:00

On-console payload

cheatspecter.elf runs on the PS5 and removes the computer from the picture. It serves the web app and bridges it to the debugger, so any phone or laptop on the network just opens http://<PS5 IP>:8744.

Status: builds and passes its tests on a computer; not yet run on a real PS5. The same source is compiled natively and exercised against the mock console (test/payload.test.mjs): serving the app, the WebSocket handshake, large transfers both ways, several connections at once, a missing debugger, and cross-site rejection. What that cannot show is how it behaves under the console's own loader and network stack.

Use it

Send cheatspecter-v<version>.elf if you use a payload manager: it reads the version from the file name and shows it next to the payload. cheatspecter.elf is the same build under a fixed name, for scripts.

  1. Load ps5debug-NG on the console as usual.

  2. Send payload/cheatspecter.elf to your ELF loader, the same way you load any other payload. From this folder:

    npm run payload:send -- 192.168.1.20        # loader port 9021 by default
    
  3. A notification on the TV shows the address to open.

It has to be sent again after each reboot, like any payload. Sending it twice is harmless: the second copy sees the port is taken, says so, and exits.

What it does

Request Behaviour
GET /, /assets/*, /ghost.svg The web app, embedded in the ELF and served gzip-compressed.
GET /api/info {"mode":"console","version":"..."}. The app sees this and skips the "find your PS5" screen.
WS /ws Opens a TCP connection to 127.0.0.1:744 and relays binary frames both ways, unchanged. One WebSocket is one TCP connection.
GET /api/library Installed titles: {"titles":[{"id","meta":"json"|"sfo","size","path"}]}. meta is which metadata file the title has (param.json = PS5, param.sfo = PS4).
GET /api/appmeta/<title id>/<param.json|param.sfo|icon0.png> The system's own metadata file for a title, untouched. The web app reads the name from it.
POST /api/launch/<title id> Closes the running game, if any, and starts this one.
GET /api/tables/<title id> Which game versions have a saved cheat file.
GET, PUT /api/tables/<title id>/<version> The user's cheats for that game version, stored as /data/cheatspecter/cheats/<title id>-<version>.cspecter.
WS /events Debugger stop reports. The payload listens on 127.0.0.1:755, where the debugger connects when something attaches, and forwards what arrives.

It is deliberately thin. All protocol knowledge and file parsing stay in the web app, and ps5debug-NG keeps doing the kernel work.

WebSocket upgrades, launches and file saves are refused when the Origin host differs from Host, so another web page cannot drive the console through a visitor's browser. Title IDs and versions are checked against a strict pattern before they are used in a path.

The library is built from the system's metadata folders (/system_data/priv/appmeta, /user/appmeta). Sizes are the files found under /user/app, /user/patch, the same folders on /mnt/ext0 and /mnt/ext1, and /system_ex/app, where game folders kept elsewhere are mounted. A title with none of those is listed without a size; one with more than 200,000 files is marked partial.

Build it

npm run payload:host     # for this computer; then: CS_PORT=8745 CS_DEBUGGER_PORT=7440 payload/build/cheatspecter-host
PS5_PAYLOAD_SDK=/opt/ps5-payload-sdk npm run payload     # cheatspecter.elf

Both embed whatever npm run build produced, so the ELF needs rebuilding after any change to the web app. The PS5 build needs ps5-payload-sdk with clang and lld.

src/main.c is the whole thing: an HTTP server, a WebSocket relay with one thread per direction, and SHA-1 and Base64 for the handshake.