Disclaimer: This project contains zero pokie/slot machine parts, the machine doesn’t have a coin mech or note acceptor – it can’t accept money and doesn’t payout money. No software is hosted, linked to or shared on this page. This is just a project for personal use, this was simply to see if this was even possible to work. The information here is for educational purposes only.
Contents
- Parts
- The Cabinet
- Software
- VGA Dummy Plug
Parts
- Flat Pack Bench Top Arcade Cabinet w/ 19” Dell LCD Monitor
- Dell Micro PC
- 12v Power Supply
- Ultimarc PacDrive
- SJ@JX Keyboard Coding Board
- 16x Generic Square Buttons w/ 12v LED’s & Microswitches
The Cabinet
I found a nice looking flat pack bar top arcade cabinet on eBay. The price was super reasonable, it included a 19″ LCD monitor that had the bezel already removed and the seller wasn’t too far away so I thought, what the hell? A global pandemic has just started and I might as well keep busy…
Once the cabinet arrived and I put it together I thought wow, this would be a cool little MAME box and I understand it was made with the intentions of it being a MAME box, but I had some other plans for it.
The Control Panel
Designing the Buttons
After playing around with the emulator, I knew I was going to have a problem with determining a physical button layout. Not all games have the same button layout, there are different bets, different number of lines and buttons randomly swapping.
I ran every single ROM and took a screenshot of the buttons and compiled it into the largest “iCloud Notes” note ever, in fact it actually ended up alerting me with an error saying I’ve added the maximum number of image attachments and I had to save the last couple to another note…
Because I’m an idiot, I printed all the buttons, cut them out and grouped them to find similarities. The ‘Gamble’ and ‘Take Win’ buttons seemed to always be in the same spot but the ‘Rules’, ‘Spin’ and ‘Collect’ buttons move around a bit.
My final solution was to have a mix of a 5 Dragons and Miss Kitty layout as I personally like both those games. I can always change the inserts later if I want to and nothing changes on the software side of things either way.
I designed a rough version with paper, then changed some things up like adding the suit symbols, adding some colour variations and printing it on a clear sheet.
Mounting the Buttons
I placed the buttons on the panel in the same layout as the emulators buttons – I think this looks nice and is practical. I thought about moving the collect button to the monitors bezel but there wasn’t much space and it would have been off centre (and that would have annoyed me).
I went and purchased a 25mm hole saw (thanks Bunnings), measured it up, marked it out and went to town. I put in all the button inserts (I only had paper copies at this stage) and mounted the buttons in the panel. It was looking good so far!
Wiring the Button Switches
Cabinet Side (PCB Side)
Now I wanted to get some real buttons working. For projects I’ve done in the past, I’ve normally just used an Ultimarc product, but I thought I’d try something different this time. As the Aristocrat emulator already has predefined controls, I just thought it would be easier to assign buttons to them physically. This board is called a “Keyboard Coding Board” by SJ@JX, which I found on Amazon.
Now that I had it in my hands, the first problem arose – they were kind enough to send me pre-made cables that connect the microswitches to the small connectors on the board… But not enough for how many buttons this project required. An easy solution to this problem was to pull the plastic connector off the board leaving the pins exposed. I soldered wires to each of the required pins then used heat shrink so nothing shorts and to keep the connections strong.
The second issue that came about was that there isn’t a common + or – on this board, which means every button requires 2 wires… This was turning into a chunky harness and I hadn’t even wired any of the LED’s yet.
Control Panel Side (Buttons Side)
Following the same colours as the wires soldered to the keyboard emulator, I made the harness that is on the control panel side, with molex connectors for easy removal of the panel (this is also a requirement because of the soldered wires to the board). As Ben Heck always says, “never build something you can’t pull apart” – wise words.
I tried my best to keep everything neat by cutting everything to length, using cable ties and plastic cable tidy. On the board side I kept the harness on the long side so in the event of removing the control panel, there is enough slack on the harness to get it out easily. This also keeps the harness rigid which makes removal and installation of the harness easy (I’m going to have to remove it when I vinyl wrap it though).
The wires hanging out the bottom are for other buttons on the cabinet which are not located on the control panel like the credit button, internal menu buttons and exit. I’ll deal with these later.
Wiring the LED’s
The LED’s that came with the buttons are 12v and the Ultimarc PacDrive LED Driver can only output 5v. Luckily it’s safe to use external 12v with this board as long as you only connect the ground wires and leave the + terminals disconnected.
I ran a common 12v to all LED’s and all the grounds terminate at the PacDrive board. Just like the switch harness, I added Molex connectors for easy removal. I tried to keep is as neat as possible but it still turned into looking like chaos!
As the Dell is a small form factor PC with a 19v power supply “brick” I wasn’t going to power everything of it. So, I used a framed 12vdc power supply as it is more than enough to power all the button LEDs, the speaker amp board and the header LED strip. Because the LEDs in the buttons have a 12v source from the external power supply and it’s ground is from the PacDrive you need to join grounds between the power supply and the computer. My simple solution was to terminate the wire with the screw of the WiFi antenna.
Software
Maximus Arcade
I found this post on AussieArcade.com from 2015, it explains how to load the ROMs into the Maximus Arcade front end and people also posted their theme designs.
I’d never used Maximus Arcade, I’d only ever used LaunchBox, Attract-Mode, EmulationStation and HyperSpin as front end software on dedicated hardware.
The software didn’t look like it was being actively worked on, but it looked so simple to setup and those other front ends would be overkill for this setup.
Setting Up Maximus Arcade as the Front End
Now this was super time consuming… Did I mention the global pandemic?
Anywho, I started up my Windows 7 VM and installed Maximus Arcade. By default, as you can guess by it’s title, Maximus Arcade is a Front End designed for arcade games. To make this look like it’s a finished product (and I know how to use photoshop so why not?), I needed to give the software a pokie theme with previews of the games so that I knew what each of them looked like. But with little to no information online about these games, I had to do it the DIY way…
My solution – I opened every single ROM, removed the credits, waited until it went into attract mode and took a screenshot of the artwork. Whilst I was there I also took a screenshot of the reels and recorded a short video of the reels in action – now I had enough art to make Maximus Arcade look awesome!
Having never used Maximus Arcade before, I spent a bit of time playing around with the theme editor. I slowly learnt how it worked by editing the default theme until I was completely happy with it.
AutoHotkey
Making The Game Start Fullscreen
Firstly, I don’t use Windows much. All my other computers are Mac’s, Hackintosh’s and Linux boxes – but I have to say, wow AutoHotKey is awesome.
Originally I wrote a simple AutoHotkey script called ‘background.exe’ that launched from Maximus Arcade at the time of loading a ROM. It looks for the active window titled Roms Screen 1
and when found hit ALT-ENTER
which is the shortcut for fullscreen.
This worked fine and I played it like this for a while but it would also hide the on-screen buttons. I knew I needed the on-screen buttons to be visible so AutoHotKey could see them and turn the LED’s on and off – I had to think outside the box.
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
WinWaitActive, Roms Screen 1 ; Look for active game window.
Send !{Enter} ; Press ALT-ENTER to enable fullscreen.
AutoHotKey script to make the game appear fullscreen while moving the on-screen buttons to a second monitor
What I ended up doing was writing another AutoHotKey script called ‘move.exe’ – similar to the previous script, it’s launched when loading a ROM, looks for the game window, but this time removes the titlebar and frame, then maximises the window (this looks fullscreen). Once it sees the on-screen buttons window, it moves it to my second monitor (in the exact same location every time).
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
WinWaitActive, Roms Screen 1 ; Look for active game window.
WinSet, Style, -0xC40000 , A ; Remove the window border and titlebar.
WinMaximize ; Maximise window.
WinWait, MK6 Emulator ; Look for buttons window.
WinMove, 1571, 475 ; Move window to the second screen.
AutoHotKey script to control LED’s by the colour of the pixels on the on-screen button panel
This script was my ha-ha moment! I found a script here that allowed me to utilise the PacDrive64.dll file and control the PacDrive from AutoHotKeys. In the original script it would turn on the LED as the button is pressed, so I removed the parts referencing button presses and replaced it with code I found here which I modified to look at a single pixel on every onscreen button: if it’s yellow it tells the assigned buttons LED to turn on, if it’s any other colour (black background from emulator not running yet or grey) it will turn the LED off. I’m no AutoHotKeys expert, I just found things online and adapted them for what I needed. This actually worked surprisingly well.
#SingleInstance Force
#Persistent
#NoEnv
SetWorkingDir, %A_ScriptDir%
; Uses of the PacDrive64.dll
; First, Load the Library with DllCall("LoadLibrary", "str", "PacDrive64.dll")
; Then Initialize the PacDrive with DllCall("PacDrive64.dll\PacInitialize")
; To set the LEDs as a whole use DllCall("PacDrive64.dll\PacSetLEDStates",Int,0,UShort,0) - Note (integer, pacdrive ID, short integer, decimal value for LEDs)
; To set induvidual LEDs, use DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,0,Int,1) - Note (integer, pacdrive ID, integer, pin0, integer, 1 means ON)
;
; This program, loads the PacDrive64.dll (which should be in the same folder as the AHK file you ran) and initializes it.
; Then it will refresh the LED output status for all 16 outputs (ie the LED ports on the PacDrive) after reading what the status of the virtual buttons on screen are.
;
; For this program, I used a Ultimarc PacDrive to light up 12v LEDs inside buttons.
;
; Every 100ms the ChangeLED routine is called from the settimer command and it reads a pixel colour, checks to see if it's 0xFFFF00 (RGB Yellow) and if so, sets the LED port pin
; to (1) ON. If it is not RGB yellow, then it sets the LED port to (0) OFF.
;
; Original code by Gwarble - THANKYOU!!!
;
; Modified for basic Gamepad/Joypad/Joystick indication by Ramjet - Later to be upgraded to Arcade/RaceSim cockpit
;
; Modified for Aristocrat MK6 Emulator by Shaun Jay.
If DllCall("LoadLibrary", "str", "PacDrive64.dll")
If DllCall("PacDrive64.dll\PacInitialize")
DllCall("PacDrive64.dll\PacSetLEDStates",Int,0,UShort,0) "`n`nError: " ErrorLevel
Else
ExitApp
SetTimer, ChangeLED, 100
Return
ChangeLED:
CoordMode, Pixel, Screen
Pixelgetcolor, Color0, 1582, 504, RGB ;Reserve Gamble Button
if Color0 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,0,Int,1)
}else {DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,0,Int,0)
}
CoordMode, Pixel, Screen
Pixelgetcolor, Color1, 1661, 504, RGB ;Bet x1 Button
if Color1 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,1,Int,1)
}else {DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,1,Int,0)
}
CoordMode, Pixel, Screen
Pixelgetcolor, Color2, 1737, 504, RGB ;Bet x2 Button
if Color2 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,2,Int,1)
}else {
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,2,Int,0)
}
CoordMode, Pixel, Screen
Pixelgetcolor, Color3, 1819, 504, RGB ;Bet x5 Button
if Color3 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,3,Int,1)
}else {DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,3,Int,0)
}
CoordMode, Pixel, Screen
Pixelgetcolor, Color4, 1893, 504, RGB ;Bet x10 Button
if Color4 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,4,Int,1)
}else {DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,4,Int,0)
}
CoordMode, Pixel, Screen
Pixelgetcolor, Color5, 1971, 504, RGB ;Bet x20 Button
if Color5 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,5,Int,1)
}else {DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,5,Int,0)
}
CoordMode, Pixel, Screen
Pixelgetcolor, Color6, 2065, 504, RGB ;Rules Button
if Color6 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,6,Int,1)
}else {DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,6,Int,0)
}
CoordMode, Pixel, Screen
Pixelgetcolor, Color7, 2144, 504, RGB ;Collect Button
if Color7 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,7,Int,1)
}else {DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,7,Int,0)
}
CoordMode, Pixel, Screen
Pixelgetcolor, Color8, 1580, 568, RGB ;Take Win Button
if Color8 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,8,Int,1)
}else {DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,8,Int,0)
}
CoordMode, Pixel, Screen
Pixelgetcolor, Color9, 1657, 568, RGB ;2 Lines Button
if Color9 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,9,Int,1)
}else {DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,9,Int,0)
}
CoordMode, Pixel, Screen
Pixelgetcolor, Color10, 1735, 568, RGB ;10 Lines Button
if Color10 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,10,Int,1)
}else {DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,10,Int,0)
}
CoordMode, Pixel, Screen
Pixelgetcolor, Color11, 1813, 568, RGB ;20 Lines Button
if Color11 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,11,Int,1)
}else {DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,11,Int,0)
}
CoordMode, Pixel, Screen
Pixelgetcolor, Color12, 1893, 568, RGB ;30 Lines Button
if Color12 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,12,Int,1)
}else {DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,12,Int,0)
}
CoordMode, Pixel, Screen
Pixelgetcolor, Color13, 1970, 568, RGB ;50 Lines Button
if Color13 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,13,Int,1)
}else {DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,13,Int,0)
}
CoordMode, Pixel, Screen
Pixelgetcolor, Color14, 2065, 568, RGB ;Feature Button
if Color14 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,14,Int,1)
}else {DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,14,Int,0)
}
CoordMode, Pixel, Screen
Pixelgetcolor, Color15, 2145, 568, RGB ;Rules Spin Button
if Color15 = 0xFFFF00
{
DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,15,Int,1)
}else {DllCall("PacDrive64.dll\PacSetLEDState",Int,0,Int,15,Int,0)
}
return
VGA Dummy Plug
Since the AutoHotKey script moves the on-screen buttons to the second monitor I was considering getting a small LCD panel that I could hide in the back of the cabinet. This didn’t seem like the best solution as it adds extra costs, heat and power consumption. I searched online for a software fix, but nothing I found seemed like a permanent solution.
I finally stumbled upon this “VGA hack” that tricks the computer into thinking there is a monitor plugged in. All you have to do is connect 75Ω resistors from the RGB channels to ground. Quick trip to JayCar, got all the things I needed, put it together and it worked! Because it’s a dongle I can always remove it and plug in a real monitor for troubleshooting reasons. Such a cheap and simple solution.
To be continued… (Project is 100% complete now, will add a follow up here).