// Host input for nn::hid (runtime/ov_input.c): an SDL3 gamepad (no SDL window needed), the keyboard and the mouse, // merged into Switch npad button bits and stick axes. Button order follows libnx HidNpadButton (ISC). The key and pad // bindings are the tables in input_map.c (totk.ini overrides them). The keyboard and the mouse come from the window // system's back end (input_wsys.h: input_win.c with Win32, input_sdl.c with SDL), which also owns the cursor capture. // Keys and their map: docs/controls.md. // The gamepad also rumbles (input_rumble) and, when it has a gyro and an accelerometer, feeds the six-axis sensor from a // thread of its own (input_motion_start). Every SDL call on the gamepad is made under `lock`. #include #include #include #include #include #include #include "cfg.h" #include "host.h" #include "input.h" #include "input_map.h" #include "input_wsys.h" #include "nvn_api.h" #include "ui/menu.h" #include "vk.h" #include "platform/platform.h" enum { STICK_MAX = 32767, STICK_DIR = 16384, TRIGGER_ON = 16384, RESCAN_MS = 1000 }; static PlatMutex lock = PLAT_MUTEX_INIT; static int state; // 0 not started, 1 running, -1 disabled or SDL failed static volatile int32_t g_block, g_menu; // text entry / host menu: 0 off, 1 open, 2 waiting for release // The device the player used last (input_kbm_last): 1 keyboard and mouse, 0 the gamepad. A pad counts once a button is // down or a stick is past half way (a drifting stick never switches), the mouse once it moved MOUSE_USED raw counts // within one poll (a slow deliberate move does; a desk bump does not), the keyboard with any key or mouse button. enum { PAD_USED = 16384, MOUSE_USED = 6 }; static volatile int32_t g_kbm_last = 1; int input_kbm_last(void) { return __atomic_load_n(&g_kbm_last, __ATOMIC_RELAXED); } static SDL_Gamepad *pad; static uint64_t next_scan; static int pad_rumble; // the open gamepad has rumble motors static volatile int32_t pad_labels[4]; // ... and the labels of its south, east, west, north buttons (PAD_LABEL_*), any thread static int pad_east_a; // ... and labels its east face button A (Nintendo layout under TOTK_PAD_LAYOUT=auto) static int pad_layout = -1; // PAD_LAYOUT_* in effect for the open gamepad, -1 to pick again; live (cfg_version) static unsigned pad_layout_seen; static volatile int32_t pad_layout_shown = -1; // pad_layout for the menu (any thread), -1 without a gamepad static SDL_JoystickID sensor_pad; // the gamepad whose sensors the motion thread set up, 0 none static int sensor_ok; // ... and it has both sensors, enabled static int motion_thread; // 0 not started, 1 running, -1 off (TOTK_MOTION=0, no SDL) // SDL buttons of the gamepad inputs (input_map.h PAD_*), by position; PAD_ZL and PAD_ZR are the triggers (axes). static const SDL_GamepadButton pad_sdl[PAD_COUNT] = { [PAD_SOUTH] = SDL_GAMEPAD_BUTTON_SOUTH, [PAD_EAST] = SDL_GAMEPAD_BUTTON_EAST, [PAD_WEST] = SDL_GAMEPAD_BUTTON_WEST, [PAD_NORTH] = SDL_GAMEPAD_BUTTON_NORTH, [PAD_LSTICK] = SDL_GAMEPAD_BUTTON_LEFT_STICK, [PAD_RSTICK] = SDL_GAMEPAD_BUTTON_RIGHT_STICK, [PAD_L] = SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, [PAD_R] = SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, [PAD_START] = SDL_GAMEPAD_BUTTON_START, [PAD_BACK] = SDL_GAMEPAD_BUTTON_BACK, [PAD_DPAD_LEFT] = SDL_GAMEPAD_BUTTON_DPAD_LEFT, [PAD_DPAD_UP] = SDL_GAMEPAD_BUTTON_DPAD_UP, [PAD_DPAD_RIGHT] = SDL_GAMEPAD_BUTTON_DPAD_RIGHT, [PAD_DPAD_DOWN] = SDL_GAMEPAD_BUTTON_DPAD_DOWN, [PAD_LPADDLE1] = SDL_GAMEPAD_BUTTON_LEFT_PADDLE1, [PAD_RPADDLE1] = SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1, [PAD_LPADDLE2] = SDL_GAMEPAD_BUTTON_LEFT_PADDLE2, [PAD_RPADDLE2] = SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2, }; // TOTK_INPUT_SCRIPT=: lines "