From 2e2b87ec69fbf2ceaa3adb459448d3ab88de1818 Mon Sep 17 00:00:00 2001 From: Ruben Ripalda Date: Wed, 30 Sep 2026 16:15:24 -0700 Subject: [PATCH] Add developer tools --- tools/embed_assets.py | 26 +++++++++ tools/mock_ps5.py | 125 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 tools/embed_assets.py create mode 100644 tools/mock_ps5.py diff --git a/tools/embed_assets.py b/tools/embed_assets.py new file mode 100644 index 0000000..4161e35 --- /dev/null +++ b/tools/embed_assets.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +"""Regenerate src/assets_embed.cpp from assets/ (the UI font and the PSGFX mark). +Run from the repository root: python3 tools/embed_assets.py""" +import os + +FILES = [ + ("sora300", "assets/fonts/sora300.woff2"), + ("sora400", "assets/fonts/sora400.woff2"), + ("sora600", "assets/fonts/sora600.woff2"), + ("sora700", "assets/fonts/sora700.woff2"), + ("mark_svg", "assets/mark.svg"), + ("wordmark_png", "assets/wordmark-ui.png"), +] + +out = ["// Generated by tools/embed_assets.py - do not edit.", + "// Sora font (SIL Open Font License 1.1, see assets/fonts/OFL.txt) the PSGFX mark and wordmark.", + "#include "] +for name, path in FILES: + data = open(path, "rb").read() + out.append(f"extern const unsigned char {name}[] = {{") + for i in range(0, len(data), 24): + out.append(" " + ",".join(str(b) for b in data[i:i + 24]) + ",") + out.append("};") + out.append(f"extern const size_t {name}_len = {len(data)};") +open("src/assets_embed.cpp", "w").write("\n".join(out) + "\n") +print("wrote src/assets_embed.cpp") diff --git a/tools/mock_ps5.py b/tools/mock_ps5.py new file mode 100644 index 0000000..39fe938 --- /dev/null +++ b/tools/mock_ps5.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +"""File-backed stand-in for PS5 Upload's payload (development only), following its runtime.c + register.c. +Usage: python3 tools/mock_ps5.py ROOT MGMT_PORT XFER_PORT (set MOCK_FW13=1 to mimic firmware 12/13 register behaviour) +Serves management (FTX2) and transfer frames on two ports; paths map under ROOT.""" +import base64, json, os, shutil, socket, struct, sys, threading + +ROOT = sys.argv[1]; MPORT = int(sys.argv[2]); XPORT = int(sys.argv[3]) +ALLOWED = ("/data/", "/user/", "/mnt/") +txs = {} + +def P(p): return os.path.join(ROOT, p.lstrip("/")) +def allowed(p): return p.startswith(ALLOWED) and ".." not in p + +def recv_exact(s, n): + b = b"" + while len(b) < n: + c = s.recv(n - len(b)) + if not c: raise EOFError + b += c + return b + +def send(s, t, body=b""): + if isinstance(body, str): body = body.encode() + s.sendall(struct.pack("