Skip to main content
Every recipe on this page needs hardware mode and a Rebind Link whose USB profile includes a joypad; see Change the USB identity. Attach the controller in Peripherals the way you attach a keyboard or mouse; see Attach your devices. With no script running, the controller passes straight through to the Link’s joypad, so games keep seeing it. Scripts treat a controller like any other input:
  • Buttons are keys. PadA, PadLB, PadUp and the rest arrive as down and up events and work with rb.bind, rb.bind.remap, rb.input.is_down and rb.hid.down. A controller button sent through rb.hid goes to the Link’s joypad; a keyboard key or mouse button goes to the keyboard or mouse.
  • Sticks and triggers are axes. An rb.on("axis", fn) handler sees each change; return false to keep that value off the joypad. rb.input.axis(name) reads the current value, and rb.hid.axis(name, value) sets one on the joypad.
  • The joypad is shared. A button a script presses adds to the controller’s buttons. An axis a script sets wins over the controller’s until rb.hid.joypad_reset(), which Rebind also runs when the script stops.
Button and axis names, ranges, supported controllers, and limits are in Controllers. Press Left Ctrl + Left Alt + K (Left Control + Left Option + K on macOS) at any time to stop every running script and release held input. On Windows, the Link’s joypad shows up in the game controller panel: press Win+R, run joy.cpl, select the joypad, and click Properties to watch its buttons and axes while a script runs.

Watch a controller

Observer events see every input without taking any of it, so the controller keeps working while this script logs what it does. The first input from each controller logs its name, vid:pid, and kind.
Watch the output with rebind logs.

Buttons as keyboard keys

rb.bind.remap holds the target for as long as the button is held, so a controller types, navigates, and holds modifiers. The remapped buttons stop reaching the joypad; everything else still does.
The bumpers switch browser tabs; A and B confirm and cancel dialogs.

A stick as the mouse

The left stick moves the cursor and the face buttons click. The axis handler keeps the left stick off the joypad; rb.input.axis still reads it on every tick. Holding RB slows the cursor for precise work.
tick_rate=125 runs the tick every 8 ms, which is smooth enough for a cursor.

Remap the joypad

A game sees the joypad, so remapping it remaps the controller for every game at once. Here A and B swap, the left stick’s vertical axis inverts, and the right trigger gets a softer curve: half pressed reads a quarter, fully pressed still reads full.
Stopping the script returns the joypad to the plain controller.

Keyboard and mouse as a controller

The reverse direction: the mouse aims with the right stick, WASD moves the left stick, and clicks pull the triggers. mouse_block=true lets the move handler keep mouse movement from reaching the computer while the mouse is captured. F9 releases the mouse so the cursor works again, and F10 stops the script.
A real controller keeps working beside it. While a key or the mouse is moving an axis, the script’s value wins; once both have been still for IDLE_MS, the controller has the axes again. To aim faster, raise GAIN.

Rapid fire

Holding X taps the joypad’s X about twelve times a second until you let go. rb.run repeats the press in a coroutine, and the bind’s release stops it.
To rapid-fire a keyboard key instead, change "PadX" in rb.hid.press and rb.hid.up to that key’s name.

A combo that plays a motion

Pressing both bumpers together plays a quarter-circle motion on the joypad (down, down and right, right) and then X. Every button still reaches the joypad as normal, because the script only observes.