From ROM Workbench
One-time installer for the WPC mod toolchain — Visual Pinball X + PinMAME + VPinMAME + the patched libpinmame (for record). Use only on first machine setup or when reinstalling a single component. Not needed for day-to-day mod work.
How this skill is triggered — by the user, by Claude, or both
Slash command
/rom-workbench:setupThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> **Orientation:** if you haven't already, load `rom-workbench:overview` for the
Orientation: if you haven't already, load
rom-workbench:overviewfor the end-to-end mod workflow (setup → record → synthesize → debug → build → test) and where this step fits.
One-time install. Once setup runs successfully, day-to-day work doesn't need this skill loaded — debug and record use the installed components directly.
For everyday "analyze a ROM" / "replay a session" / "set a breakpoint" requests, skip this skill — the install is already done on a configured machine.
Everything lands under one per-user data root (see "Setup scripts" below):
%LOCALAPPDATA%\rom-workbench\ on Windows, ~/Library/Application Support/rom-workbench/
on macOS, ~/.local/share/rom-workbench/ on Linux.
| Component | Where | Env var |
|---|---|---|
| Visual Pinball X 10.8.0 | <root>\vpinball | VPINBALL_DIR |
Patched libpinmame.dll (prebuilt from bin/) | <root>\pinmame | PINMAME_DIR |
| VPinMAME COM (regsvr32-registered) | <root>\vpinmame | VPINMAME_DIR |
Pillow (via pip, for the DMD-render tools) | this Python's environment | — |
| Patched VPinMAME64.dll | deployed over the installed VPinMAME | — |
No PinMAME standalone is downloaded: replay loads only the self-contained
libpinmame.dll, which ships prebuilt in bin/. VPinMAME is still installed —
it supplies bass64.dll (a hard dependency of the patched VPinMAME64.dll) and
the directory layout VP's COM path expects.
| Component | Where | Env var |
|---|---|---|
| Visual Pinball X (macOS GL build) | <root>/vpinball | VPINBALL_DIR |
| Patched libpinmame.dylib | <root>/pinmame | PINMAME_DIR |
Pillow (via pip, for the DMD-render tools) | this Python's environment | — |
On macOS the patched libpinmame.dylib ships prebuilt in bin/ for the common
case; setup-pinball.py only builds from source (from --pinmame-src,
default ../pinmame beside the repo) when no arch-matched prebuilt is available.
Env vars are written to ~/.zshenv and ~/.bash_profile.
setup-pinball.py — cross-platform toolchain installerOne stdlib-only Python script handles both macOS and Windows (replacing the
old setup-pinball.sh / setup-pinball.ps1 pair). It requires Python 3.9+ and
pip on PATH; run it directly:
python3 '${CLAUDE_PLUGIN_ROOT}/bin/setup-pinball.py' [--force] [--install-root <dir>] [--pinmame-src <path>]
Everything installs under a per-user data directory (no admin needed for the
files themselves), with vpinball/, pinmame/ and — on Windows — vpinmame/
underneath, plus a cache/:
| OS | Install root |
|---|---|
| macOS | ~/Library/Application Support/rom-workbench/ |
| Windows | %LOCALAPPDATA%\rom-workbench\ |
| Linux | $XDG_DATA_HOME (or ~/.local/share)/rom-workbench/ |
Override with --install-root. Idempotent; pass --force to re-download/rebuild.
Steps:
pip is available for the launching interpreter, then pip install pillow (the only third-party dependency, used by the DMD-render tools). Every other tool is stdlib-only and runs as python3 <tool>.py.<root>/vpinball/ (skips gracefully if the pinned release has no asset for this OS/arch; replay doesn't need VPX).bin/ into <root>/pinmame/ (replay loads it via ctypes; it's self-contained, so nothing is downloaded).
libpinmame.dylib (prefer the arch-matched prebuilt in bin/; otherwise build from --pinmame-src, default ../pinmame beside the repo). Also deploy it into the VPX bundle, ad-hoc re-sign, and run a Gatekeeper trial-launch.lib/libpinmame.dll into <root>/pinmame/. Then download VPinMAME COM into <root>/vpinmame/ (for bass64.dll + the layout), deploy the patched VPinMAME64.dll, and regsvr32-register it (needs an elevated shell once — the script detects this and prints the exact relaunch command rather than failing).VPINBALL_DIR, PINMAME_DIR, and (Windows) VPINMAME_DIR — two ways:
~/.zshenv and ~/.bash_profile; Windows writes the user environment (HKCU).config.env at the platform-default data dir (%LOCALAPPDATA%\rom-workbench\config.env, ~/Library/Application Support/rom-workbench/config.env, or $XDG_DATA_HOME/rom-workbench/config.env). Every entrypoint calls workbench_env.load_config() at startup to read it, so the toolchain works in a fresh shell that never inherited the user env vars — no "open a new terminal" step. An explicit shell export still wins over the file.Downloads are SHA-256 verified against a sidecar recorded on first use (trust-on-first-use). To pin upstream hashes, fill in the empty expected_sha constants near the top of the script.
There's no per-game install command. record.py finds a game's files by
convention from the working directory:
| File | Looked for at | Override |
|---|---|---|
| ROM zip | ./orig/<rom>.zip, then ./dist/<rom>.zip | --rom-zip <path> |
| VPX table | ./tables/<rom>.vpx | --table <path> |
record.py stages the ROM zip into VP's roms/ dir ($PINMAME_DIR/roms on
macOS, %VPINMAME_DIR%\roms on Windows) itself, just before launch — VP loads
ROMs from there by gamename, so it only has to live there at record time. Drop a
game's files into ./orig/ and ./tables/ and run record.py --rom <name>;
nothing to register.
Each game needs two files: a ROM zip and a VPX table. Neither is auto-downloaded.
| File | What it is | Where it comes from |
|---|---|---|
ROM zip (e.g. congo_21.zip) | The 6809 game ROM dump VPinMAME runs. Same shape PinMAME has used for 20+ years. | VPForums "ROMs" section, sometimes bundled with VPX downloads. |
VPX table (.vpx, sometimes inside a .zip) | The VP playfield — physics, art, lamps, VBScript that wires keys → switches and tells VPinMAME which ROM to load. Must be .vpx (Visual Pinball X), not .vpt (older VP9) or .fpt (FuturePinball). | VPUniverse or VPForums table sections — community-authored. |
Confirm the game. Williams/Bally WPC-era only (1990s).
Send the user to one of these sites (both free, one-time account):
https://vpuniverse.com/ — VPX Tables → search.https://www.vpforums.org/ — ROMs / Tables sections.Tell them what to look for.
.vpx or a .zip containing one; optional .directb2s / .altcolor / .pup can come later.congo_21.zip, tz_94h.zip). The VPX usually states which revision it's scripted against — pick that.Save in ~/Downloads (i.e. C:\Users\<user>\Downloads\). User pings back when done.
Claude extracts the .vpx from its .zip if needed and drops the files
into the game working dir by convention: ROM zip → ./orig/<rom>.zip, table →
./tables/<rom>.vpx. Then record.py --rom <rom> picks them up.
The patched DLLs ship prebuilt in lib/ and are sufficient for
day-to-day use — you only rebuild to extend them (a new export, a debugger
tweak). Rebuilding needs the patched PinMAME source: the switch-recorder
branch off github.com/vpinball/pinmame (it adds the PinmameDebug* API, the
m6809 hooks, the vp_putSwitch recorder, and the closed-loop pacing exports).
Clone it to a local directory of your choosing and point $PinmameSrc at it.
(Maintainer note: the exact clone path for this project is recorded in Claude's
project memory.)
$PinmameSrc = 'C:\path\to\your\pinmame' # your local clone of the patched branch
# Rebuild (from any PowerShell)
& 'C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\MSBuild\Current\Bin\amd64\MSBuild.exe' `
"$PinmameSrc\build\libpinmame\pinmame_shared.vcxproj" `
/p:Configuration=Release /p:Platform=x64 /m /nologo
# Copy into the plugin lib/ under the canonical loader name and re-run
# setup-pinball.py — its deploy step (re)installs the DLL into PINMAME_DIR.
Copy-Item "$PinmameSrc\build\libpinmame\Release\pinmame64.dll" `
${CLAUDE_PLUGIN_ROOT}\lib\libpinmame.dll -Force
python3 '${CLAUDE_PLUGIN_ROOT}/bin/setup-pinball.py'
If you'd rather skip the downloads/env checks entirely, the patched DLL just needs to land on top of the installed one: copy it directly over %LOCALAPPDATA%\rom-workbench\pinmame\libpinmame*.dll.
Forgetting the deploy step makes replay.py fall back to the un-patched DLL. The giveaway error is PinmameDebugAttach not found.
You need Python 3.9+ and pip on PATH. setup-pinball.py runs directly under
that interpreter and pip installs Pillow; every day-to-day tool then runs as
python3 <tool>.py. Additionally:
regsvr32 VPinMAME.dll step.xcode-select --install), git — only needed for the rare libpinmame source-build fallback (the prebuilt lib/libpinmame.dylib covers the common case). setup-pinball.py checks these only when it actually has to build.The only third-party Python dependency is Pillow (used by the DMD-render tools), installed by setup-pinball.py via pip; everything else is stdlib-only.
${CLAUDE_PLUGIN_ROOT}/
├── skills/setup/SKILL.md # this file
├── bin/
│ └── setup-pinball.py # cross-platform VP + libpinmame (+ VPinMAME on Windows) installer
└── lib/ # prebuilt patched libraries this script deploys
├── libpinmame.dylib # macOS
├── libpinmame.dll # Windows
└── VPinMAME64.dll # Windows (VPinMAME COM recorder)
npx claudepluginhub techbert08/rom-workbench --plugin rom-workbenchCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.