Table top Retropi Tron Theme

Been working on this for a while and needed to get it off the unfinished list… Getting closer.

Joystick panel was laser cut and joysticks were 3d printed. Micro connected to buttons is pi pico wired to an arduino nano breakout board programmed to enumerate as a usb keyboard and every button reports as a keyboard keypress. Keyboard integration into retropi is not completed yet, but the xbox controllers work awesome and there are no loose wires around the TV so setup and takedown are noexistent and the system is available for play all the time now.

initial cuts on MDF were done on MPCNC. cabinet is an original design I made drawn in Coreldraw, processed in estlecam, and cut from 1/2" mdf. Side graphics are printed poster adhesively laminated with adhesive on the back and cut to size. Front marquee is laser engraved and laser cut acrylic. Lighting is LED neon cut to lenght and nailed in place. System runs on a raspberry pi3 with a craigslist freebie 19" LCD monitor and leftovver usb speaker in the marquee.

Favorite game: playstation- TonyHawk Pro Skater 2. I have the disk and imaged the ISO to play on this machine. Second favorite- NES Mike Tyson’s Punchout.

Once the keyboard integration is complete, I can start playing the sega mortal kombat games originally intended for this system as a 2 player fight system.

A few items are not fully complete, but it works and is being used and may find a new home soon off of my workspace.


I love THPS. I spend way too much time playing that game on the playstation.

That cabinet looks awesome. I like the clear panel on the top. You should find some cool looking PCBs from recycled electronics and just cut them up and stick them back there.

1 Like

I just got the new THPS version for the switch. It is pretty good, though a bit harder for me than the original.

1 Like

I did not know there was a version for the switch. We just got 5 new games this holiday, but maybe by the time my birthday comes around we will be looking for new challenges.

1 Like

It is actually THPS 1 & 2 combined. I picked it up in October on sale for like $30. Graphics are so much better than the original, but the maps are pretty much the same. There are some extra challenges and a ton more customization, but it plays very similar to the playstation with a pro controller.

1 Like

Sick! Love the classic SFII button layout. Why go Genesis MK when you can go arcade version? Pi 3 should be able to handle it.

1 Like

availability. I have the sega MK and not the arcade version. I suppose with some effort I could “find” it.

DM me if you can’t find it. I’ve got a copy that runs on a Pi 3 somewheres.

1 Like

I printed Mortal Kombat graphics for the sides as well, but went with tron for waf. Plus, the led accent goes with tron better. I probably should put a tron game on it…

1 Like

There’s Tron Deadly Discs for the Intellivision I think. Maybe Atari 2600? The Tron arcade version might use some specialty controls if I’m remembering that right. It’s been awhile since I played those.

1 Like

Yep, can’t do THE arcade Tron without the spinner and analog stick. Something like that needs a modular panel, unless you’re really, really into Tron.


Very interesting… never heard of the combo version. THPS2 is like mine and my wife’s all time favorite game.

1 Like

The biggest reason I’m messing with a modular panel rn is Star Wars arcade. I got myself a GRS flight yoke for Christmas because that was one of my favourite games. I spent many quarters on it. I’m having some trouble with the modular design, enough that I’m comsidering making it a separate machine. Star Wars arcade, Spy Hunter, maybe some more flying and driving games

1 Like

At the risk of ridicule and infamy. I offer this as a possible option.


Ah yes Star Wars, one of the few vectorized games that I think everyone is familiar with. Don’t forget the pedal for spyhunter. One of the things I want to make a modular for is Off Road and Super Sprint… modular pedals too, because you only need one set for APB.

LOL, I opened up the comments, and was not expecting what I saw. There are lots of folks taking that seriously. I mean, it doesn’t even have A10 grips?! :wink:

1 Like

A couple more roms found their way on my system:


In case anyone wants, I harvested some micropython code examples and customized it for the 3d printed joystick and buttons to run on the pi pico that is powering the panel controls when not using the controller. I’m still working out how to get retroarch to recognize 2 different player controller on one keyboard device, but player 1 works well enough.

Here is the joystick 3d print model I used:

Bought the cheapest 1/2" buttons I could find. Not recommended, but they work. Tried 3d printing the buttons and using the ultra cheap mini buttons… did not work.

Button assignments
Control button Player 1 Player 2 Mame name Default Mame key P1
up w u up ^ arrow
down s j down v
left a h left <
right d k right >
Upper blue 3 8 Y (button name)
red 4 9 X
yellow 5 0 Right shoulder
Lower blue e i B ENTER
red r o A P
yellow t p R2 trigger
select f l COIN select 1/2 5
start v . START 1/2 6
special z z exit/play
Micropython Code for pi pico


Keyboard Emulator Using Maker Pi Pico and CircuitPython

References and credit to

. CircuitPython HID Keyboard and Mouse | CircuitPython Essentials | Adafruit Learning System

Raspberry Pi Pico

. [Maker Pi Pico] Maker Pi Pico and Kits

Additional Libraries

. adafruit_hid


12 Feb 2021 . Tested with CircuitPython Pico 6.2.0-beta.2

import time

import board
import digitalio
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.keycode import Keycode

A simple neat keyboard demo in CircuitPython

modified for an arcade control cabinet.

#keyboard 1 IO is for player 1
#keyboard 2 IO is for player 2

The pins we’ll use, each will have an internal pullup

#this list is for the IO Pins
keypress1_pins = [
board.GP0, # up P1
board.GP1, # down P1
board.GP2, # left P1
board.GP10, # right P1
board.GP7, # upper blue P1 (Y)
board.GP9, # upper red P1 (X)
board.GP8, # upper yellow P1 (R)
board.GP4, # lower blue P1 (B)
board.GP5, # lower red P1 (A)
board.GP6, # lower yellow P1 (R2)
board.GP11, # select / coin P1
board.GP28, # O Start P1
board.GP22, # play / menu (special key)
#this list is for the keys that are pressed for the corresponding pins above
keys1_pressed = [
#this is for the keys in the queue that are actually pressed
key1_pin_array = []

#player two io, then keys, then the array
keypress2_pins = [
board.GP12, # up P2
board.GP13, # down P2
board.GP14, # left P2
board.GP15, # right P2
board.GP19, # upper blue P2 (X)
board.GP20, # upper red P2 (Y)
board.GP21, # upper yellow P2 (R)
board.GP16, # lower blue P2 (B)
board.GP17, # lower red P2 (A)
board.GP18, # lower yellow P2 (R2)
board.GP26, # , select/coin P2
board.GP27 # . start P2
keys2_pressed = [
key2_pin_array = []
#control_key = KeyCode.

The keyboard object!

time.sleep(1) # Sleep for a bit to avoid a race condition on some systems
keyboard1 = Keyboard(usb_hid.devices)
keyboard2 = Keyboard(usb_hid.devices)
keyboard1_layout = KeyboardLayoutUS(keyboard1) # We’re in the US …
keyboard2_layout = KeyboardLayoutUS(keyboard2)

Make all pin objects inputs with pullups

for pin in keypress1_pins:
key1_pin = digitalio.DigitalInOut(pin)
key1_pin.direction = digitalio.Direction.INPUT
key1_pin.pull = digitalio.Pull.UP

for pin in keypress2_pins:
key2_pin = digitalio.DigitalInOut(pin)
key2_pin.direction = digitalio.Direction.INPUT
key2_pin.pull = digitalio.Pull.UP

For most CircuitPython boards:

control_key = 0

last_pressed1 = 0
this_pressed1 = 0
last_pressed2 = 0
this_pressed2 = 0

while True:
# Check each pin
# build a bit array of the port status…
#if grounded, put in a 1, if not put in a 0 for activated button
i = 0
for key1_pin in key1_pin_array:
if not (key1_pin.value) and not (last_pressed1 & 1<<i): #not value means grounded… pin press, not in last pressed array
this_pressed1 |= 1<<i # set array value[i])
if (last_pressed1 & 1<<i and key1_pin.value):
this_pressed1 = 0<<i
i = i + 1
last_pressed1 = this_pressed1
i = 0
for key2_pin in key2_pin_array:
if not (key2_pin.value) and not (last_pressed2 & 1<<i): #not value means grounded… pin press, not in last pressed array
this_pressed2 |= 1<<i # set array value[i])
if (last_pressed2 & 1 << i and key2_pin.value):
this_pressed2 = 0<<i
i = i+1
last_pressed2 = this_pressed2


Retroarch.cfg in configs/all had to be modified for the emulated keyboard to work


Keyboard input. Will recognize letters (“a” to “z”) and special/keypad keys):

(removed for brevity)

Keyboard input, Joypad and Joyaxis will all obey the “nul” bind,

rather than relying on a default.

input_player1_a = “r”
input_player1_b = “e”
input_player1_y = “num3”
input_player1_x = “num4”
input_player1_start = “v”
input_player1_select = “f”
input_player1_l = “num5”
input_player1_r = “t”
input_player1_left = “a”
input_player1_right = “d”
input_player1_up = “w”
input_player1_down = “s”
input_player1_l2 = nul
input_player1_r2 = nul

input_player1_l3 =

input_player1_r3 =

input_player2_a = “o”
input_player2_b = “i”
input_player2_y = “num8”
input_player2_x = “num9”
input_player2_start = “period”
input_player2_select = “l”
input_player2_l = “num0”
input_player2_r = “p”
input_player2_left = “h”
input_player2_right = “k”
input_player2_up = “u”
input_player2_down = “j”
input_player2_l2 = nul
#input_player2_r2 = nul

Here is the SVG for the laser cut control panel


1 Like

I finally got around to publishing the timelapse footage and photos to call this one done.