Porting an existing Visual Pinball PinMAME game - freezy/VisualPinball.Engine 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.

Setup

For most of the setup, we can refer to this page.

Make sure you are using Unity 2020.3.11f or greater.

If you ARE NOT doing Visual Pinball PinMAME Development

Install the following packages:

If you ARE doing Visual Pinball PinMAME Development

Setup the VPE scoped registry:

image

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.PinMAME

Build 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 Release

Verify the plugins have been created by looking in the Plugins/<RID> folder:

image

Game ROM

You will need to find an existing Terminator 2 L8 ROM. (Not sharing where to find one)

image

image

Service Manual

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

image

Create a scene

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

image

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

image

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

image

Import the table

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.

image

Extract the table script

We will need to refer to the table script when configuring the table.

image

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.TableScript

Other scripts

The table also uses other scripts that are part of a Visual Pinball installation:

LET'S START PORTING!

Now that we have everything we need, let's start porting!

Game Logic Engine

Whenever a table is imported, a Default Game Logic component is automatically added:

image

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

image

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

image

In the PinMAME Inspector, set the following values:

Game:  Terminator 2: Judgement Day
ROM: L-8

image

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:

image

Confirm that the Switch and Coil Managers have been updated:

image

image

DMD

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

image

Verify Game ROM

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.

image

Click the Stop button.

Trough

Next, we need to configure the Trough.

Refer to the Service Manual to find the Switch and Solenoid locations:

image

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 

image

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

image

In the Coil Manager, configure the Trough coils:

3, Outhole, Device, Trough, Entry
4, Trough, Device, Trough, Exit

image

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:

image

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:

image

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

image

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.

image

The ball now enters the shooter lane!

Plunger

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:

image

Plunger1 must be Coil 8 (Kickback), and was NOT what we were looking for.

Review the table script and search for SolCallBack(9).

image

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

image

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.

image

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

image

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.

image

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