Porting an existing Visual Pinball PinMAME game - freezy/VisualPinball.Engine GitHub Wiki
Game logic for many Visual Pinball tables is done using VBScript. A table contains a script that references other scripts that are included with a Visual Pinball installation. The scripts all work together and connect the playfield to a game controller such as Visual PinMAME.
Out of the box, Visual Pinball Engine can do a lot without any scripting at all!
This guide will show how to port an existing "Terminator 2: Judgement Day" VPX table to Visual Pinball Engine.
For most of the setup, we can refer to this page.
Make sure you are using Unity 2020.3.11f or greater.
Install the following packages:
-
VisualPinball.Engine(0.0.1-preview.46 or greater) -
VisualPinball.Engine.PinMAME(0.0.1-preview.42 or greater) -
VisualPinball.Unity.Hdrp(0.0.1-preview.58 or greater)
Setup the VPE scoped registry:

Clone the repositories:
git clone https://github.com/freezy/VisualPinball.Engine
git clone https://github.com/VisualPinball/VisualPinball.Unity.Hdrp
git clone https://github.com/VisualPinball/VisualPinball.Engine.PinMAMEBuild the PinMAME Unity Plugins:
The PinMAME libraries are large and change often, so they are not stored in the git repo. We only need to do this once.
cd VisualPinball.Engine.PinMAME
git checkout feature/audio
cd VisualPinball.Engine.PinMAME
dotnet build -c ReleaseVerify the plugins have been created by looking in the Plugins/<RID> folder:

You will need to find an existing Terminator 2 L8 ROM. (Not sharing where to find one)
- If you are on Windows, make sure you have a working install of VPinMAME. Place the ROM in the VPinMAME's
romsfolder:

- If you are on MacOS or Linux, make a
.pinmame/romsfolder in your home directory and place the ROM here:

The service manual contains switch and solenoid location information. This information is important when configuring switches in the Switch Manager, and coils in the Coil Manager. Service manuals are available at IPDB

Create a new Basic Indoors (HDRP) Scene and save it as T2VPE

Select the Main Camera, and set Post Anti-aliasing to SMAA

Select the Plane, and change the Transform Y Position to -0.1

You will need to find an existing "Terminator 2: Judgement Day" VPX table. (Not sharing where to find one)
In the Visual Pinball menu, select Import VPX, and open the "Terminator 2: Judgement Day" vpx file.

We will need to refer to the table script when configuring the table.
- If you are on Windows and have Visual Pinball installed, view the script using the
Scriptcommand in theViewmenu.

- If you are on MacOS or Linux, use the
VisualPinball.TableScriptcommand line tool which is part of the VisualPinball.Tools project. You can download it here.
Extract the table script:
VisualPinball.TableScript "Terminator 2: Judgment Day (Williams 1991).vpx" .Note: If you are on MacOS and have issues running the utility, run the following:
chmod +x VisualPinball.TableScript
xattr -d com.apple.quarantine VisualPinball.TableScriptThe table also uses other scripts that are part of a Visual Pinball installation:
Now that we have everything we need, let's start porting!
Whenever a table is imported, a Default Game Logic component is automatically added:

Remove it by selecting Remove Component in the Table Inspector under Default Game Logic:

Add a PinMAME Game Logic component by selected Add Component and searching for PinMAME:

In the PinMAME Inspector, set the following values:
Game: Terminator 2: Judgement Day
ROM: L-8

The PinMAME Game Logic component can automatically configure switches, coils, and lamps per game. While this feature is not complete, it provides a good start in setting up the table.
Select Populate Hardware and then click Yes when prompted:

Confirm that the Switch and Coil Managers have been updated:


To add a DMD (Dot Matrix Display), select Create Displays:

Save the scene.
Click the Play button.
If this is the first time running the ROM, the DMD will cycle between
BOOKKEEPING
TOTALS CLEARED
and
FACTORY SETTINGS
RESTORED
Press 7 to continue initializing the ROM.

Click the Stop button.
Next, we need to configure the Trough.
Refer to the Service Manual to find the Switch and Solenoid locations:

When the ball enters the outhole, it actives Switch 18 (Outhole). The CPU activates Coil 3 (Outhole) which kicks the ball in the trough. If all three balls are in the trough, then Ball 3 activates Switch 15 (Trough Left), Ball 2 activates Switch 16 (Trough Center), and Ball 1 activates Switch 17 (Trough Right).
When the player hits the Start button (Switch 13), the CPU activates Coil 4 (Trough) which moves Ball 1 into the Shooter Lane. Ball 1 then activates Switch 78 (Shooter). When the player presses the Grip Trigger (Switch 34), the CPU activates Coil 9 (Plunger) which launches the Ball 1 around the playfield.
In the Table Hierarchy, search for Trough.
In the Trough Inspector, set the following values:
Type: Two coils multiple switches
Ball Count: 3
Switch Count: 3
Has Jam Switch: [ ]
Roll Time: 300
Playfield Links
Input Switch: Drain
Exit Kicker: Ball Release

In the Switch Manager, configure the Trough switches:
15, Trough Left, Device, Trough - Ball 3 (entry)
16, Trough Center, Device, Trough - Ball 2
17, Trough Right, Device, Trough - Ball 1 (eject)
18, Outhole, Device, Trough - Entry Switch

In the Coil Manager, configure the Trough coils:
3, Outhole, Device, Trough, Entry
4, Trough, Device, Trough, Exit

Save the scene.
Click the Play button.
Once the ROM finishes initializing, press 5 to add coins. Press 1 to start the game.
The ball never makes it into the shooter lane.
Click the Stop button.
To see what is happening, turn off the apron Primitive 68 and shooter cover Primitive 45.
Click the Play button.
Once the ROM finishes initializing, press 5 to add coins. Press 1 to start the game.
Now we can see the ball move, but it doesn't have enough power to make it into the shooter lane:

Click the Stop button.
We need to review the table script to see how the trough was set up. Search the table script for Trough.
bsTrough is defined as a cpvmBallStack object:

In Core.vbs, find the cvpmBallStack.InitKick function:
Public Sub InitKick(aKicker, aDir, aForce)
Set mExitKicker = aKicker : mExitDir = aDir : mExitForce = aForce
Set mSoundKicker = aKicker
End Sub
The parameter names aDir, and aForce hint they are related to direction and force.
Activating BallRelease will kick a ball 90 degrees with a force of 8.
If we search the Table Hierarchy for BallRelease, we see the following values:
Default Angle: 90
Default Speed: 3

Update the values to:
Default Angle: 90
Default Speed: 8
Save the scene.
Click the Play button.
Once the ROM finishes initializing, press 5 to add coins. Press 1 to start the game.

The ball now enters the shooter lane!
Next, we need to configure the Plunger.
From the Service Manual, we know that the table uses a solenoid, Coil 9 (Plunger), for launching the ball into the playfield.
If we search the Table Hierarchy for Plunger, select Plunger1.
Notice that Plunger1 is located on the left side of the playfield:

Plunger1 must be Coil 8 (Kickback), and was NOT what we were looking for.
Review the table script and search for SolCallBack(9).

SolCallBack(9) references bsShooter. bsShooter is defined as a cpvmBallStack object:

In Core.vbs, find the cvpmBallStack.InitSaucer function:
Public Sub InitSaucer(aKicker, aSw, aDir, aPower)
InitKick aKicker, aDir, aPower : mSaucer = True
If aSw Then mSw(1) = aSw Else mSw(1) = aKicker.TimerInterval
End Sub
The parameter names aSw, aDir, and aPower hint they are related to switch, direction, and power.
Shooter is connected to switch 78. Activating Shooter will kick a ball 0 degrees with a power of 50.
In the Switch Manager, set switch 78 to Shooter:
78, Shooter, Playfield, Shooter
In the Coil Manager, set coil 09 to Shooter.
09, Plunger, Playfield, Shooter
Save the scene.
Click the Play button.
Once the ROM finishes initializing, press 5 to add coins. Press 1 to start the game.
When the ball enters the shooter lane, press Enter to launch the ball.

We see the ball move slightly and it appears the CPU activates Coil 9 several times.
Click the Stop button.
If we search the Table Hierarchy for Shooter, we see the following values:
Default Angle: 90
Default Speed: 3

Update the values to:
Default Angle: 0
Default Speed: 50
Click the Play button.
Once the ROM finishes initializing, press 5 to add coins. Press 1 to start the game.
When the ball enters the shooter lane, press Enter to launch the ball.

The ball now exits the shooter lane and onto the playfield!