The Pinball Power-Up Controllers are a set of hard- and software designed to repair and enhance the capabilities of classic pinball machines of the 80s and 90s and to drive the hardware of home brew pinball machines. The project is in ongoing development. Visit the PPUC Page for further information. This directory contains the PinMAME related parts, mainly the building blocks to emulate a pinball CPU that drives PPUC I/O boards.
We want to enable people to be creative and to modernize old pinball machines using today's technology. Our goal is to establish an open and affordable platform for that. Ideally people will publish their game-specific PPUs so others could leverage and potentially improve them. We want to see a growing library of so-called Pinball Power-Ups (PPUs) and a vital homebrew pinball community.
The code in this directory and all sub-directories is licenced under GPLv3, except if a different license is mentioned in a file's header or in a sub-directory. Be aware of the fact that your own enhancements of ppuc need to be licenced under a compatible licence.
PPUC uses
These components are still in an early development stage and the documentation will grow.
- -c path
- path to config file
- required
- --ini-file path
- path to a ppuc runtime ini file
- optional
- values from dedicated command line options override values from the ini file at runtime
- -r rom name
- rom to use, overwrites rom setting in config file
- optional
- -s serial device
- serial device path to use, overwrites serialPort setting in config file
- optional
- -d
- enable debug mode, overwrites debug setting in config file
- optional
- --debug-effects
- enable effect trigger debug output
- optional
- -u
- enable Serum colorization
- optional
- -t VALUE
- Serum timeout in milliseconds to ignore unknown frames
- optional
- -p VALUE
- Serum ignore number of unknown frames
- optional
- --pup-triggers path
- path to a lightweight PUP trigger rules file
- optional
- --speech-file path
- path to a speech trigger text file used with speech trigger rules
- optional
- --music-files csv
- comma-separated MP3 playlist for gameplay background music
- plays only while the game is not in attract mode
- ducks while PinMAME or speech audio is active
- optional
- --switch-refresh-idle-ms VALUE
- re-read all IO board switches after this many milliseconds without non-button switch updates
- default:
15000 - always active; the value must be greater than zero
- --ball-search
- enable host-side ball search for coils marked
ballSearch: truein the game YAML - optional and disabled by default because newer ROMs often implement their own ball search
- enable host-side ball search for coils marked
- --ball-search-delay-ms VALUE
- first ball-search delay after no non-button switch activity while the game is running
- default:
15000
- --ball-search-round-delay-ms VALUE
- delay between complete ball-search rounds
- default:
5000
- --speech-backend value
- speech backend to use:
auto,flite,espeak-ng - optional
- speech backend to use:
- --speech-voice value
- speech voice name, mainly for
espeak-ng - optional
- speech voice name, mainly for
- --speech-rate value
- speech rate in words per minute, mainly for
espeak-ng - optional
- speech rate in words per minute, mainly for
- --speech-pitch value
- speech pitch
0-100, mainly forespeak-ng - optional
- speech pitch
- -i
- render display in console
- optional
- -h
- help
An example runtime ini file is available at examples/ppuc-pinmame.ini.
ppuc-pinmame always runs a switch-refresh safety net. If no non-button switch
update arrives for Runtime.SwitchRefreshIdleMs, the host sends a v2 switch
refresh command. IO boards re-read their switch inputs, restart their local
switch readers, and return full switch bitmaps through the normal switch chain.
The normal runtime output/switch-poll cadence is controlled by
Runtime.OutputFrameIntervalMs or --output-frame-interval-ms; the default is
4.
Switches can be marked as cabinet/player buttons in the game YAML:
switches:
-
description: 'LEFT FLIPPER BUTTON'
number: 63
board: 1
port: 17
debounce: 3
debounceMode: fastFlip
button: trueButton switch activity does not postpone switch refresh or ball search. A held button does suppress ball search, so a player can hold a ball on a raised flipper without the host firing search coils.
Host-side ball search is separate from switch refresh and is disabled by default. Enable it only for older ROMs that do not perform their own ball search:
[Runtime]
OutputFrameIntervalMs = 4
BallSearch = true
BallSearchDelayMs = 15000
BallSearchRoundDelayMs = 5000Only coils marked ballSearch: true are fired. They are pulsed one after
another with the same short pulse style as coil test, then the host waits
BallSearchRoundDelayMs before starting the next round if the machine is still
quiet.
pwmOutput:
-
description: 'Outhole Kicker'
number: 7
board: 4
port: 3
type: solenoid
ballSearch: trueUse --pup-triggers <file> to map switch/lamp/coil conditions to calls of SetPUPTrigger(source, id, value).
This trigger feature is independent from --pup, and can also drive speech callouts and board-local PPUC effects.
Rule syntax:
<source> <id-or-name> [value] [cooldown=<milliseconds>] [delay=<milliseconds>] : <expression>
Expression functions:
switch(<number>)lamp(<number>)coil(<number>)attractorattract()switch_rising(<number>)switch_falling(<number>)lamp_rising(<number>)lamp_falling(<number>)coil_rising(<number>)coil_falling(<number>)
Operators:
!&&||- parentheses
(...)
Rule options:
cooldown=<milliseconds>- suppress retriggering until the cooldown window has elapsed
delay=<milliseconds>- wait before firing after the expression matches
- for state-based expressions, the condition must still be true when the delay expires
- for edge expressions like
switch_rising(...), the matching edge arms the delayed trigger once
Example:
P 100 1 : switch_rising(13) && lamp(42)
P 101 1 cooldown=500 : switch_rising(13) && attract
P 102 1 delay=750 : switch(13) && attract
O 60010 1 : lamp_rising(23) && !attract
F cabinet-attract 1 : lamp_rising(5) && attract
A ready-to-use sample file is available at examples/pup-triggers.rules.
Speech trigger source:
O- spoken callout target
- the trigger
idis looked up in a--speech-file
F- board-local effect trigger
- forwarded to
libppucas a runtime event with sourceEVENT_SOURCE_EFFECT - use matching
trigger.source: Fplustrigger.nameortrigger.numberin the game YAML effect block
Use --speech-file <file> together with --speech and --pup-triggers to map speech trigger IDs to spoken text.
Syntax:
<trigger-id> : <text to speak>
Example:
60010: New highscore!
If a trigger rule emits source O with id 60010, the speech backend will speak that text.
Speech backends:
auto- prefer
espeak-ngwhen available, otherwiseflite
- prefer
flite- lightweight default backend
espeak-ng- second backend with broader voice/language support when staged in
third-party - default voice is now a more distinct
en-us+f3
- second backend with broader voice/language support when staged in
Examples:
--speech-backend espeak-ng --speech-voice en-us+m3--speech-backend espeak-ng --speech-rate 210 --speech-pitch 35--speech-backend flite --speech-voice kal
Ready-to-use samples are available at:
examples/flash.rulesexamples/flash.speech
platforms/win/x64/build.shplatforms/win/x86/build.shplatforms/linux/x64/build.shsudo apt install git autoconf libtool libudev-dev libpipewire-0.3-dev libwayland-dev libdecor-0-dev liburing-dev libasound2-dev libpulse-dev libaudio-dev libjack-dev libsndio-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxtst-dev libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev
git clone https://github.com/PPUC/ppuc.git
cd ppuc
platforms/linux/x64/build.sh
ppuc/ppuc-pinmame -c examples/t2.yml -n -ippuc-menu is an SDL3 selector that reads a plain-text menu file with repeated title, image, selected-image, and command fields. It uses the same speech backend options as ppuc-pinmame.
ppuc/ppuc-menu \
--menu-file examples/menu.txt \
--logo assets/ppuc-logo.png \
--slogan "Choose a machine and press Enter" \
--speech --greetingplatforms/linux/aarch64/build.shAfter building, install a per-user GNOME/XDG autostart entry with:
platforms/linux/install-gnome-autostart.sh -- -c examples/t2.yml -n -iThis writes ~/.config/autostart/ppuc-pinmame.desktop with absolute paths to the
generated launcher and starts ppuc-pinmame in a terminal window so the process
stays attached to the foreground session. Pass the same arguments you normally
use on the command line after --.
By default the installer prefers gnome-terminal, then kgx, then
x-terminal-emulator. Override that with:
platforms/linux/install-gnome-autostart.sh --terminal gnome-terminal -- -c examples/t2.yml -n -iThe installer also sets a GNOME autostart delay of 10 seconds by default so the terminal is launched after the session settles. Override that with:
platforms/linux/install-gnome-autostart.sh --delay 15 -- -c examples/t2.yml -n -iOn GNOME, the generated launcher also tries to dismiss the Activities overview a
couple of seconds after startup so the terminal and game are shown on the normal
workspace instead of remaining visible only in the workspace selector. Disable
that behavior with --no-dismiss-overview if needed.
Remove the autostart entry with:
platforms/linux/uninstall-gnome-autostart.shplatforms/macos/arm64/build.shplatforms/macos/x64/build.sh