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.

Why?

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

Very cool idea, I will experiment with it!

P#98616 2021-10-14 02:25

Would it be possible to make it compatible with Directinput as well ? I want to make a pico8 game that is compatible with Atari VCS Paddle.

P#99543 2021-11-03 09:29

@hijongpark The next version should be able to talk to DirectInput devices as well. I'm in the process of rewriting Pinput in Rust + SDL so that I can reuse the same code base everywhere, and SDL can handle DirectInput-compatible devices on every platform (it's the same library PICO-8 itself uses). As of tonight, it's working on macOS and partially on Linux, but I haven't set up a Rust build on Windows yet.

That said, Pinput currently expects a gamepad-like controller. I'm not familiar with the Atari VCS Paddle, but if SDL doesn't recognize it as a gamepad, Pinput might have to be further customized for it to work. How does that twist stick show up to other games?

P#99860 2021-11-09 08:25 ( Edited 2021-11-09 08:26)

in windows controller settings and joy2key, it is recognized as dial and slider1 and moves between -1 and 1 just like any axes.

P#99931 2021-11-11 08:48

It's potentially doable. My original vision for Pinput is to match the capabilities of XInput and the macOS, web, and SDL game controller APIs inspired by XInput: controllers are gamepad-shaped, and have a certain number of axes, buttons, and triggers. Supporting arbitrary game controllers is out of scope for baseline Pinput, especially if I don't own that hardware and can't test with it.

However, I'd be happy to help you create a custom fork of Pinput for your game, because that sounds neat. You'd need to look for that specific controller, use SDL's general joystick API instead of the gamepad-specific API it's currently using, and map that onto Pinput's axes and buttons. Since the VCS Paddle has fewer than a gamepad, it should be trivial.

I'm currently looking into a bug with DirectInput devices on Windows, but I hope to have builds published for the cross-platform Rust + SDL version of Pinput by this weekend.

P#99949 2021-11-11 19:55

It took a little longer than I expected, but I've just released version 0.1.2 of Pinput, which includes the first iteration of the Rust + SDL version, and supports Linux in addition to macOS, Windows, and exported web cartridges. This version also adds rumble effects.

P#100659 2021-11-23 03:33 ( Edited 2021-11-23 03:33)

@hijongpark Just remembered an SDL feature that could get your Atari VCS Paddle working with Pinput, without any code changes. Try this:

P#100715 2021-11-23 21:23 ( Edited 2021-11-23 21:25)

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-29 09:45:58 | 0.033s | Q:24