Log In  

Ever wish PICO-8 had dual analog stick support? Me too, so I wrote Pinput. Pinput is a Lua library and suite of external helper apps to provide XInput-like gamepad support to PICO-8, without requiring binary patching. The library and helpers use the GPIO area of cartridge RAM to communicate, making Pinput a sort of virtual peripheral plugged into an imaginary expansion port. (The P8T Twitter client uses GPIO the same way.)

You can try it now if you have a gamepad that works with your browser. (You may want to test it first with this gamepad test page.)

Demo video:

Pinput working in web browser with Logitech F310 gamepad

What do you get?

  • Up to 8 players
  • Per player:
  • 2 analog thumbsticks
  • 2 analog triggers
  • 4-way digital D-pad
  • 4 digital action buttons (ABXY)
  • 2 digital bumper/shoulder buttons
  • 2 digital thumbstick buttons
  • 2 or 3 digital menu buttons (Start and Back, plus Guide/Xbox/PS button on macOS and web)

Pinput currently works on:

  • macOS: with up to 8 gamepads supported by Apple's Game Controller API (newer Xbox One, DualShock 4, DualSense, MFi)
  • Windows: with up to 4 gamepads supported by XInput (360, Xbox One)
  • Web: depends on your OS and browser's support for the web gamepad API, but expect USB/BT HID gamepads to work, and on Windows, probably XInput too

Coming soon:

  • rumble/vibration support
  • battery level/charging status for wireless controllers (macOS and Windows only)
  • Linux

How does it work?

When you initialize the Pinput library in a cartridge, it writes a magic UUID to the first 16 bytes of the GPIO area. The external helpers look for this magic UUID in PICO-8's memory to identify the GPIO area. On macOS, the helper uses Mach virtual memory APIs to map GPIO into the helper's address space. On Windows, the helper uses ReadProcessMemory/WriteProcessMemory from the Windows memory API. Cartridges exported in web format expose GPIO as an array of integers in JavaScript, so the web version just needs a little extra JavaScript. Once the helper knows where GPIO is, it can read and write gamepad data there for the cartridge to use.

All platforms have the same interface between a cartridge and the helper, so you can run the same Pinput-enabled cartridge on macOS, Windows, or your browser.


I wanted to do a Geometry Wars demake but still have twinstick support. 😁

Claw ship firing shots at all angles

P#98548 2021-10-12 18:25 ( Edited 2021-10-12 19:09)

good work but the external program is a killer for standalone release :/

one quality of life improvement would be to merge with regular btn functions for standard axis/buttons - that would make the game compatible with both pinput and regular input schemes.

note: the pinput lua code could use a bit less tokens (like jscript libs, a minified version would be handy!)

P#98550 2021-10-12 19:27 ( Edited 2021-10-12 19:30)

@freds72 good notes!

I definitely want to support standalone executables someday, but patching binaries on 4 supported architectures (Windows 32-bit x86, macOS 64-bit x86, Linux 64-bit x86, and Linux 32-bit ARM) is probably an order of magnitude more work than manipulating cartridge memory from a separate program.

I like the idea of wrapping BTN()/BTNP() to read from Pinput for O/X buttons and the D-pad. Might add that to the next release as another chunk of Lua.

And yeah, pinput.lua is very verbose right now. I'll see about minifying it — not everyone is going to need the button constants or the player index checks, for example, and a minified version could trade those convenience features for reduced token count.

P#98552 2021-10-12 19:55
:: touk

Very cool idea, I will experiment with it!

P#98616 2021-10-14 02:25

[Please log in to post a comment]

Follow Lexaloffle:        
Generated 2021-10-19 15:54:40 | 0.026s | Q:16