Skip to content

Instantly share code, notes, and snippets.

@vitorio
Last active January 20, 2023 04:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vitorio/b92f3085041b055c0e0416545ddca598 to your computer and use it in GitHub Desktop.
Save vitorio/b92f3085041b055c0e0416545ddca598 to your computer and use it in GitHub Desktop.
Stadia gamepad + Bongos as synthetic/composite/hybrid Switch Pro controller for Taiko no Tatsujin
# sudo apt install python3-pip pkg-config libdbus-1-dev libglib2.0-dev
# sudo pip3 install nxbt
# sudo pip3 install jinja2==3.0.3 itsdangerous==2.0.1 Werkzeug==2.0.2 eventlet==0.33.0 dnspython==2.2.1
import pyjoystick.sdl2
import nxbt
import gpiozero
import sys
button3 = gpiozero.Button(24, pull_up=False)
button3.when_pressed = sys.exit
nx = nxbt.Nxbt()
# Reconnects should be on the Home screen, new connects should be on Change Grip/Order
controller_index = nx.create_controller(nxbt.PRO_CONTROLLER, reconnect_address=nx.get_switch_addresses())
nx.wait_for_connection(controller_index)
print("Connected to Switch")
NXinput = nx.create_input_packet()
SDL2NX = {}
SDL2NX['a'] = nxbt.Buttons.A
SDL2NX['b'] = nxbt.Buttons.B
SDL2NX['x'] = nxbt.Buttons.X
SDL2NX['y'] = nxbt.Buttons.Y
SDL2NX['back'] = nxbt.Buttons.MINUS
SDL2NX['start'] = nxbt.Buttons.PLUS
SDL2NX['guide'] = nxbt.Buttons.HOME
SDL2NX['dpup'] = nxbt.Buttons.DPAD_UP
SDL2NX['dpdown'] = nxbt.Buttons.DPAD_DOWN
SDL2NX['dpleft'] = nxbt.Buttons.DPAD_LEFT
SDL2NX['dpright'] = nxbt.Buttons.DPAD_RIGHT
SDL2NX['leftshoulder'] = nxbt.Buttons.L
SDL2NX['rightshoulder'] = nxbt.Buttons.R
SDL2NX['leftstick'] = nxbt.Buttons.L_STICK_PRESS
SDL2NX['rightstick'] = nxbt.Buttons.R_STICK_PRESS
def key_received(key):
controller_name = key.joystick
key_name = key.keyname
key_value = key.value
key_mapping = pyjoystick.sdl2.get_mapping_name(key.joystick, key)
# Bongos are YXAB clockwise from upper left
# Ignore start/pause and right trigger (microphone)
# Remaps are Taiko no Tatsujin defaults
if controller_name == 'limited MAYFLASH GameCube Controller Adapter':
if key_mapping == 'a':
NXinput[SDL2NX['x']] = bool(key_value)
elif key_mapping == 'b':
NXinput[SDL2NX['dpleft']] = bool(key_value)
elif key_mapping == 'x':
NXinput[SDL2NX['b']] = bool(key_value)
elif key_mapping == 'y':
NXinput[SDL2NX['dpright']] = bool(key_value)
# Stadia controller
elif controller_name == 'Google LLC Stadia Controller rev. A':
if key_mapping in ['a', 'b', 'x', 'y', 'back', 'start', 'guide', 'leftshoulder', 'rightshoulder']:
NXinput[SDL2NX[key_mapping]] = bool(key_value)
elif key_mapping in ['dpup', 'dpdown', 'dpleft', 'dpright']:
for dpad_key in ['dpup', 'dpdown', 'dpleft', 'dpright']:
if key_mapping == dpad_key:
NXinput[SDL2NX[dpad_key]] = bool(key_value)
else:
NXinput[SDL2NX[dpad_key]] = not bool(key_value)
elif key_mapping in ['leftstick', 'rightstick']:
NXinput[SDL2NX[key_mapping]] = bool(key_value)
if key_mapping == 'leftstick':
NXinput[nxbt.Sticks.LEFT_STICK]['PRESSED'] = bool(key_value)
else:
NXinput[nxbt.Sticks.RIGHT_STICK]['PRESSED'] = bool(key_value)
elif key_name == 'Hat 0 [Centered]':
NXinput[SDL2NX['dpup']] = bool(key_value)
NXinput[SDL2NX['dpdown']] = bool(key_value)
NXinput[SDL2NX['dpleft']] = bool(key_value)
NXinput[SDL2NX['dpright']] = bool(key_value)
elif key_name == 'Hat 0 [Up Right]':
NXinput[SDL2NX['dpup']] = bool(key_value)
NXinput[SDL2NX['dpdown']] = not bool(key_value)
NXinput[SDL2NX['dpleft']] = not bool(key_value)
NXinput[SDL2NX['dpright']] = bool(key_value)
elif key_name == 'Hat 0 [Down Right]':
NXinput[SDL2NX['dpup']] = not bool(key_value)
NXinput[SDL2NX['dpdown']] = bool(key_value)
NXinput[SDL2NX['dpleft']] = not bool(key_value)
NXinput[SDL2NX['dpright']] = bool(key_value)
elif key_name == 'Hat 0 [Up Left]':
NXinput[SDL2NX['dpup']] = bool(key_value)
NXinput[SDL2NX['dpdown']] = not bool(key_value)
NXinput[SDL2NX['dpleft']] = bool(key_value)
NXinput[SDL2NX['dpright']] = not bool(key_value)
elif key_name == 'Hat 0 [Down Left]':
NXinput[SDL2NX['dpup']] = not bool(key_value)
NXinput[SDL2NX['dpdown']] = bool(key_value)
NXinput[SDL2NX['dpleft']] = bool(key_value)
NXinput[SDL2NX['dpright']] = not bool(key_value)
# Left and right triggers are analog
elif key_name == 'Button 14':
NXinput[nxbt.Buttons.ZL] = bool(key_value)
elif key_name == 'Button 13':
NXinput[nxbt.Buttons.ZR] = bool(key_value)
# Capture is on the opposite side
elif key_name == 'Button 12':
NXinput[nxbt.Buttons.CAPTURE] = bool(key_value)
elif key_mapping == 'leftx':
NXinput[nxbt.Sticks.LEFT_STICK]['X_VALUE'] = key_value * 100
elif key_mapping == 'lefty':
NXinput[nxbt.Sticks.LEFT_STICK]['Y_VALUE'] = key_value * -100
elif key_mapping == 'rightx':
NXinput[nxbt.Sticks.RIGHT_STICK]['X_VALUE'] = key_value * 100
elif key_mapping == 'righty':
NXinput[nxbt.Sticks.RIGHT_STICK]['Y_VALUE'] = key_value * -100
nx.set_controller_input(controller_index, NXinput)
pyjoystick.sdl2.run_event_loop(None, None, key_received)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment