mirror of
https://github.com/valentderah/totk-pc-recomp.git
synced 2026-11-11 01:41:02 +00:00
While a game menu has the pointer the left mouse button is A, and it was Y's only default key, so keyboard and mouse players could not sort the inventory or press Y anywhere in the menus. T is now Y's second default key. A bind line in totk.ini now also removes its keys from the defaults of buttons without a line, as the remapping rows already do: with bind_X = key:t, T presses X only, not X and Y. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
145 lines
10 KiB
C
145 lines
10 KiB
C
// 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 <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
// Actions are the bit numbers of libnx 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 held with Ultrahand. 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 flight recorder: 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 (TOTK_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 totk.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:<name>" and
|
|
// "key:<name>" 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 TOTK_BIND_<action> settings (cfg_get) over the defaults: at start, and again when one of them changes.
|
|
// A key a line binds leaves the defaults of the actions that have no line.
|
|
void input_map_configure(void);
|
|
|
|
// The layout for a TOTK_PAD_LAYOUT value: "nintendo" or "xbox" (any case); "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 (TOTK_PROMPTS): the controller whose buttons the game's prompts show. Nintendo: the game's own. Xbox:
|
|
// LB RB LT RT, Menu, View and a d-pad cross for the other buttons, and the face buttons named by the label of the
|
|
// button the pad layout presses (runtime/romfs.c overlay_init, tools/make_romfs_patches.py --prompts). 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 };
|
|
// The prompts for a TOTK_PROMPTS value ("nintendo", "xbox" 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 TOTK_PAD_LAYOUT value, NULL for the game's own. The
|
|
// Nintendo layout plays an Xbox pad by position, so its folder names the face buttons the other way round
|
|
// (romfs-patches-xbox: the right button does A and is labelled B); xbox and auto put every Switch button on the button
|
|
// labelled with its letter (auto picks the layout per pad by its labels), so they share romfs-patches-xbox-label. The PC
|
|
// prompts follow no pad: romfs-patches-pc whatever the layout (romfs.c overlay_init serves romfs-patches-pc-<w>x<h>
|
|
// under that name at a game resolution of another shape).
|
|
const char *input_prompts_folder(int prompts, const char *pad_layout);
|
|
// down[pad] != 0 for the gamepad inputs held. Returns the Switch button bits (0..15) the layout's pad table presses.
|
|
uint64_t input_map_pad_buttons(const uint8_t down[PAD_COUNT], int layout);
|
|
|
|
// down[key] != 0 for the keys held. Returns the Switch button bits (0..15) the table presses.
|
|
uint64_t input_map_buttons(const uint8_t down[KEY_COUNT]);
|
|
// 1 when a key of action is held.
|
|
int input_map_held(const uint8_t down[KEY_COUNT], int action);
|
|
// out = x, y of the stick (0 left, 1 right) from its four direction actions; up is +y; a diagonal is scaled to the
|
|
// unit circle.
|
|
void input_map_stick(const uint8_t down[KEY_COUNT], int stick, int32_t out[2]);
|
|
// Mouse motion in raw counts over dt_s seconds to right-stick deflection: full deflection at 3000 / sens counts/s.
|
|
// Clamped to the unit circle, up (negative dy) is +y.
|
|
void input_mouse_stick(int32_t dx, int32_t dy, double dt_s, float sens, int32_t out[2]);
|
|
// A gamepad stick (x, y in -32768..32767, up is +y) through a round dead zone of `dead` (fraction of full deflection,
|
|
// 0..0.5): inside the circle the stick reads 0, and the rest of the travel is scaled to start at 0 at the edge, so a
|
|
// drifting stick rests at 0 and full deflection still reaches full. The result stays inside the unit square.
|
|
void input_pad_stick(int32_t x, int32_t y, float dead, int32_t out[2]);
|
|
// The dead zone of gamepad stick 0 (left) or 1 (right) for input_pad_stick, as a fraction of full deflection:
|
|
// TOTK_LSTICK_DEADZONE or TOTK_RSTICK_DEADZONE when set, else TOTK_STICK_DEADZONE (both sticks), percent clamped to 0..50.
|
|
float input_pad_deadzone(int stick);
|
|
// How far a stick (x, y in -32768..32767) is from the centre, in percent of full deflection (100 at an axis's end; a
|
|
// square gate's corner reads more).
|
|
double input_stick_percent(int32_t x, int32_t y);
|
|
|
|
// ---- the remapping rows' edits, on a copy of input_map. Pure.
|
|
// action's keys (table order) / its gamepad buttons in layout, at most max; returns how many.
|
|
int input_map_keys_of(const InputMap *m, int action, uint8_t *out, int max);
|
|
int input_map_pads_of(const InputMap *m, int action, int layout, uint8_t *out, int max);
|
|
// Key slot (0 or 1) of action becomes key; KEY_NONE clears the slot. A key another action has moves here: returns that
|
|
// action, -1 when none lost it.
|
|
int input_map_set_key(InputMap *m, int action, int slot, int key);
|
|
// action's gamepad button in layout becomes pad; PAD_NONE clears it. The action that had pad takes action's old button
|
|
// (a swap): returns it, -1 when none. A remapped button is physical, so the face buttons (A B X Y) and the changed actions
|
|
// get the result in every layout: the layout setting no longer moves them. A change that puts every button of layout
|
|
// back at its default restores the defaults of every layout instead.
|
|
int input_map_set_pad(InputMap *m, int action, int layout, int pad);
|
|
// The bind_ value that gives action its bindings of m: "" when they are the defaults (no line needed), else the entries,
|
|
// with key:default / pad:default for a part at its defaults, or "none".
|
|
void input_map_line(const InputMap *m, int action, char *out, size_t n);
|