Skip to content

v0.1.1 — three live-test bug fixes + auto-pause screenshot

Choose a tag to compare

@dmang-dev dmang-dev released this 16 May 19:57
· 69 commits to main since this release

Three real bugs surfaced by the first end-to-end live test of v0.1.0 against PPSSPP v1.20.3 + a PSP homebrew. Protocol mapping was right in the abstract but wrong in three details — all caught and fixed.

Fixed

  • Memory reads were returning undefined — PPSSPP's memory.read_u8 / _u16 / _u32 responses use the field name value, not uintValue (which I'd assumed from the singular-register cpu.getReg/setReg responses, which DO use uintValue). Memory r/w round-trip now validated end-to-end: write 0xDEADBEEF to 0x08800000 + read back = match.

  • cpu.getAllRegs response shape was wrong — I'd assumed {categories: [{name, registers: [{name, uintValue}]}]}. Actual PPSSPP shape is {categories: [{name, registerNames: [...], uintValues: [...], floatValues: [...]}]} — parallel arrays, not an array of objects. Rewrote the handler with bounds-aware parallel indexing.

  • cpu.stepping and cpu.resume were hanging — PPSSPP source documents these as "No immediate response. Once CPU is stepping, a 'cpu.stepping' event will be sent." (async broadcast with no ticket). My ticketed call() was waiting 10s for a reply that never comes. Added PpssppClient.fireAndForget(event, params) and PpssppClient.waitForState(predicate, opts) which polls cpu.status (which IS synchronous) until the state change is detected. ppsspp_pause / ppsspp_resume / the screenshot internal pause/resume now use this pattern.

Changed

  • ppsspp_screenshot now auto-pauses + auto-resumes — PPSSPP's gpu.buffer.screenshot requires CPU or GPU to be stepping (otherwise "Neither CPU or GPU is stepping" error). The tool now transparently cpu.steppings, captures, and cpu.resumes. If the caller had already paused, it leaves the state alone on exit. Also requests type: "base64" explicitly (PPSSPP's default is "uri" which returns a data:image/png;base64,... prefix); belt-and-suspenders URI-prefix stripping kept as a fallback.

Added

  • scripts/smoke.cjs — live test harness that connects to PPSSPP, exercises every major event path (ping, game.status, memory r/w, pause/resume, registers, screenshot, breakpoints), and reports per-event status. Used to surface all three bugs above. Run with PPSSPP_PORT=<port> node scripts/smoke.cjs.

Known limitations

  • gpu.buffer.screenshot is backend-dependent — observed "Could not download output" on a homebrew where the GPU readback path can't fetch the framebuffer. This is a PPSSPP-side limitation (the GPU backend's framebuffer readback support varies), not a bug in our code. Likely works on commercial PSP games with normal rendering.

Validated live

Smoke-tested end-to-end against PPSSPP v1.20.3 (Windows x64) running BTC Miner PSP:

Event Result
WebSocket handshake (debugger.ppsspp.org subprotocol) ✅
version (ping) ✅ returns PPSSPP v1.20.3
game.status ✅ returns full game metadata
memory.read_u8/u16/u32 ✅ returns value field
memory.read (range, base64) ✅
memory.write_u32 + read-back ✅
cpu.stepping (fire-and-forget + poll) ✅
cpu.resume (fire-and-forget + poll) ✅
cpu.getAllRegs (parallel arrays) ✅
cpu.breakpoint.list ✅
gpu.buffer.screenshot ⚠️ backend/game-dependent

Upgrade

npm install -g mcp-ppsspp@0.1.1

The bridge protocol is the same — no PPSSPP-side changes required.