From 21e57a82cc1db47d57c40650eacdaa8d7d542936 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Jul 2026 17:08:19 +0000 Subject: [PATCH] docs+patch: psx-beetle oracle on Linux (pinned beetle-psx base + SIO trace hook) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit beetle_libretro.cpp targets the C++ beetle-psx tree; upstream master has been converted to plain C and no longer compiles against it. Documented the working recipe: pin beetle-psx at 5759277b (the wtrace patch's base, located via the patch's own blob hash), apply beetle_wtrace_hook.patch, and apply the new beetle_sio_trace_hook.patch — FrontIO::SetSIOTraceCallback (fires once per completed SIO byte exchange), a hook beetle_libretro.cpp required that was missing from the committed patch set. Verified on Linux/Xvfb: psx-beetle boots Kula World to demo gameplay and serves ping/screenshot over the shared TCP debug protocol, alongside kula-runtime — the two-process oracle setup from CLAUDE.md §16 now works in this environment. Runtime-created per-game .mcr files are gitignored. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01BdjxoRB1f9VQsNzZayCgGS --- .gitignore | 4 ++++ docs/beetle-linux.md | 41 ++++++++++++++++++++++++++++++++ docs/beetle_sio_trace_hook.patch | 35 +++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 docs/beetle-linux.md create mode 100644 docs/beetle_sio_trace_hook.patch diff --git a/.gitignore b/.gitignore index 401cdaf2..f77307f6 100644 --- a/.gitignore +++ b/.gitignore @@ -84,3 +84,7 @@ _wip/ games/*/* !games/*/game.toml !games/*/seeds.txt + +# Per-game memcards created at runtime +*.mcr +!dummy.*.mcr diff --git a/docs/beetle-linux.md b/docs/beetle-linux.md new file mode 100644 index 00000000..f95dd678 --- /dev/null +++ b/docs/beetle-linux.md @@ -0,0 +1,41 @@ +# Building psx-beetle on Linux + +The psx-beetle oracle builds and runs on Linux with the same wire protocol +as on Windows. Verified 2026-07-02 (Kula World boots to demo gameplay; +ping/screenshot served over the TCP debug protocol). + +## beetle-psx checkout + +`runtime/src/beetle_libretro.cpp` targets the C++ beetle-psx tree. Upstream +master has since been converted to plain C (`libretro.cpp` -> `libretro.c`, +`PS_CPU` class dropped), which no longer compiles against our integration. +Pin the checkout to the last compatible commit — the same base +`docs/beetle_wtrace_hook.patch` was generated from: + +```bash +git clone https://github.com/libretro/beetle-psx-libretro.git beetle-psx +cd beetle-psx +git checkout 5759277b # "audit pass" — last C++-tree base we target +patch -p1 < ../docs/beetle_wtrace_hook.patch +patch -p1 < ../docs/beetle_sio_trace_hook.patch +``` + +`beetle_sio_trace_hook.patch` adds `FrontIO::SetSIOTraceCallback` (fires per +completed SIO byte exchange) — an integration hook beetle_libretro.cpp needs +that predated the committed wtrace patch. + +## Build + +```bash +# Static lib. On unix the artifact is named mednafen_psx_libretro.so but is +# an ar archive (STATIC_LINKING=1); stage it under the name cmake expects. +make platform=unix STATIC_LINKING=1 HAVE_LIGHTREC=0 -j"$(nproc)" +cp mednafen_psx_libretro.so libmednafen_psx.a + +cd ../runtime +cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DPSX_LAUNCHER=OFF -DPSX_DEBUG_TOOLS=ON +ninja -C build psx-beetle + +# Headless run (picks the next free port from 4380 if taken; watch stderr) +xvfb-run -a ./runtime/build/psx-beetle ../bios/SCPH1001.BIN --disc +``` diff --git a/docs/beetle_sio_trace_hook.patch b/docs/beetle_sio_trace_hook.patch new file mode 100644 index 00000000..935b5315 --- /dev/null +++ b/docs/beetle_sio_trace_hook.patch @@ -0,0 +1,35 @@ +diff --git a/mednafen/psx/frontio.cpp b/mednafen/psx/frontio.cpp +index a35b022f..02e7ce0b 100644 +--- a/mednafen/psx/frontio.cpp ++++ b/mednafen/psx/frontio.cpp +@@ -783,6 +783,10 @@ int32_t FrontIO::Update(int32_t timestamp) + ReceiveInProgress = false; + ReceiveBufferAvail = true; + ++ /* PSXRecomp oracle hook: byte exchange complete. */ ++ if(MDFN_UNLIKELY(sio_trace_cb)) ++ sio_trace_cb(TransmitBuffer, ReceiveBuffer, (uint16_t)Control); ++ + if(Control & 0x800) + { + istatus = true; +diff --git a/mednafen/psx/frontio.h b/mednafen/psx/frontio.h +index 8a67f5af..d9a260ca 100644 +--- a/mednafen/psx/frontio.h ++++ b/mednafen/psx/frontio.h +@@ -95,8 +95,15 @@ class FrontIO + + int StateAction(StateMem* sm, int load, int data_only); + ++ /* PSXRecomp oracle hook: fires once per completed SIO byte exchange ++ * (tx byte sent, rx byte received, current Control register). */ ++ typedef void (*sio_trace_cb_t)(uint8_t tx, uint8_t rx, uint16_t ctrl); ++ void SetSIOTraceCallback(sio_trace_cb_t cb) { sio_trace_cb = cb; } ++ + private: + ++ sio_trace_cb_t sio_trace_cb = nullptr; ++ + void DoDSRIRQ(void); + void CheckStartStopPending(int32_t timestamp, bool skip_event_set = false); +