I remember playing most of the 20 cent (closest denomination to US quarters) classics, such as 1941/1942, Arkanoid, Bubble Bobble (my all time favourite), Elevator Action, Gyruss & Galaga.
I missed out on the all-time greatests such as Space Invaders, Pac-Man and Donkey Kong as the local shops weren't that big. I did get some of them on cartridge for the Atari 8-bit computers a few years later though.
I stopped playing coin-ops in around mid-1990 as I got my first 'real' computer (an Atari 1040 STfm). The next time I was around arcade machines, they'd shot up to $1 for 2 games, and all the old classics had disappeard from sight. *sobs* The leading reasons were loss of popularity (fighting such as Street Fighter and Mortal Kombat were all the rage) and hardware failure. Old cabinets were thrown out in the trash, or had their PCBs thrown out to be replaced with newer games...
Thanks to the initial efforts of Nicola Salmoria and now countless others, these classic games will be preserved for the foreseeable future. MAME is free, world-wide software project that now emulates (the hardware) for over 3000 arcade games. The first version of MAME I saw was 0.24, and I think it only supported a few hundred games (anyone have an exact figure?).
So the reason for the cabinet? To preserve a bit of computing history & to enjoy the nostalgia of playing old arcade games in as close to their original environment as possible. Plus, you have to admit, it makes a rather impressive and unique coffee-table! :)
I finished the cabinet in 2001 (pic below). I've included information from during the build below, as reference material for anyone else who wants to build a cabinet. Some of it is a bit outdated, for example I would choose a RasPi or Arduino instead of trying to cram a full-sized PC in the case.
I was given a generic cocktail/tabletop cabinet with a "Burnin' Rubber" PCB in it. The case itself was in pretty good condition. The acrylic on the top was scratched and misty, so it needed replacing. The PCB was damaged, as were the controls and wiring. The screen looked dead.
The original plan was to just restore the cabinet to its original state. After looking around a bit, I figured out that I probably wouldn't be able to fix it. The next best thing was to build an emulated arcade machine...
The first thing I did was remove the old cruddy bit of arylic on the top. Underneath, there was another bit of acrylic covering the screen, which had gone yellow. There were two bits of cardboard covering the spaces for rotating the screen 90°. The black vinyl underneath the acrylic was also past its used-by-date, so it had to be binned too. The vinyl came off in one piece, but left the very sticky glue behind. I removed the glue with some "De-solve it" (very handy stuff!) and sanded the top of the table. The top looked pretty good, apart from where someone obviously filled a hole in with wood putty.
After finishing the top, I sanded the inside of the cabinet a bit to remove excess splinters. The rest of the wires, staples and clips were removed from the cabinet and the remaining crud/dust was vacuumed out. I decided to paint the top of the cabinet instead of replacing the vinyl, as paint doesn't start to peel off after a few years.
The PC I built was a BX m/b fitted with a Celeron 433 & 64MB SDRAM.
It was overkill for the time - any pentium-class system would have worked. I was originally after a pII/233 as I had the motherboard handy, but then came across a smaller m/b which had inbuilt audio, video, modem and 10/100mbit LAN. I chose a Celeron because of price and the PPGA packaging. As it turns out, a Slot1 pII CPU wouldn't have fitted underneath the tube for the screen.
The PC is mounted in a standard ATX tower case with powersupply. I bought the smallest case that I could find (at a reasonable price), but it still had 3x5.5" and 2x3.5" bays. Some drastic measures were needed to fit it inside the cabinet.
The solution? Take a hacksaw to it... quite satisfying. :)
The onboard sound didn't work properly in DOS, so I disabled it and used an old ISA Soundblaster 16 instead. A photo showing the final layout is below. On the far left of the case is a 3.5" Floppy drive, which was used to install the OS.
Space is rather limited inside the cabinet, so I spent a fair amount of time trying different ways of installing the PC system. I decided to just put the PC case (trimmed to size) into the bottom of the cabinet and work around it. The photo on the left shows the case loose inside the cabinet. The powerboard on the left was later covered with a shelf/shielding for the left speaker. The photo on the right shows the final layout.
The screen sits directly above the PC system. It is just a cheapo Samsung 14" VGA monitor. It was the perfect size for the cabinet. The mounting bracket was the same size as the old screen, so I didn't even have to worry about lining it up correctly. The PCB and front panel controls are mounted vertically next to the tube on player 1's side.
A really nice feature of the case I bought, was that the front panel controls (power/reset/sleep switches & LEDs) were seperate from the rest of the case. They were located on a small rectangular piece of plastic that was only attached to the front bezel with two screws.
To maintain the illusion of being a 'real' arcade machine, the controls needed to be accessible without having reach inside the cabinet, but not visible. The best place for the controls was underneath the ledge for player 1's controls. The control strip and external connectors are shown in the photos below. From left to right are:
The PC speaker/beeper was installed at the top of the cabinet, just to the left of player 1's controls (so it can be heard with the case closed). There is a keyboard switch to change between the internal controls and an external keyboard. The switch also allows for multiple mice/monitors too, if they're ever needed.
The original controls were in bad shape, and there was only 1 button per player, so games like elevator action were unplayable. I decided on 6 buttons for player 1 and 2 buttons for player 2. The 1&2p start buttons have LEDs to indicate when there are enough credits to use them.
I ordered the parts online from Happ Controls in the US. It was a simple matter of cutting & drilling a couple of bits of wood, painting them, then mounting the controls.
I collected the background info on the PC joystick from several sites. I've put them all here as none of the individual sites covered everything you need to build a set of arcade controls. The usual disclaimer applies to all information here... if you damage anything, then it's your fault, not mine. :)
Building the circuits is pretty simple. You'll need the controls, some wires and (100k ohm) resistors and a soldering iron. A multimeter also helps in making sure you're hooking up the circuit correctly before soldering things in place and for troubleshooting bad connections. If you're just after the circuit diagrams, they're at the end of this document, but I've also included some background info on how the circuits work.
PC joysticks are typically simple. They are provided +5v and GND by the joystick port, and feed provide each output on a seperate pin. A table of pinouts and circuit diagrams for various joystick configurations are included at the end of this document. Joystick buttons are simple on/off inputs, while the x&y axis provide variable resistance for a range of motion.
Analog joysticks basically consist of 2 potentiometers (one for up/down and another for left/right) and switches for the buttons. The potentiometers provide variable resistance for the x&y axis. The up/left directions will have lower resistance values than down/right ones.
Digital joysticks/joypads have 2 switches per axis which are wired to produce 3 distinct resistance values for up/left, center and down/right. The table shows the values I used in creating the digital joystick circuits.
Bit # | Data |
---|---|
7 | Button B2 (pin 14), 0=closed, 1=open (default) |
6 | Button B1 (pin 10), 0=closed, 1=open (default) |
5 | Button A2 (pin 7), 0=closed, 1=open (default) |
4 | Button A1 (pin 2), 0=closed, 1=open (default) |
3 | Monostable BY (pin 13), 1=timing, 0=timed-out |
2 | Monostable BX (pin 11), 1=timing, 0=timed-out |
1 | Monostable AY (pin 6), 1=timing, 0=timed-out |
0 | Monostable AX (pin 3), 1=timing, 0=timed-out |
The joystick port is a very simple 8 bit interface which resides in ISA bus I/O address 201h. The CPU can read and write to the joystick port I/O address 201h. Writing to that address starts joystick postition measurement. The joystick interface only uses the signal that somebody is writing to the I/O address to reset the multivibrators in the card, so the value written doesn't matter.
Reading a byte from I/O addess 201h returns the joystick interface's status. The four most significant bits store the state of the joystick buttons. The four least significant bits store state of the multivibrators which are used for measuring the resistance value of the joytick position potentiometers.
To determine the value of each stick axis, this byte is polled until all the joystick bits have flipped. When they have all flipped, the number of polling cycles each one took to flip is proportional to the resistance on that pin. Reading the buttons' values is much simpler, the byte is just read once and the values taken directly from bits 4-7.
Pinout (front of male D15 connector on joystick)
.------------------------. \ 8 7 6 5 4 3 2 1 / \ 15 14 13 12 11 10 9 / `--------------------'
Use the links in the table headers below for circuit diagrams.
Pin # | 2 Button stick | Dual 2 Button sticks | 4 button stick | 6 button stick |
---|---|---|---|---|
1 | +5v | +5v | +5v | +5v |
2 | Button 1 | Player 1 Button 1 | Button 1 | Button 1 |
3 | X-axis | Player 1 X-axis | X-axis | X-axis |
4 | GND | GND | GND | GND |
5 | GND | GND | GND | GND |
6 | Y-axis | Player 1 Y-axis | Y-axis | Y-axis |
7 | Button 2 | Player 1 Button 2 | Button 2 | Button 2 |
8 | - | - | - | - |
9 | +5v | +5v | +5v | +5v |
10 | - | Player 2 Button 1 | Button 3 | Button 3 |
11 | - | Player 2 X-axis | - | Button 5 |
12 | GND | GND | GND | GND |
13 | - | Player 2 Y-axis | - | Button 6 |
14 | - | Player 2 Button 2 | Button 4 | Button 4 |
15 | - | - | - | - |
To help in building and testing your controls, you can download this program which I wrote to help build mine.
I chose the 6 button stick layout for player 1's controls to give the maximum amount of useable buttons. Even if I used the 2 stick layout, I'd still need to wire up the start buttons and coin-mech to the keyboard interface.
Most of the time taken for wiring this set of controls was figuring out which wire goes where. :) I couldn't find any information for a 6 button circuit, so I had to mess around until I came up with the right setup. A multimeter and a little program I wrote were really useful in creating and troubleshooting the design.
I wired up the controls to a D15 (PC joystick) connector to reduce the chance of breaking the circuit when working in the cabinet. It also makes the wiring in the cabinet a bit nicer.
The main parts of a PC keyboard are the keyboard controller and the contacts for each key.
There are 2 sets of wires for the contacts, forming a matrix. The contacts are connected to one wire from each set. When a contact is presesd, the circuit is completed between the two wires. The keyboard I hacked had 16 wires in one set and 8 in the other, giving a maximum of 16x8 = 128 keys.
The controller checks for key presses by passing current through each wire in the first set, in turn, and seeing which wires in the second set have current. It then translates the info into something the PC can understand. The limit to the number and combination of keys that can be held down together comes from the controller. The 'keyboard hack' involves removing the controller from the keyboard and wiring up the cabinet controls to your own matrix. The keyboard I used was an old IBM ps/2 model. I had several of them sitting in boxes in the garage, so there were plenty of backups in case I killed one. Inside the keyboard, the matrix was printed on 2 sheets of plastic. The contacts were seperated by a third sheet. The controller was on a small PCB, hidden underneath a sheet of metal supporting the matrix.
I mounted the controller together with a hobby PCB to make it easier to work with. The first photo below shows the state of the controller before I started working on it. The three black connectors on the top, from left to right are for the 1st set of 16 wires, the 2nd set of 8 wires and the keyboard LEDs. The LEDs are still plugged in at this stage and you can just make out the tracks on the plastic that connect them to the controller. In the second photo, I've removed the connectors and wired the controller to the hobby PCB with some old floppy-drive ribbon cable. It took a while to solder all the wires in place, but it made the rest of the work easier.
I placed the controller between player 2's controls and the cabinet controls. The mounting is hinged, and swings open, for easy access. The next job was to find out where the necessary keys were on the matrix. To do this, I connected the controller to an old 386 running the same program I used to wire up player 1's controls. The 386 was used instead of the cabinet's PC as it's fairly easy to blow up the controller and/or the keyboard interface on the PC. The matrix I came up with is shown below. It's actually using MAME's standard settings for player 1, as the player 2 standard key assignments have always caused problems when multiple keys are being held down. The 5, 1 & 2 keys are used for the coin-mech, 1up and 2up respectively.
This is the final result. If you look carefully, you can see that the ribbon cable for the set of 16 wires in the matrix is now wired underneatch the PCB. I had to replace the keyboard controller as it broke sometime when I was either fitting or testing it (oops!). The keyboard LEDs for Num-lock and Caps-lock are wired to the 1up and 2up buttons on the front panel. The buttons light up when enough credits are inserted in some games.
The cabinet only had 1 small speaker mounted at the bottom left. This was replaced with a fan to suck in fresh air to keep the temperature down inside the cabinet.
The replacement speakers needed to be amplified (the cabinet muffles the sound somewhat), have a flat surface, and have a fairly simple layout inside. Low cost was more important than looks as they were going to be ripped apart anyway. :)
The speakers I ended up with met most of the requirements, and as an added bonus, could plug straight into the mains for power (yay, no external PSU!). The speakers had a slightly more curved surface than I thought, so they had to be recessed further into the cabinet.
I had no idea where the speakers would be placed, but space inside the cabinet was now limited to two 'shelf' type areas on the upper left and right sides of the cabinet. The first photo below shows how the speakers stayed until I finally decided to poke them through the top of the cabinet. The second photo shows the original screen that was in the cabinet. Take note of the empty space between the tube and where the speakers sit on either side.
When I first fitted the monitor inside the cabinet, I was getting interference from the speakers (which were supposed to be shielded). The speakers would also crackle and then make a low buzzing noise when the monitor was turned on. The problem would get worse once I removed the speakers from their casing and mounted them inside the cabinet, so the only solution was to make up my own shielding.
The shielding I made was some sheet-metal from some old 286 cases, which were cluttering up the garage, sandwiched between some plywood. The shielding also hides away some of the wiring mess at the bottom of the cabinet. The first photo below shows the inside of the cabinet with the shielding in place and the speakers mounted on the lid. The next two show the top of the cabinet with the speakers installed.
NOTE: Before asking me why binaries aren't available here to download, or how you download and compile the MAME sources, please read this.
Since I had made the cabinet hardware look as authentic as possible, I needed to spend an equal amount of attention on the software. The PC's only job is to run MAME, so I didn't need the latest fancy software on it. I didn't include a CD-ROM drive in the PC, so that also helped me decide on what got installed. I settled on using the DOS version of MAME and Windows for networking to my other PC. Win95 was installed from floppies, and the rest of the software installed over the network.
After everything was installed, the next step was to try and get MAME running as soon as possible after the system starts, with the minimum amount of stuff on the screen that gives away that there's a PC in there and not a real arcade machine.
When the PC starts, the usual DOS cruft is loaded (HIMEM, EMM386, SMARTDRV), then my custom frontend is run, which starts MAME. Windows is only started after MAME exits, which impossible unless the external keyboard is plugged in. To select another game, you currently have to reboot the PC. I'll only fix that if/when it becomes too annoying.
The next step was to fiddle with the MAME sourcecode so that there's no extra output (the disclaimer & the game info screens). At the same time, I changed the default cabinet type to cocktail and tweaked the controls so that P1 defaults to the joystick and P2 has the arrow keys + control + alt.
Apart from the BIOS self-test output when the PC is powered on, there's now nothing that gives away the fact that there's a PC in there.
Mission complete! :-)There didn't seem to be a way of configuring MAME to set the default cabinet type to cocktail, and I really didn't feel like changing each game manually, so I had to somehow change it at the source level. Unfortunately, the cabinet type is set using the default dip switch settings in each driver file (hundreds of them), so changing them manually would still have been somewhat tedious...
Fortunately, the settings were in a standard format, so that means I could write a script to change them all at once. Here is an example dip switch setting:
PORT_DIPNAME( 0x08, 0x00, DEF_STR( Cabinet ) )
The "PORT_DIPNAME" part signifies a dip switch setting. The first number (in hex notation) is the bit that the switch controls. The second number is the default value of the bit (0x00 if unset, or the value of the first number if set). The last part is the text that is displayed in the on-screen-display inside MAME. Therefore, all the script needs to do is set the second number to the first one if it is zero, otherwise set it to zero.
The Sed script I wrote is shown below. It needs to be run on all the C files in the "src\drivers" directory. If you decide to use the script, it's probably a good idea to back up the driver files first, just in case something goes wrong.
s/PORT_DIPNAME( 0x\(..\), 0x\1, DEF_STR( Cabinet ) )/PORT_DIPNAME( 0x\1, 0xxxabcdef, DEF_STR( Cabinet ) )/ s/PORT_DIPNAME( 0x\(..\), 0x00, DEF_STR( Cabinet ) )/PORT_DIPNAME( 0x\1, 0x\1, DEF_STR( Cabinet ) )/ s/0xxxabcdef/0x00/
I wrote an extremely basic frontend for DOS. It displays a game selection screen only if both joystick 1 buttons A&B were pressed when it loaded, otherwise it just runs MAME using the last game that was played. The game is selected by highlighting its 8-letter name (I did say it was basic!) using the joystick, then pressing joystick 1 button 'C' / joystick 2 button 'A'.
The sourcecode needs DJGPP & STOSLib to compile. Here's a screenshot showing the game selection screen:
All amounts are in Australian dollars... in 2001. (1.00 AUD ~ 0.56 USD at the time)
Part description | Cost |
---|---|
Arcade cabinet | $150 |
BX m/b, Celeron 433 & 64MB SDRAM | $400 |
ATX tower case | $42 |
14" screen | $40 |
"600W" powered speakers | $35 |
Arcade controls | $85 |
Power board | $15 |
1.44MB Floppy & 2GB HDD, keyboards, cables, etc. This stuff is from loads of computer junk that I've gathered over the years. | $0 |
2x PS/2 & VGA switchbox | $45 |
Sheet of glass for the top | $50 |
Misc wiring, timber, paint, screws, fasteners, latches, etc. | $100 |
Total Cost (AUD): | $937 |