Documentation: VPIN – build your own Virtual Pinball in a old cabinet

Für die deutsche Version bitte hier klicken: Baubericht: Projekt VPIN (Virtueller Flipper) im Eigenbau

„VPIN“ – who? what? why?…

Since I was always fascinated by ‚Arcade stuff‘ and as a 70’s child, from my first impressions with „Pong“ over the Atari VCS to C64, Amiga, Atari ST, I386 until today with current PC’s I still „follow“ the topic passionately, I thought after playing the table „MARS“ of Pinball FX2:

A rotated screen would be much better and the whole thing controlled by buttons in an old pinball case would be cool too.

After many hours in boards and search engines etc. I found out that there are so called „VPINs“, virtual pinball’s in the housing of a pinball machine… and some additional variations.

So… it started… and this documentation summarizes three stages of development (thats why you see on some pictures various hardware f.e.) and there is time (duration) of about 1.25 years the whole proccess… but let´s beginn with a small video:

Shopping list (Hardware & Parts)



Power supply/voltage/cooling

Plugs & Sockets




Surround Sound Feedback (SSF):


‚already there‘ costs (in da house):

  • Mouse & Keyboard
  • Screws, Spax…
  • Putty
  • Colours & Spray cans
  • various small stuff

A bit of theory

What is a Virtual Pinball (VPIN) and how is it with the hardware and stuff?

Briefly explained on a higher flight level is as follows:

It’s an old pinball machine cabinet, a personal computer and three monitors. It runs Windows and different pinball simulations. But there is also a lot of additional software that interfaces to microcontrollers, which act as a keyboard, sensors or control LEDs. Also additional cool things like bass-shakers or exciter are built in, which further enhance the gaming experience… and on top of that, there is a so-called „frontend“ (software) which is automatically started in windows and controls the individual simulations and their „pinball tables„.

On a virtual pinball machine theres no „one and only table“ like in a real pinball machine… but more about that later.

This documentation is a summary of two building and configuration projects (V1 & V2 Update).



Here we go… with the case

The case

The first thing I bought concerning virtual pinball was a (not virtual) old pinball case (PinBall Champ82) including coin slot, disc & siderails.

After I spent a lot of my (analog) spare time in digital boards/forums, blogs, YouTube & Co. and also various hardware stores… the first steps were roughly clear.

First of all I removed all strips and woods from the inside of the cabinet, made a hole and also a reinforcement for the subwoofer and a hole for the inspection door on the back (to get easy access to the PC later). Then I removed all the metal parts and rust (rust film) in a nice Cola bath (but without Jack Daniels) and polished or sanded them.

In my V1, I had chosen the (FullHD) Samsung UE40J6250 TV for my „playfield screen“. My pinball case has 52 cm, the TV still had about 52.6 cm „stripped“ (I left the frame at the front to „centre the front“), so the plan was to cut a groove 0.5 cm deep on each side.

In the V2 I used the PROLITE X4071UHSU-B1 (4K), which fitted in incl. case. However, the buttons (on/off etc.) are still at the bottom and protrude a little… but they are now perfectly recessed in the groove. For the monitor mount, I adapted an angle profile and covered it with good fabric tape to prevent scratches on the monitor housing.

With the help of a ‚hole cutter‘ I was able to cut the 28 mm holes for the additional pinball buttons and the 4 navigation buttons into the related plates.

I left 15 mm distance from the glass pane for the playing field, so that the air can circulate a little bit there. Then I could finally cut the groove for the playfield TV into the case (a router is really a great tool) and stabilize the whole thing afterwards with the wall mount screws.

Then I went on with the router and I worked in all the holes and grooves for the buttons and attached them in a way that they don’t ’stick out‘ with the centering ring but lie nicely against the case.

Also the case, the PC and screen inside need a circulation… so I used a jigsaw (+ file and sandpaper) to cut out the fan hole („sucking in right“ to „blowing out left“).

The illuminated buttons can be disassembled in a way that it is possible to put a sticker or your own printout in front of the button. In combination with LED’s as lighting this comes quite good. So I created a small graphic for the most important buttons (arrows left, right, up, down; ESC, Tab, Launch & Start), printed the whole thing, cut it out and this is how it looks like (see pictures on the right).

I painted all parts black matt (RAL 9005) and then I started to apply the foil. The whole thing went quite well without big air bubbles and as always with such a project it is really fun to build the whole thing together (see gallery). Also take a look a little „closer“ on the revision door in the back.

The design was quite complex… the right/left side of the pinball machine alone has about 100 layers and should be designed to work together during transitions but after 5 nights the work was done and the freshly printed adhesive foils were ‚in da house‘ round about a week later.

With the foil on the side i reccomend ‚work with two people‘, but then it works quite well… also here I cut the cutout for the fans and pulled them over the edges with a hair dryer. Afterwards I attached 10×10 mm edges (like the backbox) and then the case could finally stand on its own feet now.

Because there is a distance between the bezel and the playfield monitor I put a sticker on the top and bottom (so you can’t see inside) and a small black plastic strip on the playfield monitor which goes up to the glass pane.

What happens „electronically„, you will see a little later below.

The Backbox

As mentioned in the shopping list above, I bought a 17″ monitor and 27″ TV from Ebay and this was the basis for the layout, which also means that there is space in the backbox (the head of the pinball machine) and in the lower pinball case for the 17″ monitor which is used as a dot-matrix display. So that the dot-matrix display (DMD), in my case the DMD monitor, is adjustable in height (to fit exactly into the cutout) and is screwed to the bottom of the backbox with the appropriate stability.

For ventilation purposes I drilled a hole with a socket drill (120 to 80mm adapter) at the bottom left for the „sucking in fan“ and sawed out an exact cutout for the „blowing out 120mm fan“ with a jigsaw at the top right so that the ‚waste heat‘ can rise to the top and be dissipated and of course be supplied with fresh air from below.

At the same time I made 3 grooves (á 16 mm wide, 4,2 mm deep) with the router for the LED strips to be at ground level (more about this later). Then I had to fill, sand and paint several times.

The application of the foil went quite well and with a hairdryer I was able to bend the corners of the fan cutout… otherwise it is a very exact, tedious work because all the grooves and projections have to be cut carefully with the ‚cutter knife’…. puh…

After that I decided to put 10×10 mm aluminium strips on the edges to protect the foil in these places. The whole thing is mitred and painted black matt (RAL 9005) and fixed with a very good glue.

The last part was then the front, the so-called ‚Backglass‚… in my case rather the ‚Backwood‘ :-). After varnishing & Co. I used 2 pieces of wood to hold the Backglass 27″ Led in place, then tensioned it with a fine perforated plate (which is embedded in the wood) and foam rubber. The loudspeakers of the Wavemaster Moody system (see shopping list) were screwed on, the cable was shortened and the ‚back-wood‘ was ready.

After the complete insert was screwed on, I was able to mount the DMD monitor and finally the wooden panel.

So much for the case… of course I have tinkered with electronics & software in parallel… but more about that later.

The inside


The computer is a normal PC (see above components) which I have screwed with ‚board feet‘ on a wooden board, the PCIe cards additionally fixed with a threaded rod.

To switch everything on I decided to use a „Master-Slave power strip“. The power button of the PC (on the mainboard „Power“) i.e. the power supply is the „Master“ and the remaining components are then switched on as „Slave“.

You can switch off the whole thing via the VPIN „Frontend“ (details below) with the flipper buttons (in which the PC shuts down).

I attached the buttons under the case (white „Power“, red „Reset“, the small white „WIN Volume louder/quieter“ and the bigger knob is the volume of the Moody-Systems).

The whole thing is a „3 Screen Setup“ and I solved it like this: Monitor #1 (TV) is the playing field in portrait format, Monitor #2 is the DMD and Monitor #3 is the backglass. Contrary to the standard setup, I chose to place the monitors sideways, because I often stand in front of them and work in the WIN (install and set up new tables etc.)… I found this more practical (and besides, some bully makes the font smaller and smaller and smaller every year…)

Miscellaneous: the computer boots into WIN again, in the Bios I switched off the USB power supply (otherwise the microcontrollers are permanently on) and in the WIN some programs start by batch file/autostart but more about that later.


For my virtual pinball I use the following different setups:

  1. WS2801 LEDs with a Raspberry Pi2 (RPI) controller (to ‚project the playing field‘ downwards (like Ambilight))
  2. WS2812B LEDs with a Teensy 3.2 controller (to place colors/triggers/events from the game on the playfield & behind the backglass)
  3. RGB LEDs to illuminate the pinball & magma buttons with the appropriate color
  4. (one)colored LEDs to light up the buttons or to put events from the game, e.g. a „blinking“ on the buttons

From the power supply they are connected as follows:

  • The WS2801 LEDs are connected to the 5V power supply (see shopping list) with +5 and GND (-) and in parallel GND is connected again to RPI at pin 9, as well as „DI“ at pin 19 and „CK (Clock)“ at pin 23
  • The WS2812B LEDs on the Teensy Octo adapter (network cable) with Orange/Orange-White: Stripe #1 and
  • Blue/Blue-White: Stripe #2: The voltage (+5V and GND) is fed directly into the LED strips from the power supply unit (see pictures). Important: Re-feed +5V after 180 LEDs.
  • The monochrome and RGB buttons are connected to the pinscape controller (see pictures)… but be careful: this is „switched to ground“, meaning: there is „a plus“ (PIN 18) and the other cables (R, G, B..) are „ground“ (this experience costs me one RGB button)

I have fused everything that comes out of the 5V power supply accordingly… the whole thing can be calculated well (see pictures)… I usually split it up in a way that 2A are enough (very important for the lifetime of the LEDs, the Pinball machine… and house at least).

How I control them in the VPIN can be found at the Software / Microcontroller.

Surround Sound Feedback (SSF)

SSF does not stand for South San Francisco… no… it stands for „Surround Sound Feedback“… important here is the word „feedback“.

Simply explained: the feedback is „tangible“ through bass pumps (bass shaker/body sound transducer) and „audible“ through so-called exciters.

SSF can be used together with DOF (Direct Output Framework) and solenoid based stuff like contactors etc. or standalone. I personally operate it standalone (without contactors & Co.), find it very simple and effective… actually almost the coolest thing about my Virtual Flipper (VPIN).

But you can also visit South San Francisco… a nice spot on earth :-).

but Ok… how you procced?!

You take a 7.1 soundcard and use:

  • Front for his normal system, which is mounted in the backglass (in my case the „Moody“, which contains a subwoofer with crossover)
  • Center/subwoofer remains empty
  • Side for rear bass pumps & exciter (near backglass)
  • Rear for the bass pumps & exciter in the front (near flipper buttons)

» See sketch in the gallery.

How the speakers, exciters & bass pumps are mounted, you can see best on the photos in the gallery.

I controlled the whole thing with 2.1 power amplifiers… 4 of them, so that I can use the bass pumps at the subwoofer output. As you can also see on the pictures: L/R is disconnected at the soundcard with a „jack <> chinch“ cable, then it goes to the left or right channel of the amp and from there to the exciter (sound) and bass pump (vibration).

I recommend amps with a small tone control and separate volume for subwoofer & speaker output. Also a high quality power supply to avoid noise on the bass pumps (thus e.g. stupid vibrations).

Each power amplifier is fused with 2A. All parts can be found again in the „shopping list“ above.

For mounting the components I can only give the following advice:

  • Power supply should get a little „cooling“ (place it somewhere in the air stream)
  • The bass pumps should not necessarily be placed next to electronically critical components
  • Place the amps so that you can easily „readjust“ the sound

I’ve been asked several times… but that has no influence on the „nudging“ (tilt & co), because my pinscape controller (on which the sensor is sitting) is mounted on a board in the middle of the cab.

It is remarkable in any case, when in the „virtual game“ the pinball flippers, slingshots & bumpers are triggered and you can hear and feel it on the case!

Even if the ball rolls or bounces against wood, plastic or metal… you can feel and hear that… a super great „feedback“… I can only recommend it!

How to set up and configure all this, you can see under „Software„.

The Microcontroller

Raspberry Pi

My Raspberry Pi 2 I use in combination with OpenElec, WS2801 LED´s and Hyperion to project the edge of the „playfield“ down on the floor.

How I solved this exactly, you can find a bit more detailed on this page: Self-built ambilight with Raspberry PI

  • Number of LEDs left/right: 12 each
  • Number of LEDs front/rear: 32 each

HyperCon Settings:

HyperCon Config - General
HyperCon Config - Process
HyperCon Config - Grabber
VPIN: Rapsberry Pi WS2801 LEDs

VPIN: Rapsberry Pi WS2801 LEDs

Example video (old version… at that time with Ambilight also on the backglass):

Pinscape KL25Z

The Pinscape KL25Z is one of the core pieces in my virtual pinball machine / VPIN, the whole thing is OpenSource (Webseite) which I find additionally a very good thing.

I use the Pinscape incl. the mainboard (extension board) for:

  • my buttons (click button)
  • the control of the lighting of the Start / launch ball button and the 4 RGB flipper buttons
  • the „nudging“ (sensor) – i.e. influencing the pinball machine by shocks
  • the analog „plunger“


For the (arcade) buttons I designed some icons, printed them with the inkjet printer, cut them out and put them between the button & plate… the effect: buttons with illuminated symbols (see pictures).

I connected the following buttons to the pinscape:

  • blue top – key: „E
    • Frontend: Cancel/Escape/Exit Game
    • Visual Pinball: –
    • Pinball FX: –
  • blue middle- key: „ESC
    • Frontend: –
    • Visual Pinball: –
    • Pinball FX: Menu
  • blue bottom – key: „Tab
    • Frontend: Info
    • Visual Pinball: –
    • Pinball FX: Tab in Menu
  • Left, Right, Up, Down
    • Arrow keys on the keyboard… to navigate through the menus in Pinball FX
  • Money ejection – key: „3
    • Frontend: Coin1
    • Visual Pinball: Add credit
    • Pinball FX: camera(view angle)
  • red top – key: „Enter
    • Frontend: Select/Enter
    • Visual Pinball: Plunger
    • Pinball FX: Plunger/Enter(Menu)
  • red middle – key: „S
    • Frontend: Launch
    • Visual Pinball: Start Game
    • Pinball FX: Wizard-Power
  • Flipper left – key: „Shift L
    • Frontend: back
    • Visual Pinball: Flipper L
    • Pinball FX: Flipper L
  • Magnasave left – key: „Ctrl L
    • Frontend: page back
    • Visual Pinball: Magnasave L/Nudge L
    • Pinball FX: Nudge L*
  • Flipper right – key: „Shift R
    • Frontend: next
    • Visual Pinball: Flipper R
    • Pinball FX: Flipper R
  • Magnasave right – key: „Ctrl R
    • Frontend: next page
    • Visual Pinball: Magnasave R/Nudge R
    • Pinball FX: Nudge R*

*Note: the Magnasave keys are mapped to the „L / R“ keys in Pinball FX… and in DOFlinx Config (see below) then mapped to „Nudge L/R via “ Ctrl L & R“.

  • Vol up (WIN Volume +)
  • Vol down (WIN Volume -)

Outputs (lighting control)

I’m taking advantage of the outputs of the Pinscape:

  • set the RGB Flipper & Magnasave buttons to the corresponding color
  • at the Launch Ball / Start Buttons (Select/Enter or Start Game – see Buttons) to let the LED light up or pulsate

Use case is like: I can illuminate the pinball buttons with the original colors of the real tables and control interaction (e.g. if money is thrown into Visual Pinball + credits are enough there, then the „Start Game“ button pulsates) from within the game or frontend.

  • Output 50-52 (RGB): Flipper right
  • Output 53-55 (RGB): Flipper left
  • Output 56-58 (RGB): Magmasave right
  • Output 59-61 (RGB): Magmasave left
  • Output 62: Launch Ball
  • Output 65: Start Game

PIN-assignment at the pinscape you can see in the pictures on the right. The whole thing is also entered in the DOF-Config-Tool so if DOF support is available (in the game/frontend…), the corresponding color/action for the corresponding table is stored.

More about DOF (direct output framework) further down in the category „Software„.



Nudging (synonymous with stimulating, directing, shaping) is a behavioural economics method that attempts to influence people’s behaviour in a predictable way… at „pinball“ it means: to influence the ball with mechanical action (by bumping, shaking) on the cabinet „.

Our playing field is „digital“ and the cabinet is „analog“… in this case, the acceleration sensor of the pinscape controller creates the bridge.

And I have to say: it’s pretty cool if you shake the pinball cabinet and the ball or even elements on the playfield are moving / influenced.

How exactly… you can see below at Software (Visual Pinball, DOFLinx…).. at Pinscape I set the dynamic of the sensor to  +/- 1G and the centering to „Auto-Center“.

My Pinscape is installed so that the USB ports are pointing to the back.


With the plunger (piston) it behaves like above with the „nudgen“… we have a „real plunger“ for a „digital playing field“. Some pinball tables (like Terminator 2) also have a „launch button“… I use the button from above (Launch Ball).

You can also solve it in such a way that if you hold this button longer, it „winds up“ the plunger…. but its:

  • „fiddly“, because you have to release it at the right time, e.g. to make a skillshot
  • not so cool…

It’s amazing and much more „play friendly“ if you pull the (real analog) plunger and then the plunger is moved to the same position on the digital playfield (incl. corrections).

Short and simple explained: the plunger via Pinscape works like a joystick with the corresponding axis.

I have installed a potentiometer (poti) with a resistance of 10 kOhm and a sliding distance of 100 mm.
The potentiometer is connected with 3 cables to the corresponding PINs (see pictures). The potentiometer is attached to the plunger by means of a 3D print holder and calibrated in the Pinscape software.

I would also like to refer to the very good documentation from MJR (details about the plunger).

How this is set up in Visual Pinball and what else is to be done in Pinball FX3 can be found below under „Software“.

Teensy 3.2

The Teensy (which I soldered on a Teensy Octo board) takes control of (WS2812B) LEDs on the Playfield and Backglass triggered from the game/frontend.

The most people use LEDs in the playfield, under the pinball „undercab“… a little bit different than myself. Since in my case „undercab“ is done by the Raspberry (which I like more, because there is a little „movement of the real game“) I have the following setup:

In total there are 405 LEDs distributed over:

Stripe #1 (RJ45 cable – Orange/Orange-white)

  • Playfield right: 126
  • Playfield back: 69
  • Playfield left: 126

Stripe #2 (RJ45 cable – Blue/Blue-white)

  • Backbox left: 28
  • Backbox top: 28
  • Backbox right: 28

So I use „RGB Undercab Complex MX“ for my backbox left/right… this has the effect: the back in the corresponding table color / pinball table LED animation illuminates the room… and I use „Playfield back“ parallel on the „Backbox top stripe“, which has the effect, if e.g. the stroboscope on the playing field of a pinball table is turned on, the room also joins in for a short time (looks very cool to my taste).

Flashed is the Teensy via Arduino with the „OctoWS2811Ext.h“ (see pictures).

Every power supply is fused with 2A (with my use-case / my number of LEDs)… I have calculated as follows:

132 Led’s are about 7,92A, 25% of it = ~2A

I have fed in (+5V) at:

  • Playfield right + back (195 LEDs)
    Playfield left (126 LEDs)
    Backbox left, top, right (84 LEDs)

The Cabinet.xml:


This describes, let’s say: the structure of your LED arrangement (number of strips, name, number of LEDs, LED number, colors, output, output grouping etc.)… see pictures.

My LEDs are mounted in a strip on the playing field and covered with mirror foil, in the backbox the LEDs are embedded in the corresponding groove.

As with the „outputs“ above, the corresponding „ports“ must be entered in the DOF-Config-Tool, so that the „triggers of the game“ can control the corresponding LED effects á pinball table (see pictures).

Relevant here is the „directoutputconfig30.ini“… but more about „DOF“ and the corresponding settings below at „Software„.


Hint: where I easily wasted 3 days „trouble shooting“: plug the network cable „RJ45“ into the correct port (Port1 = Stripe 1-4, Port2 = Stripe 5-8) on the Teensy 😉


Minimum 50% of my project time was spent on software.

The software chapter is pretty much the biggest and most elaborate, at least the way I use the VPIN. That’s why I’ll go into a few things here, but not in all depth (the individual documentation of the programs gives a lot of very helpfull information).

In summary, the whole thing is a WIN10 (Pro, because of remote desktop functionality) computer, which activates a master/slave power strip when the „Power Switch“ (mainboard) is turned on by a button at the bottom of the cabinet. The computer boots up and supplies the devices connected via USB and computer power supply (Pinscape, Teensy…) and the master/slave power strip then supplies the rest (RPI, 5V & 13.8V power supply, monitors, TV…)

In Windows, the user is automatically logged in, a batch file and the autostart will start programs like „PinballY, DOFLinx, PinUPPlayer, PINvol, PinSoundStudio… “ are started.

As soon as the frontend (in my case PinballY) is started, everything can be controlled comfortably via the Buttons.


Here´s a rough ratio of the effort::

@echo off
cd c:\DirectOutput
start /min DOFLinx.exe

cd C:\PinUPSystem\PinUPPlayer
start /min PinUpPlayer.exe

cd C:\PinballY\
start PinballY Admin Mode.exe

cd C:\PinSoundStudio\PinSoundStudio-09\
start PinSoundStudio.exe /minimized

Project phase

Effort distribution Mechanical/Technical/Software during the project phase

0% Mechanical effort
(wood, metal, etc)
0% Electrical effort
(soldering, wiring, etc.)
0% Software
(Operating System - Frontend)

Regular operation

Effort distribution in regular operation (software)

0% Fine tuning (general)
(Optimizations, Addons, Scripts ...)
0% Frontend
(Design, Videos, Audio)
0% Tables
(Installation, Configuration, SSF)

Share of effort: Software (during the project phase)

Information 35%
Research, documentation...
OS 5%
Configuration 10%
Hardware, Configs, INIs, ...
Frontend 10%
PinballY, PUPplayer
VPX/FX3 5%
Games, Settings...
DOF/DOFLinx 10%
Addons 15%
PINsound, PINvol, Altsound, Scripting...

I’m not gonna start with how to install a WIN10… also the „automatic login“ is easy to find on the net.

I start from the „Games“ over the interaction of „Gimmicks“ and necessary „Tools“ up to the „Frontend“.

Visual Pinball

Visual Pinball

Visual Pinball is a freeware video game engine for pinball tables and in combination with Visual PinMAME it is able to emulate the ROMs from the (real) pinball machines and with the B2S Backglass Server (Plugin) it is able to emulate another Backglass. The tables roughly consist of two parts: the playing field design and a script which controls the gameplay.

Attention: VPX (Visual Pinball 10) is not a „Plug & Play like thing“… i.e. if you are not ready to go a little bit deeper and cannot edit an INI file, you are wrong here… but the other way round you are probably here for this reason (descend into the depth etc.).

I would start with the:

VPX 10.6 All-in-one Installer (or current Beta …).

  • Install VPX6Setup.exe
  • in c:\Visual Pinball
  • Select DMD-EXT
  • and further (DirectX, .Net etc)
  • and for the 3-monitor setup I installed B2S (direct backglass)
  • let vpinballx.exe still run as „Admin

Unpack the latest SAM build (3.3 Beta) and overwrite the following folder: c:\Visual Pinball\VPinMAME\, then run the Setup.exe and install Freezys DMD Extentions (Freezys DLL) for a nice DMD (see Install Instructions on the page).

Also in the meantime I can highly recommend FlexDMD (in combination with Freezy’s DLLs)…. in short: floats, looks great… and even adds value by supporting PinballY… more about this at the features and the (relatively easy) installation on the git page.

A tip on how to make sure that the DMD is in the right place on all tables and what exactly the pixel position is you can find below at tools.

Btw „about settings“ » here is my DmdDevice.ini:


; how to downscale SEGA 192x64 pixel games to smaller displays: fit, fill or stretch
resize = fit

; flips the image horizontally
fliphorizontally = false

; flips the image vertically
flipvertically = false

; enable or disable frame-by-frame colorization (inactive in VPX bundle)
colorize = true

; a DMD that renders with nice dots on a computer monitor
enabled = true

; virtual dmd stays on top of all other windows
stayontop = false

; hide the resize grip
hidegrip = false

; x-axis of the window position
left = -3

; y-axis of the window position
top = -936

; width of the dmd in monitor pixels
width = 1296

; height of the dmd in monitor pixels
height = 324


; if false, doesn't bother looking for a pinDMD1
enabled = false


; if false, doesn't bother looking for a pinDMD2
enabled = false


; if false, doesn't bother looking for a pinDMD3
enabled = false

; COM port, e.g. COM3
port =


; if false, doesn't bother looking for a PIN2DMD
enabled = false

; if enabled, writes frames to an .avi file
enabled = false

; path to folder or .avi file. if folder, gamename.avi is used.
path =


The B2S Backglass Server should be located in c:\Visual Pinball\Tables\… in case this doesn’t work:

  • B2SBackglassServer.dll “ right mouse button “ Tab: General » Allow“
  • B2SBackglassServerRegisterApp.exe “ right mouse button “ run as administrator“

What I have set up in VPX, you can find in the gallery.

Install tables in Visual Pinball

Basically you need (until e.g. on tables that are made ‚only in VPX‘ or in combination with the PUPPlayer) the table itself, the backglass and the Rom

  • tablename.vpx » c:\Visual Pinball\Tables
  • tablename.directb2s » c:\Visual Pinball\Tables
  • » c:\Visual Pinball\Tables\VPinMAME\roms\

Note: I always use the following logic for table name:

  • Name (Brand Year)
  • Attack From Mars (Bally 1995)

So no table name V.0815.vpx etc… because that’s also the way the filing structure of my media is in the Frontend.

Alternatively you can replace the sound with Altsound or PinSound, as well as install so-called PUPPacks… but more about that later.

Sources for tables & ROMs:,,,, Google.

Fine tuning:

Since I have a Sourround Sound Feedback (SSF) setting, I optimize almost every table… I basically always replace

  • Bumper-Sounds
  • Flipper-up / Flipper-down
  • Slingshots

in the sound manager (see pictures) and position the sounds accordingly (front/rear, left/right), and depending on the table, change the output of backglass/table (e.g. collide, plunger-pull, knocker to the „BG“).

If you like, you are welcome to try my sounds… here for download:

fR33Styler´s SSF Sounds
Table position

From VPX you can start the positioning of the table with „F6„… and then use the Flipper & Magnasave buttons to adjust angle, size and position as well as lighting etc.


In the game with „F1“ you can go to the „Options“ and set there e.g. Cabinet-Mode and external DMD (see „FlexDMD„).

Color ROM (DMD with color)

To „colorize“ the ROM there are 2 possibilities: Altcolor (colorize via Pin2DMD) & patch a ROM (Stern ROMs)

How to proceed for Altcolor:

Requirement: Freezy’s DMD Extentions and my recommendation FlexDMD (check #VPX)

  • Create folder: c:\Visual Pinball\vpinmame\altcolor\(rom-name)
  • copy files pin2dmd.pal & Pin2DMD.vni into this folder
  • Press F1 in the game, there (of course „Use external DMD (dll)“ activated) then select „Colorize DMD (4 colors)“ (see pictures on the right)
  • Restart the table and ‚be colorful‘ 😉

How to patch ROMs:

Prerequisite: Freezy’s DMD Extentions and my recommendation FlexDMD also applies here (check this at #VPX)

  • reate folder: c:\Visual Pinball\vpinmame\altcolor\(rom-name)
  • copy file pin2dmd.pal into this folder
  • bspatch
    • download, unzip
    • right mouse button and select „Allow“… and in case of compatibility „run as admin“.
    • start DOS Window (execute (WIN+R) » „cmd“)
    • navigate to the folder of the files (z.B. c: … cd ABC …)
    • then patch the ROM (i.e. the original ROM (.bin), the patch file (.diff) should then also be in that folder)
    • Parameters are: bspatch original-rom.bin new-color-rom.bin patch.diff
      • means for AC/CD as an example: bspatch ACD170LE.bin acd_170hc.bin acd_170hc_ByPinballMikeD.diff
  • the new ROM then packs (with 7zip / Winrar) e.g. under the name
  • store the ROM (.zip) in the following folder c:\Visual Pinball\vpinmame\roms\
  • in the table script then enter the name of the new ROM at „cGameName“
  • Press F1 in the game, there (of course „Use external DMD (dll)“ activated) then select „Colorize DMD (4 colors)“ (see pictures on the right)
  • Restart the table and ‚be colorful‘ 😉

Important: the selected ROM name MUST be present in the VPinMame database, otherwise it will not work.

Good sources for: Pin2DMD Colorizations & Color ROM Patches also 296 AltColor Color Pallettes (for colouring only).


Important here: if you have an „altsound“ (alternative soundpack), you have to select „Alt. Sound Mode„, you have to set a „1„, the soundpack in exactly the same name as the Rom: c:\Visual Pinball\Tables\VPinMAME\altsound\(rom-name) speichern.

A good source for altsounds:

I adjust the volume inside the tables with „PINvol„… but more about that below.


What I also do is sometimes use optimized scripts…from Fastflips to SSF optimizations. You don’t have to replace the „original script“… it’s enough if you name the script the same way as tablename.vpx or .directb2s (as above) and copy it into the folder c:\Visual Pinball\Tables\ .

Check out the repo of „sverrewl„: vpxtable_scripts, I think there are some good ones and in the comments you can read what has been optimized.



PinSound actually stands for Soundboards, which gives the pinball machines of yesterday a higher sound quality.

But there is also a software called „PinSound Studio Pro“ which allows you to edit and adjust sounds etc. Unfortunately after version 0.9 the focus is only on „editing“.

Until version „PinSound Studio 0.9“ it was possible to assign a PinSound-Soundpack to a VPINMame-Rom (see pictures)… and what happened: when the game starts, the sounds from the pack are used instead of the original/old rom sounds.



  • Install PinSound Studio 0.9
  • Unpack the Soundpack into the corresponding folder under PinSound Studio 0.9
  • In PinSound Studio 0.9 assign ROM <> Make Soundpack
  • In VPX, enter a „2“ in the „Options“ (F1 key) under „Sound mode
  • Restart the table and have fun

Important: VPX and PinSound Studio must be running in admin mode.

That sounds pretty damn good… I can really recommend to try the Terminator 2 or the Doctor Who Rush Pack.

You can find some packs here in the PinSound Community: Downloads

Pinball FX3

Pinball FX3

Pinball FX3 is actually the easiest to set up. It won’t be so easy to get the „toys“ (Leds, SSF..) running later, but more about  DOFLinx later.

You install the game via Steam, buy the tables (best in a Steam-Sale) you want to play… then you ask for the cabinet code (takes 2-3 days) and with this code you can put the DMD on a separate screen (see pictures).

Note: how to find out the best pixel position for your DMD can be found under tools.

In the audio settings I have taken back certain things like the game mechanics and adjusted the whole thing in relation to PINvol, VPX, as well as frontend (PinballY)… so that the ‚volume jumps‚ are not too violent, but also the surround sound feedback over the PUPpack is balanced (slingshots, bumpers, pinballers etc. are given directly to the bass pumps and exciters and the game mechanics are added discreetly over the backglass of Pinball FX3 „on top“.

More about „fR33Styler´s Pinball FX3 SSF PUP-Pack“ and DOFLinx/PUPplayer below.

Direct Output Framework (DOF)

DOF (direct output framework)

DOF is a software that allows to control feedback devices. It is a kind of „add-on“ that works together with Visual Pinball and other software.
DOF takes care of the communication between the pinball software and the output controllers (LedWiz, PacLed, SainSmart relay boards, Pinscape and more) and translates between the simulated game elements of VPX and the physical device connectors of the output controller.

So… driving LEDs, strobe, shaker motor, fan, solenoids, knocker, bell(game) etc.

DOF: Download

The following microcontrollers are automatically recognized by DOF: Pinscape, LedWiz, and Pac-Led.

It is important to install DOF after VPX and B2S… and preferably in the folder: C:\DirectOutput

  • Unpacking in C:\DirectOutput
  • release all new DLL and EXE files
    • right mouse button on the file
    • Properties from the menu
    • General“ tab
    • „Security: This file is from another computer and could be blocked to protect this computer“
    • Click on the „Allow“ button
  • Create a shortcut of C:\DirectOutput in the folder c:\Visual Pinball\Plugins\

Now for testing purposes load a VPX table containing an interactive backglass (the topic from above with the .directb2s backglass files) and test it.

Press the right mouse button on the backglass in the game, then click on „Plugin Settings“ and you should see „DirectOutput“ running as plugin:

VPIN: DOF Plugin

VPIN: DOF Plugin


More about DOF is also explained quite well at MJR´s website.

DOF Config Tool

DOF loads the Cabinet.xml (see above)… and this is also the basis for controlling the LEDs.
Now we need the „bridge“: VPX -> Trigger -> what should the LEDs do -> …

You create an account and log into the DOF Config Tool:

Output devices:

In the navigation bar under „My Account“ you can enter how many output devices you have. If you use a pinscape controller, set the „Number of pinscape devices“ to 1 and leave the „Number of FRDM-KL25Z devices“ at 0… then save with „Save Settings„.

Port assignments:

Navigate to the „Port Assignments“ in the navigation, here you make the mappings between „output port numbers“ and „specific devices“.

At the moment I have „only LEDs“… and as described above with the Outputs I have my 4 RGB pinball buttons, Start- & Launch-Button… which is very much like you see in the picture on the right… responsible for the pinscape outputs is the „directoutputconfigini51„.
Note: the outputs are set to the same „numbers“ in the DOF Config Tool as in the Pinscape above. 😉

The LED stripes are similar. Above in the Cabinet.xml or under Teensy you can see my distribution of the Stripes or from which LED address on what starts… that’s exactly the same here… responsible for Teensy & the Stripes is the „directoutputconfigini30„.

For both: each channel in RGB-stuff uses one port (see pictures).



DOFLinx is the bridge for Pinball FX3/Future Pinball and hardware… in the end: LEDs and SSF (in combination with the PUPPlayer) and is based on Direct-Output-Framework.

And it’s damn fun to play Pinball FX3 with SSF & LEDs.

DOFLinx to the: Download

Wichtig ist DOFLinx im DOF-Ordner zu installieren (C:\DirectOutput)

  • Unpacking in C:\DirectOutput
  • Customize DOFLinx.INI
  • Check path specifications in the INI

I start DOFLinx with the above mentioned autostart (see #Software) and here is my DOFLinx.ini on the right (open it) to view and download.

To start, I can only recommend:


and see what DOFLinx is up to… you can quickly see if the triggers are read by Pinball FX3 etc.

What else did I do specifically in the INI?

I deactivated the joystick „Plunger Settings„and „Nudge Settings„, because I realize this meanwhile in Pinball FX3 with X360ce (see below).

The Flipper-Buttons are assigned to the corresponding Output [DeviceNo.] [Port] (150,153)… and the Start-Button (162) and the Launch Ball- & Fire-Button (165).

This creates the following: in Pinball FX3 the flipper buttons are illuminated according to the defined color of the table, the buttons flash depending on the action.

Keyboard key codes can be found here:

Read more about „Surround-Sound-Feedback @ Pinball FX3“ and „fR33Stylers-Pinball-FX3-SSF-PUP-Pack“ below.



#							#
# DOFLinx.ini by fR33Styler	#
#							#	

# The config file for DOFLinx with most common settings as a sample
# Note - this works with LEDWiz, PacLed64, Pinscape, Ultimate I/O and Sainsmart (FTDI devices)
# Edit this file as you see fit, lines that start with a hash (#) or are blank are not processed.  This blurb and comments can be cut out if you want.
# Output devices outputs are entered in the format of
# device (D) and output number (#) in the format D##, so controller device 1 and output 3 is "103" without the quotes, controller board 2 output 23 is "223" without quotes
# The keyboard hex code for the key that is used for each flipper from


# Point to your directoutputconfig.ini file.  Your file may have a number, ie directoutputconfig20.ini
# You can point to any of your directoutputconfig.ini files, but only one
# Keep this as the first pararameter to process in your INI file.  The order past ths point is not relevant


# The location of the .FX2/3 game specific files included with the DOFLinx release package
# Ensure your path has a \ on the end of it

# The path to where you keep all of the .directb2s files that you've downloaded for use with FX3
# Ensure your path has a \ on the end of it

# This is the folder where B2SServer.exe can be found on your system
PATH_B2S_SERVER=C:\Visual Pinball\Tables\

# This is the path to where your B2SServer GlobalConfig is located. Needed for addressable led effects.

# The list of processes that can activate DOFLinx, in this case, Pinball FX2, Pinball FX3 and Future Pinball
PROCESSES=Pinball FX2,Pinball FX3,Future Pinball

# An over-ride to the default setting given this is just being used with Pinball FX3, not FX2, FP or other systems that may require the default delay

# Joystick Nudge Settings with keycodes
# Doku:
# Keys:
# 4C = "L", 52 = "R"



# L & R



# Joystick Plunger Settings
# Doku: Alternativ X360CE:

# use default MX displays for Pinball FX2, Pinball FX3 
# the five flashers, flippers, slingshots, bumpers, strobe and beacon

# Set to 1 to output the game name to the log regardless of the DEBUG flag setting.  Set to 0 to simply follow the DEBUG flag.
# Quite useful when you trying to get the FX3 window game name for setting game specific colours, matching B2S names, etc

# Future Pinball Link-Section (for Pinball FX too)

######## DEVICES and PORTS for FUTURE PINBALL and FX3 ########

# LINK_XX=D##,Default Time,Max Time,Intensity Level
# Intensity Level should normally be left at 255 (max). Only PWM outputs used with something like a Shaker Motor can be less than 255.

# Device and Ports for the 10 solenoid setup for Flippers, Slingshots, Middle 3 solenoids, Back 3 Solenoids.

# Device and Ports for the shaker, gear motor, knocker, beacon and strobe

# Device and Ports for the lights inside the various buttons including Start, Extra Ball, Coin, Exit, Launch Ball and Fire

# Device and "RED" ports for the 5 RGB flashers.

# Just in case things go wrong (ie no keyup signal is detected, flipper held down for a long time), what is the maximum time a flipper solenoid / contactor can be in in milliseconds

# Turn on the attempt to make a full connection to Future Pinball when it is detected as running

# Set the key code for the keys being used as Left and Right flippers
# Used for the default fll back if a full link cannot be established
# Left Shift = A0, Right Shift = A1

# The device / port for the left and right flippers, set to output device 1, left flipper solenoid on port 1 and right flipper solenoid on port 2

# Link_[DeviceNo.][Port]

# -LIGHTING SECTION--------------------------------------------------------------------------------------------------------------

######### RGB UNDERCAB LIGHTING #########

# RGB Undercabinet Colour Change. RAINBOW = cycle through the colours. RANDOM = use random colour order. RAINBOW_ALTERNATE = hat picks Colour# and Colour#+1 then applies them to alternate RGB devices

# What changes the RGB undercabinet colour. TIME = set time period. FLIPPER = flipper press after the RGB_TRIGGER minimum time (to stop rapid colour changes)

# The minimum time for change between flipper flips, 1000mS or 1 second

# The Device and "RED" port for RGB undercabinet lighting

######### BUTTONS #########

# These are the default and "fallback" type of functions that are used when DOFLinx is made active, but no link to Future Pinball or FX3 is established. 
# Turn on Button lights when DOFLinx is activated (such as EXIT button) - but "mono" Buttons only (no RGB)

######### RGB BUTTONS #########

#Magnasave/Nudging buttons
#56 Rechts
#59 Links

#LINK_P2=218 then use BUTTONS_ON_COLOUR=BUT_P2,Blue


#Nudging (ctrl) makes Magnasave/Nudging RGB Button-Color = red

# -Testing Area--------------------------------------------------------------------------------------------------------------
######## KEY TO OUTPUT / COLOUR, etc examples ########

# Make the "4" key (key code 34) to pulse controller/output 119


# Set the left and right control keys to turn on a specific colour (red) for RGB.
# Example, when nudge keys are used it all goes red.

#LF = Left flipper
#RF = Right flipper
#LS = Left slingshot
#RS= Right slingshot
#ML = Mid field left solenoid
#MC = Mid field centre solenoid
#MR = Mid field right solenoid
#BL = Back left solenoid
#BC = Back centre solenoid
#BR = Back right solenoid
#SH = Shaker motor
#GR = Gear motor
#KN = Knocker
#FN = Fan
#BE = Bell
#C1 = Chime 1 (high note)
#C2 = Chime 2 (mid note)
#C3 = Chime 3 (low note)

# Devices
#FLOL = Flasher outer left
#FLIL = Flasher Inner Left
#FLCN = Flasher Centre
#FLOR = Flasher Outer Right
#FLIR = Flasher Inner Right

# The other 8 solenoid of a 10 solenoid setup using ports 4 to 11 inclusive

# Ports for the shaker, gear motor, knocker, beacon and strobe using ports 12 - 16 inclusive

# Ports for the lights inside the various buttons being Start, Extra Ball, Coin, Exit, Launch Ball and Fire for ports 17 to 22 inclusive

#ST = Start button
#EB = Extra Ball button
#EX = Exit button
#CN = Coin button
#LB = Launch Ball button
#FR = Fire Button
#P1 = Player 1
#P2 = Player 2
#PS = Pause

# -End of Testing Area--------------------------------------------------------------------------------------------------------------

######## GAME COLOURS ########
# Game specific colours in the format of a CSV of Game Name,Colour#1,Colour#2 - colours as they appear in your directoutputconfig
# Thanks to Vizzini here is a great starting list for Pinball FX2
# Extended for FX3 games by DDH69

GAME_COLOUR=TheInfinity Gauntlet,Dark_Red,Blue,Gold,Dark_Violet,Orange,Dodger_Blue,Lime


Pinup Player

The Pinup Player is part of the PinUP system, which also includes another frontend called Pinup Popper.

I only use the Pinup Player to load so-called PuP-Packs (Pinup Player Packs) . in combination with Visual Pinball X these are e.g. videos & sounds which are displayed on DMD or backglass in the game, with Pinball FX3 I use this mainly for surround sound feedback.

Pinup Player: Install Guide & Download

I recommend the following path: (C:\PinUPSystem\)

  • Installation
  • Setting up the monitors

Since I have a portrait screen setup, and also use PinballY as frontend… there is relatively little setup (see INI).

You can now simply go to the folder „C:\PinUPSystem\PinUPPlayer\PUPVideos“ for:

Alternatively, you can also customize it with the PUP Pack Editor.




fR33Styler´s Pinball FX3 SSF PUP Pack

fR33Styler´s Pinball FX3 SSF PUP Pack
fR33Styler´s Pinball FX3 SSF PUP Pack

Here you can download my SSF (Surrond Sound Feedback) Pinup Player Sound Pack for Pinball FX3 and DOFLinx

Simply unpack it: C:\PinUPSystem\PinUPPlayer\PUPVideos\

Enjoy it.

It is recommended to turn down the volume of the game mechanics in Pinball FX3 a bit… (see  PinballFX3).. but the best way is „play and try“.





SetDMD is a tool with which you can set your DMD position and a few more parameters in the DMD for all installed ROMs in the system at once.




X360ce is very powerful, but I use it to control the plunger with my pinscape controller and the analog plunger (poti) and the nudging in Pinball FX3.

Pinball FX3 is a bit ‚arcade-heavy’… so you can control the plunger and nudging with a joystick (e.g. on X-Box/PC…)… X360ce is the bridge and makes this possible with the Pinscape.

  • copy x360ce.exe into C:\Steam\teamapps\common\Pinball FX3\
  • execute
  • adjust
    • for details see picture on the right, important are the „sliders & settings“ on the pictures
  • left stick: test Y- & X-axis
  • right stick: test Y-axis
  • save

So a „xinput1_3.dll“ should be generated… then check in Pinball FX3 in the settings at ‚controller‘ briefly whether the controller fits.

As „tunning“ you can adjust the two values (see pictures) in the generated ini-file to -195 (or any value in between, of course)… this changes the nudge effect.



pbfx2dotmatrix is a tool with which you can find out your DMD pixel position and DMD pixel size very easily and comfortably. Helpful for all INI files and settings… just position the window where you want it to be and drag it as big as you want it to be… done.


VPIN pbfx2dotmatrix



PinVol is an open source program that adjusts the audio volume control on pinball tables to compensate for volume differences. In principle, the volume is stored for „each table“ (individually adjustable) and loaded when the table is played.

Super helpful to adjust the different volume levels of old/new tables… Soundpacks/ROMs etc.



PinballY (Frontend)

PinballY is a game browser and starting program for the VPIN in arcade look. I operate the complete pinball machine starting with overview, over videos up to the game start and end.

PinballY has an excellent documentation and is completely „open-source“… the download can be found here:

Again, I recommend:

Installation on „C:\PinballY

You can see some of the settings in the gallery. In the folder „Scripts“ you can put a „main.js“ with your own java-scripts… you can find the content of mine on the right.


Author: MJR – Link


// Check for a new version of PinballY on each launch (default is false to limit the load on PinballY's servers)
let checkPinballYUpdate = false;

// Check for new release of PinballY (taken from
if (checkPinballYUpdate) {
let request = new HttpRequest();"GET", "", true);
request.send().then(reply =>
if (/^(\d\d)-(\d\d)-(\d\d\d\d) \(\d+\.\d+\.\d+ .+\)$/mi.test(reply))
let mm = +RegExp.$1 - 1, dd = +RegExp.$2, yyyy = +RegExp.$3;
let onlineDate = new Date(Date.UTC(yyyy, mm, dd));
if (onlineDate > systemInfo.version.buildDate)
mainWindow.statusLines.upper.add("A new version of PinballY is available!");
}).catch(error => {
"The Javascript version update checker ran into a problem!\nJavascript error: %s\nStack:\n%s",
error.message, error.stack);

// For debugging purposes
function getMethods(obj) {
var result = [];
for (var id in obj) {
try {
result.push(id + ": " + obj[id].toString() + " / frozen=" + Object.isFrozen(obj[id]) + " / sealed=" + Object.isSealed(obj[id]) + " / type=" + typeof(obj[id]));
} catch (err) {
result.push(id + ": inaccessible");
return result;

Number.prototype.toHHMMSS = function () {
var sec_num = this;
var hours = Math.floor(sec_num / 3600);
var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
var seconds = sec_num - (hours * 3600) - (minutes * 60);
if (hours < 10) {hours = "0"+hours;}
if (minutes < 10) {minutes = "0"+minutes;}
if (seconds < 10) {seconds = "0"+seconds;}
return hours+':'+minutes+':'+seconds;

Number.prototype.toDDHHMMSS = function () {
var sec_num = this;
var days = Math.floor(sec_num / 86400);
var hours = Math.floor((sec_num - (days * 86400))/ 3600);
var minutes = Math.floor((sec_num - (days * 86400) - (hours * 3600)) / 60);
var seconds = sec_num - (days * 86400) - (hours * 3600) - (minutes * 60);
if (hours < 10) {hours = "0"+hours;}
if (minutes < 10) {minutes = "0"+minutes;}
if (seconds < 10) {seconds = "0"+seconds;}
return days+"d "+hours+':'+minutes+':'+seconds;

Author: vbousquet – Link

Animation and extention: fR33Styler

Details: The table name, logo animation, game statistics, HighScore are displayed in PinballY in the DMD according to the table in combination with flexdmd and the following entry in DMDdevices.ini:

virtualdmd left = 358
virtualdmd top = -369
virtualdmd width = 703
virtualdmd height = 337

Code (modified) see also download of main.js regarding subfolders & logo animations:

// Handle DMD updates
let dmd = null;
let udmd = null;
let hiscores = {};
let info = null;
let shownInfo = null;
let loopCount = 0;
let fso = createAutomationObject("Scripting.FileSystemObject");
let updater;
let manufacturers = {
	"Aliens vs Pinball": ["./Scripts/dmds/manufacturers/Aliens vs Pinball.gif"],
	"Alvin G.": ["./Scripts/dmds/manufacturers/Alvin G..gif"],
	"Bally": ["./Scripts/dmds/manufacturers/bally.gif"],
	"Bethesda Pinball": ["./Scripts/dmds/manufacturers/Bethesda Pinball.gif"],
	"Capcom": ["./Scripts/dmds/manufacturers/capcom.gif"],
	"Data East": ["./Scripts/dmds/manufacturers/dataeast-1.gif", "./Scripts/dmds/manufacturers/dataeast-2.gif"],
	"Foxnext Games": ["./Scripts/dmds/manufacturers/Foxnext Games.gif"],
	"Gottlieb": ["./Scripts/dmds/manufacturers/gottlieb.gif"],
	"Jurassic Pinball": ["./Scripts/dmds/manufacturers/Jurassic Pinball.gif"],
	"Marvel": ["./Scripts/dmds/manufacturers/Marvel.gif"],
	"Midway": ["./Scripts/dmds/manufacturers/bally.gif"],
	"Peyper": ["./Scripts/dmds/manufacturers/peyper.gif"],	
	"Premier": ["./Scripts/dmds/manufacturers/premier.gif"],
	"Rowamet": ["./Scripts/dmds/manufacturers/Rowamet.gif"],	
	"Sega": ["./Scripts/dmds/manufacturers/sega.gif"],
	"Spooky": ["./Scripts/dmds/manufacturers/Spooky.gif"],
	"Star Wars Pinball": ["./Scripts/dmds/manufacturers/Star Wars Pinball.gif"],
	"Stern": ["./Scripts/dmds/manufacturers/stern.gif"],
	"Taito": ["./Scripts/dmds/manufacturers/Taito.gif"],
	"The Walking Dead": ["./Scripts/dmds/manufacturers/The Walking Dead.gif"],
	"Universal Pinball": ["./Scripts/dmds/manufacturers/Universal Pinball.gif"],
	"Williams": ["./Scripts/dmds/manufacturers/williams.gif"],
	"WilliamsFX3Pinball": ["./Scripts/dmds/manufacturers/williams.gif"],
	"VPX": ["./Scripts/dmds/manufacturers/VPX.gif"],
	"VALVe": ["./Scripts/dmds/manufacturers/VALVe.gif"],
	"Zaccaria": ["./Scripts/dmds/manufacturers/Zaccaria.gif"],
	"Zen Studios": ["./Scripts/dmds/manufacturers/Zen Studios.gif"]
// logfile.log(getMethods(dmd).join("\n"));
function TestMarshalling() {
	let video = dmd.NewVideo("Manufacturer", "./Scripts/dmds/manufacturers/bally.gif");
	// This will fail due to a marshalling problem
function UpdateDMD() {
	if (updater !== undefined) clearTimeout(updater);
	updater = undefined;

	if (dmd == null) {
		dmd = createAutomationObject("FlexDMD.FlexDMD");
		dmd.GameName = "PinballY";
		dmd.RenderMode = 2; // 0 = Gray 4 shades, 1 = Gray 16 shades, 2 = Full color
//		dmd.Size = false;
		dmd.Width = 128; // normal:128 - high-res: 896
		dmd.Height = 32; // normal:32 - high-res: 224
		dmd.Show = true;
		dmd.Run = true;
		udmd = dmd.NewUltraDMD();
	if (dmd.Run == false) return;

	if (info == null) return;

	if (udmd.IsRendering() && shownInfo != null && == {
		// Add a timeout later for when the render queue will be finished
		updater = setTimeout(UpdateDMD, 1000);

	if (shownInfo == null || != {
		loopCount = 0;
		shownInfo = info;
	} else {


	if (loopCount == 0) {
		/*let rom = info.resolveROM();
		logfile.log("> Update DMD for:");
		logfile.log("> rom: '".concat(rom.vpmRom, "'"));
		logfile.log("> manufacturer:", info.manufacturer);
		logfile.log("> title:", info.title);
		logfile.log("> year:", info.year);
		logfile.log("> Table type: ", info.tableType);
		logfile.log("> Highscore style: ", info.highScoreStyle);
		if (rom.vpmRom == null) {
			dmd.GameName = "";
		} else {
			dmd.GameName = rom.vpmRom.toString();

	// Title
	var hasTitle = false;
	if (info.mediaName != null) {
		var extensions = [".gif", ".avi", ".png"];
		for (var i = 0; i < extensions.length; i++) { if (fso.FileExists("./Scripts/dmds/titles/" + info.mediaName + extensions[i])) { queueVideo("./Scripts/dmds/titles/" + info.mediaName + extensions[i], 0, 8, transitionMargin); hasTitle = true; break; } } } if (!hasTitle) { var name = info.title.trim(); var subname = ""; if (name.indexOf('(') != -1) { var sep = info.title.indexOf('('); name = info.title.slice(0, sep - 1).trim(); } if (name.length >= 16) {
			var split = 16;
			for (var i = 15; i > 0; i--) {
				if (name.charCodeAt(i) == 32) {
					subname = name.slice(i).trim();
					name = name.slice(0, i).trim();
		udmd.DisplayScene00("", name, 15, subname, 15, 0, 5000, 8);

	// Manufacturer
	let transitionMargin = (20 * 1000) / 60;
	if (info.manufacturer in manufacturers) {
		var medias = manufacturers[info.manufacturer];
		var media = medias[Math.floor(Math.random() * medias.length)];
		queueVideo(media, 10, 8, transitionMargin);
	} else if (info.manufacturer !== undefined) {
		udmd.DisplayScene00("", info.manufacturer, 15, "", 15, 10, 3000, 8);

// Manufacturer (incl. Workarround for Pinball FX3 Williams Logo)
    let transitionMargin = (20 * 1000) / 60;
    //kleine Workaround -Erweiterung für Williams "TM" Pinball Problem aus FX3
    let manufacturer_temp = info.manufacturer;
    // Wenn Manufacturer mit Williams anfängt, aber mehr als 8 Zeichen hat
    if ((manufacturer_temp.substr(0,8) == "Williams") && (manufacturer_temp.length > 8)){
        manufacturer_temp = "WilliamsFX3Pinball";
    if (manufacturer_temp in manufacturers) {
        var medias = manufacturers[manufacturer_temp];
        var media = medias[Math.floor(Math.random() * medias.length)];
        queueVideo(media, 10, 8, transitionMargin);
    } else if (info.manufacturer !== undefined) {
        udmd.DisplayScene00("", info.manufacturer, 15, "", 15, 10, 3000, 8);

	// Stats
	if (info.rating >= 0)
		udmd.DisplayScene00("", "Played " + info.playCount + " Rating " + info.rating, 15, "Play time: " + info.playTime.toHHMMSS(), 15, 10, 3000, 8);
		udmd.DisplayScene00("", "Played " + info.playCount + " times", 15, "Playtime " + info.playTime.toHHMMSS(), 15, 10, 3000, 8);

	// Insert Coin
	if (((loopCount + 0) & 1) == 0) {
		udmd.DisplayScene00("./Scripts/dmds/misc/insert-coin_c.gif", "", 15, "", 15, 10, 3000, 8);

	// Drink'n drive
	if (((loopCount + 0) & 1) == 0) {
		udmd.DisplayScene00("./Scripts/dmds/misc/drink-n-drive_c.gif", "", 15, "", 15, 10, 3000, 8);

	// Global stats (every 4 loops)
	if (((loopCount + 1) & 3) == 0) {
		var totalCount = 0;
		var totalTime = 0;
		var nGames = gameList.getGameCount();
		for (var i = 0; i < nGames; i++) {
			var inf = gameList.getGame(i);
			totalCount += inf.playCount;
			totalTime += inf.playTime;
		udmd.DisplayScene00("", "Total play count:" , 15, "" + totalCount, 15, 10, 1500, 8);
		udmd.DisplayScene00("", "Total play time:" , 15, "" + totalTime.toDDHHMMSS(), 15, 10, 1500, 8);
	// Highscores
	if (hiscores[] != null) {
		udmd.ScrollingCredits("", hiscores[].join("|"), 15, 14, 2800 + hiscores[].length * 400, 14);

	// Digital Stereo
	if (((loopCount + 0) & 1) == 0) {
		udmd.DisplayScene00("./Scripts/dmds/misc/digital-stereo_c.gif", "", 15, "", 15, 10, 3000, 8);
	logfile.log("< Update DMD done"); // Add a timeout for when the queue will be finished updater = setTimeout(UpdateDMD, 10000); } gameList.on("gameselect", event => {
	logfile.log("> gameselect");
	info =;

gameList.on("highscoresready", event => {
	logfile.log("> highscoresready");
	if (event.success && != null) {
		logfile.log("> scores received");
		for (var i = 0; i < event.scores.length; i++) { event.scores[i] = event.scores[i].replace(/\u00FF/g, ','); } hiscores[] = event.scores; if (shownInfo != null && == { udmd.ScrollingCredits("", hiscores[].join("|"), 15, 14, 2800 + hiscores[].length * 400, 14); } } }); mainWindow.on("prelaunch", event => {
	logfile.log("> launch");
	if (dmd != null) {
		dmd.Run = false;

mainWindow.on("postlaunch", event => {
	logfile.log("> postlaunch");
	if (dmd != null) dmd.Run = true;

Author: fR33Styler


// Show image overlay
mainWindow.on("launchoverlayshow", ev => {
let animation = gameList.resolveMedia("Images", "launch-image.jpg");

Author: fR33Styler


// hide the animated overlay Video as soon as the game has finished loading
mainWindow.on("gamestarted", ev => {;

Author: GSadventure – Link

Code: siehe Git-Hub.

// Choose a random game from current selection
import "start_random_table.js";

Author: fR33Styler


// Add Hotseat Modes to below Play on menu

// in the main menu, add Hotseat Modes after the
// Play command
let setPlayHotseatModeCommand = command.allocate("PlayHotseatMode");
mainWindow.on("menuopen", ev => {
if ( == "main") {
// main menu - check the current game's system
let game = gameList.getWheelGame(0) || { };
let sys = game.system || { };
if (/pinball fx3\.exe$/i.test(sys.processName)) {
// it's FX3 - add the Hotseat Play Mode command
ev.addMenuItem({ after: command.PlayGame },
{ title: "Play Hotseat Mode", cmd: setPlayHotseatModeCommand });

// Show the mode selection menu when the Play Hotseat Mode command
// is used, and process the commands in that menu.
let Hotseat2ModeCommand = command.allocate("Hotseat2Mode");
let Hotseat3ModeCommand = command.allocate("Hotseat3Mode");
let Hotseat4ModeCommand = command.allocate("Hotseat4Mode");

mainWindow.on("command", ev => {
if ( == setPlayHotseatModeCommand) {
let game = gameList.getWheelGame(0) || { };
let sys = game.system || { };
if (/pinball fx3\.exe$/i.test(sys.processName)) {
mainWindow.showMenu("custom.hotseatmode.fx3", [
title: "Hotseat: 2 Players",
cmd: Hotseat2ModeCommand,
title: "Hotseat: 3 Players",
cmd: Hotseat3ModeCommand,
title: "Hotseat: 4 Players",
cmd: Hotseat4ModeCommand,
{ cmd: -1 }, // separator
{ title: "Cancel", cmd: command.MenuReturn }

// tell the system not to launch the game yet

else if ( == command.Hotseat2Mode) {
let game = gameList.getWheelGame(0) || { };
let sys = game.system || { };
if (/pinball fx3\.exe$/i.test(sys.processName)) {
// figure out the hotseatmode options based on the current mode
// launch it with the hotseatmode 2 Players
mainWindow.playGame(game, {
overrides: {
params: "-applaunch 442120 -hotseat_2 -table_[TABLEFILEBASE]"
// skip the default action, since we did the launch here instead

else if ( == command.Hotseat3Mode) {
let game = gameList.getWheelGame(0) || { };
let sys = game.system || { };
if (/pinball fx3\.exe$/i.test(sys.processName)) {
// figure out the hotseatmode options based on the current mode
// launch it with the hotseatmode 3 Players
mainWindow.playGame(game, {
overrides: {
params: "-applaunch 442120 -hotseat_3 -table_[TABLEFILEBASE]"
// skip the default action, since we did the launch here instead

else if ( == command.Hotseat4Mode) {
let game = gameList.getWheelGame(0) || { };
let sys = game.system || { };
if (/pinball fx3\.exe$/i.test(sys.processName)) {
// figure out the hotseatmode options based on the current mode
// launch it with the hotseatmode 4 Players
mainWindow.playGame(game, {
overrides: {
params: "-applaunch 442120 -hotseat_4 -table_[TABLEFILEBASE]"
// skip the default action, since we did the launch here instead


Author: MJR » Link


// -------------------------------------------------------------------------------
// Global variable for keeping track of the current FX3 play
// mode. We'll use the strings "classic" and "new" to represent
// the modes. Initially, we'll restore the saved value from the
// settings file.
let currentFX3ModeKey = "custom.fx3.playMode";
let currentFX3Mode = optionSettings.get(currentFX3ModeKey, "classic");

// in the main menu, add our new Set Play Mode command after the
// Play command
let setPlayModeCommand = command.allocate("SetPlayMode");
mainWindow.on("menuopen", ev => {
if ( == "main") {
// main menu - check the current game's system
let game = gameList.getWheelGame(0) || { };
let sys = game.system || { };
if (/pinball fx3\.exe$/i.test(sys.processName)) {
// it's FX3 - add the Set Play Mode command
ev.addMenuItem({ after: command.PlayHotseatMode },
{ title: "Set Play Mode", cmd: setPlayModeCommand });

// Show the mode selection menu when the Set Play Mode command
// is used, and process the commands in that menu.
let classicPhysicsModeCommand = command.allocate("ClassicPhysicsMode");
let newPhysicsModeCommand = command.allocate("NewPhysicsMode");
mainWindow.on("command", ev => {
if ( == setPlayModeCommand) {
let game = gameList.getWheelGame(0) || { };
let sys = game.system || { };
if (/pinball fx3\.exe$/i.test(sys.processName)) {
mainWindow.showMenu("custom.playmode.fx3", [
title: "Classic Physics Mode",
cmd: classicPhysicsModeCommand,
radio: currentFX3Mode == "classic"
title: "New Physics Mode",
cmd: newPhysicsModeCommand,
radio: currentFX3Mode == "new"
{ cmd: -1 }, // separator
{ title: "Cancel", cmd: command.MenuReturn }

// tell the system not to launch the game yet
else if ( == classicPhysicsModeCommand) {
// set the new mode and save to the settings
optionSettings.set(currentFX3ModeKey, currentFX3Mode = "classic");
else if ( == newPhysicsModeCommand) {
// set the new mode and save to the settings
optionSettings.set(currentFX3ModeKey, currentFX3Mode = "new");
else if ( == command.PlayGame) {
let game = gameList.getWheelGame(0) || { };
let sys = game.system || { };
if (/pinball fx3\.exe$/i.test(sys.processName)) {
// figure out the extra options based on the current mode
let extra = "";
if (currentFX3Mode == "classic")
extra = "-class ";
else if (currentFX3Mode == "new")
extra = "";

// launch it with the extra options
mainWindow.playGame(game, {
overrides: { params: extra + sys.params }

// skip the default action, since we did the launch here instead

The frontend offers a lot of great possibilities (starting with filter possibilities up to statistics and ratings etc.)… best you start (after setting it up) to configure a table (actually only name it briefly) and then you can already arrange the appropriate media files (next part in the documentation)… and it looks like the one in my video above.


Here is my backup story very briefly…

I realized this with a batch-file, which in turn runs via the „task planner“ in WIN on the last day of every month.

I copy the DELTA of the (for me) relevant files to a second SSD hard drive.

@echo off

ECHO Datensicherung wird gestartet...
ECHO ...
ECHO ========================================================

ECHO === sichere Install ====================================
xcopy C:\_HDD-Install D:\_Backup\_HDD-Install /D /E /Y /I
ECHO ===== sichere _Backup ==================================
xcopy C:\_Backup D:\_Backup\_Backup /D /E /Y /I
ECHO ======= sichere Users (Roaming) ========================
xcopy C:\Users\VPIN\AppData\Roaming D:\_Backup\Users\VPIN\AppData\Roaming /D /E /Y /I
ECHO ========= sichere DirectOuptut =========================
xcopy C:\DirectOutput D:\_Backup\DirectOutput /D /E /Y /I
ECHO =========== sichere DOFConfigtoolClient ================
xcopy C:\DOFConfigtoolClient D:\_Backup\DOFConfigtoolClient /D /E /Y /I
ECHO ============= sichere Steam (Games) ====================
xcopy C:\Games\Steam\steamapps\common D:\_Backup\Games\Steam\steamapps\common /D /E /Y /I
ECHO =============== sichere PinAffinity64 ==================
xcopy C:\PinAffinity64 D:\_Backup\PinAffinity64 /D /E /Y /I
ECHO ================= sichere PinballY =====================
xcopy C:\PinballY D:\_Backup\PinballY /D /E /Y /I
ECHO =================== sichere PinSoundStudio =============
xcopy C:\PinSoundStudio D:\_Backup\PinSoundStudio /D /E /Y /I
ECHO ===================== sichere PinUPSystem ==============
xcopy C:\PinUPSystem D:\_Backup\PinUPSystem /D /E /Y /I
ECHO ======================= sichere PinVol =================
xcopy C:\PinVol D:\_Backup\PinVol /D /E /Y /I
ECHO ========================= sichere VPX ==================
xcopy C:\"Visual Pinball" D:\_Backup\"Visual Pinball" /D /E /Y /I

ECHO ...
ECHO  ----- Dietle VPIN Datensicherung abgeschlossen! -----
ECHO ========================================================


fR33Styler´s VPIN Frontend Media

So and finally there is a link to „fR33Styler’s VPIN Frontend Media“… here you find my

  • Backglass-Videos
  • DMD-Videos
  • Playfield-Videos
  • Wheel-Images
  • Launch- & Table-Audios

which I use in PinballY… …to navigate the pinball tables.

fR33Styler´s VPIN Frontend Media

fR33Styler´s VPIN Frontend Media



I hope that some of you could take something from this documentary for your stuff… or dive into the topic of virtual pinball (VPIN)… but most of all i hope you had fun with it.

Ralf Dietle