// Keyboard, mouse and gamepad bindings, free of any window system: the tables map platform-neutral key and pad ids to // Switch actions. input_win.c translates Win32 virtual keys and SDL buttons to these ids (one place); a Linux port // translates SDL scancodes the same way. The remapping rows of the menu's Controls tab (ui/binds_page.cpp) edits a copy of the tables and writes // the bind_ lines; input_win.c applies changed lines while the game runs. Layout in docs/controls.md. #pragma once #include #include // Actions are the bit numbers of HidNpadButton (input.h); 16..23 are the stick directions, which keys drive as // stick deflection. B_SHAKE is a key of its own, never a button bit: a press shakes the right stick left and right for // the game (input.c shake_stick), which detaches a fused part from the held object. A pad shakes its own stick. enum { B_A = 0, B_B, B_X, B_Y, B_STICK_L, B_STICK_R, B_L, B_R, B_ZL, B_ZR, B_PLUS, B_MINUS, B_LEFT, B_UP, B_RIGHT, B_DOWN, B_SL_LEFT = 16, B_SL_UP, B_SL_RIGHT, B_SL_DOWN, B_SR_LEFT, B_SR_UP, B_SR_RIGHT, B_SR_DOWN, B_SHAKE = 24, ACTION_COUNT = 25 }; // Keys and mouse buttons. F1, F10, F11 and Esc belong to the menu and the window, F8 to the bug capture (bugcap.c): no ids. enum { KEY_NONE = 0, KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, // letters and digits are KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, // consecutive KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_SPACE, KEY_TAB, KEY_LSHIFT, KEY_LCTRL, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_MOUSE_L, KEY_MOUSE_R, KEY_MOUSE_M, KEY_MOUSE_X1, KEY_MOUSE_X2, // the mouse buttons are consecutive KEY_ENTER, KEY_BACKSPACE, KEY_RSHIFT, KEY_RCTRL, KEY_LALT, KEY_CAPSLOCK, KEY_INSERT, KEY_DELETE, KEY_HOME, KEY_END, KEY_PAGEUP, KEY_PAGEDOWN, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F9, KEY_F12, KEY_NUM0, KEY_NUM1, KEY_NUM2, KEY_NUM3, KEY_NUM4, KEY_NUM5, KEY_NUM6, KEY_NUM7, KEY_NUM8, KEY_NUM9, // consecutive KEY_NUM_ADD, KEY_NUM_SUB, KEY_NUM_MUL, KEY_NUM_DIV, KEY_NUM_DECIMAL, // the punctuation keys of a US keyboard, by position; the character on the key follows the keyboard layout KEY_MINUS, KEY_EQUALS, KEY_LBRACKET, KEY_RBRACKET, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_COMMA, KEY_PERIOD, KEY_SLASH, KEY_BACKSLASH, KEY_GRAVE, KEY_COUNT }; // Gamepad inputs by position (Nintendo layout, as SDL names them), platform-neutral like the key ids. ZL and ZR are the // analog triggers; input_win.c translates SDL buttons and axes to these (one place). The paddles are the back buttons // of an Xbox Elite, DualSense Edge or Steam Controller (SDL's LEFT_PADDLE1 and so on); no Switch button has them by // default, a bind line or the remapping rows add them. enum { PAD_NONE = 0, PAD_SOUTH, PAD_EAST, PAD_WEST, PAD_NORTH, PAD_LSTICK, PAD_RSTICK, PAD_L, PAD_R, PAD_START, PAD_BACK, PAD_DPAD_LEFT, PAD_DPAD_UP, PAD_DPAD_RIGHT, PAD_DPAD_DOWN, PAD_ZL, PAD_ZR, PAD_LPADDLE1, PAD_RPADDLE1, PAD_LPADDLE2, PAD_RPADDLE2, PAD_COUNT }; // Gamepad layouts (NX2NAVI_PAD_LAYOUT): which face button is Switch A. Nintendo: by position, east A, south B, west Y, // north X. Xbox: south A, east B, west X, north Y, as an Xbox pad labels them (cross A, circle B on a PlayStation pad). enum { PAD_LAYOUT_NINTENDO, PAD_LAYOUT_XBOX, PAD_LAYOUT_COUNT }; enum { INPUT_BINDING_MAX = 96, INPUT_PAD_BINDING_MAX = 48 }; typedef struct { uint8_t key; uint8_t action; } Binding; typedef struct { uint8_t pad; uint8_t action; } PadBinding; // The keyboard and mouse table and one gamepad table per layout. typedef struct InputMap { Binding keys[INPUT_BINDING_MAX]; int nkeys; PadBinding pads[PAD_LAYOUT_COUNT][INPUT_PAD_BINDING_MAX]; int npads[PAD_LAYOUT_COUNT]; } InputMap; // The tables in effect. Defaults are the layout in docs/controls.md; input_map_reset restores them. extern InputMap input_map; void input_map_reset(void); // The script and nx2navi.ini names, any case when parsed; NULL for an id without one. Actions: A B X Y LCLICK RCLICK L R ZL // ZR PLUS MINUS LEFT UP RIGHT DOWN, then LSTICK_LEFT LSTICK_UP LSTICK_RIGHT LSTICK_DOWN and the same for RSTICK (the // stick directions the keys drive), then SHAKE. Keys: a-z 0-9 space tab lshift ... (key_names in input_map.c). Pads: south east ... const char *input_action_name(int action); const char *input_key_name(int key); const char *input_pad_name(int pad); // Replaces every binding of the action `button` (an action name) with `list`: comma separated "pad:" and // "key:" entries, "key:default" / "pad:default" for that part's defaults, or "none" for no input. A part the list // names neither way is left unbound. Pad names are physical buttons, so pad entries go into the gamepad table of every // layout; pad:default keeps each layout's own button. Stick directions and SHAKE take keys only. Invalid entries are logged and // skipped; when none is valid the action keeps its bindings. 1 when applied. int input_map_bind(const char *button, const char *list); // Applies the NX2NAVI_BIND_ settings (cfg_get) over the defaults: at start, and again when one of them changes. void input_map_configure(void); // The layout for a NX2NAVI_PAD_LAYOUT value: "nintendo" or "xbox" (any case); "playstation" is the Xbox layout under its // PlayStation name (cross A, circle B, square X, triangle Y); "xbox_prompts", 0.1.9's name for the Nintendo layout with // the Xbox prompts, maps the buttons as "nintendo". Anything else ("auto", NULL) picks Nintendo when the pad's east // button is labelled A (a Switch Pro Controller, a GuliKit) and Xbox otherwise. int input_pad_layout_pick(const char *setting, int east_labelled_a); // Button prompts (NX2NAVI_PROMPTS): the controller whose buttons the game's prompts show. Nintendo: the game's own. Xbox, // PlayStation and Steam Deck: that pad's buttons (LB RB LT RT, Menu and View; L1 R1 L2 R2, Options and Create; the // Deck's A B X Y with L1 R1 L2 R2, Menu and View), and the face buttons named by the label of the button the pad layout // presses (runtime/romfs.c overlay_init, tools/pad_prompts.py). PC: the key or mouse button the keyboard defaults press // each button with, the mouse for the right stick. enum { PROMPTS_NINTENDO, PROMPTS_XBOX, PROMPTS_PC, PROMPTS_PLAYSTATION, PROMPTS_STEAMDECK }; // The prompts for a NX2NAVI_PROMPTS value ("nintendo", "xbox", "playstation", "steamdeck" or "pc", any case). Unset or // empty: Xbox while the pad layout setting is "xbox_prompts", else Nintendo. int input_prompts_pick(const char *prompts, const char *pad_layout); // The folder next to romfs-index.bin that holds those prompts for a NX2NAVI_PAD_LAYOUT value, NULL for the game's own. The // Nintendo layout plays a pad by position, so its folder names the face buttons the other way round // (romfs-patches-xbox and romfs-patches-steamdeck: the right button does A and is labelled B; // romfs-patches-playstation: it is circle); xbox and // auto put every Switch button on the button labelled with its letter, or on cross, circle, square and triangle in // that order (auto picks the layout per pad by its labels), so they share romfs-patches-