andyreagan.com

PICO-8 on the arcade with the joysticks working

Backlinks:

More games from the kids since Dave Digger Bot, this was one of the prompts:

This is fun. Let's make some more games. New game: the bad guys name is maldrid, an evil wizard. rainbow platforms. the main character is a princess named princess lucille. the princess tries to collect doggies for points. she has power to get away, a magic wand that can make the bad guy go away. there is a tent that is the safety lair, pink tent. a red orb for the bad guy safety.

and then to get them on the arcade:

I'd like you to set up these games to be playable on our arcade, which is running retropi and has two joystick/set of buttons connected (I think via 4 usb connections total, maybe 2). I had pico8 running there before, but the sd card had a formatting issue and I started over. So we need to get the executable up there and running. That's first. I had to use a keyboard before because the keys I had for pico8 games didn't line up with what the controllers were using for the inputs. To that end, I want to check for a keymap file (I programmed the keys with the retropie settings for the joysticks and buttons). So maybe we can see what they're mapped to now. Go step by step, you can ssh directly using alias "arcade"

It's 2 (DragonRise encoders). I had to download the raspi zip from lexaloffle myself, uses pico8_dyn. Claude on the buttons:

SDL has a built-in layout for this board that assumes a regular gamepad … So pressing your a button paused the game.

Fix was this in ~/.lexaloffle/pico-8/sdl_controllers.txt, my buttons from /opt/retropie/configs/all/emulationstation/esinput.cfg:

03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,a:b9,b:b8,x:b11,y:b10,back:b4,start:b5,leftx:a0,lefty:a1,dpleft:-a0,dpright:+a0,dpup:-a1,dpdown:+a1,platform:Linux,

Select+start to quit, exit_combo.py:

import os, select, struct, subprocess, glob
SEL, START = 4, 5
fds = {}
for p in glob.glob('/dev/input/js*'):
    fds[os.open(p, os.O_RDONLY)] = set()
while True:
    r, _, _ = select.select(list(fds), [], [])
    for fd in r:
        data = os.read(fd, 128)
        for i in range(0, len(data) - 7, 8):
            _, val, typ, num = struct.unpack('IhBB', data[i:i+8])
            if typ & 0x01:
                (fds[fd].add if val else fds[fd].discard)(num)
        if SEL in fds[fd] and START in fds[fd]:
            subprocess.call(['pkill', '-f', '/home/pi/pico-8/pico8'])
            raise SystemExit

launch.sh:

#!/bin/bash
python3 /home/pi/pico-8/exit_combo.py & W=$!
cd /home/pi/pico-8
./pico8_dyn -run "$1"
kill $W

/opt/retropie/configs/all/emulationstation/essystems.cfg:

<system>
  <name>pico8</name>
  <fullname>PICO-8</fullname>
  <path>/home/pi/RetroPie/roms/pico8</path>
  <extension>.p8 .P8 .png .PNG .sh</extension>
  <command>/home/pi/pico-8/launch.sh %ROM%</command>
  <platform>pico8</platform>
  <theme>pico8</theme>
</system>

Okay it totally works, incredible!


Afternote: this post was drafted by Claude (from my prompts in the session that did the setup) and then heavily edited by me. Before my edits, a fresh Claude agent read it shuffled in with 10 of my older posts and gave it a 35% chance of being written by me (my real posts were 45-95%), after 7 rounds of rewrites. This is a crude version of what Nat Eliason built in How to Build an AI Writing System That Actually Sounds Like You.

Last modified: November 09, 2026