|
10 | 10 | #include "plugin.hpp" |
11 | 11 | #include "game_addrs.hpp" |
12 | 12 |
|
| 13 | +namespace Input |
| 14 | +{ |
| 15 | + void PadUpdate(int controllerIndex) |
| 16 | + { |
| 17 | + PadStatePrev = PadStateCur; |
| 18 | + PadDigitalPrev = PadDigitalCur; |
| 19 | + |
| 20 | + if (XInputGetState(controllerIndex, &PadStateCur) != ERROR_SUCCESS) |
| 21 | + PadStateCur = { 0 }; |
| 22 | + |
| 23 | + PadDigitalCur = PadStateCur.Gamepad.wButtons; |
| 24 | + |
| 25 | + // Convert analog inputs to digital bitfield |
| 26 | + { |
| 27 | + if (PadStateCur.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) |
| 28 | + PadDigitalCur |= XINPUT_DIGITAL_LEFT_TRIGGER; |
| 29 | + if (PadStateCur.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) |
| 30 | + PadDigitalCur |= XINPUT_DIGITAL_RIGHT_TRIGGER; |
| 31 | + |
| 32 | + // Check left stick |
| 33 | + if (PadStateCur.Gamepad.sThumbLY > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) |
| 34 | + PadDigitalCur |= XINPUT_DIGITAL_LS_UP; |
| 35 | + if (PadStateCur.Gamepad.sThumbLY < -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) |
| 36 | + PadDigitalCur |= XINPUT_DIGITAL_LS_DOWN; |
| 37 | + if (PadStateCur.Gamepad.sThumbLX < -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) |
| 38 | + PadDigitalCur |= XINPUT_DIGITAL_LS_LEFT; |
| 39 | + if (PadStateCur.Gamepad.sThumbLX > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) |
| 40 | + PadDigitalCur |= XINPUT_DIGITAL_LS_RIGHT; |
| 41 | + |
| 42 | + // Check right stick |
| 43 | + if (PadStateCur.Gamepad.sThumbRY > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) |
| 44 | + PadDigitalCur |= XINPUT_DIGITAL_RS_UP; |
| 45 | + if (PadStateCur.Gamepad.sThumbRY < -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) |
| 46 | + PadDigitalCur |= XINPUT_DIGITAL_RS_DOWN; |
| 47 | + if (PadStateCur.Gamepad.sThumbRX < -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) |
| 48 | + PadDigitalCur |= XINPUT_DIGITAL_RS_LEFT; |
| 49 | + if (PadStateCur.Gamepad.sThumbRX > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) |
| 50 | + PadDigitalCur |= XINPUT_DIGITAL_RS_RIGHT; |
| 51 | + } |
| 52 | + } |
| 53 | + |
| 54 | + static int HudToggleVKey = 0; |
| 55 | + |
| 56 | + void HudToggleUpdate() |
| 57 | + { |
| 58 | + static bool HudTogglePrevState = false; |
| 59 | + bool hudToggleKeyState = (GetAsyncKeyState(HudToggleVKey) & 0x8000); |
| 60 | + if (HudTogglePrevState != hudToggleKeyState) |
| 61 | + { |
| 62 | + HudTogglePrevState = hudToggleKeyState; |
| 63 | + if (!hudToggleKeyState) // if key is being released, toggle the hud flag |
| 64 | + *Game::navipub_disp_flg = (*Game::navipub_disp_flg == 0 ? 1 : 0); |
| 65 | + } |
| 66 | + } |
| 67 | + |
| 68 | + int StringToVK(std::string_view key) |
| 69 | + { |
| 70 | + // Convert key to uppercase |
| 71 | + std::string keyUpper(key); |
| 72 | + std::transform(keyUpper.begin(), keyUpper.end(), keyUpper.begin(), |
| 73 | + [](unsigned char c) { return std::toupper(c); }); |
| 74 | + |
| 75 | + static const std::unordered_map<std::string_view, int> vkMap = { |
| 76 | + {"LBUTTON", VK_LBUTTON}, {"RBUTTON", VK_RBUTTON}, {"CANCEL", VK_CANCEL}, {"MBUTTON", VK_MBUTTON}, |
| 77 | + {"XBUTTON1", VK_XBUTTON1}, {"XBUTTON2", VK_XBUTTON2}, {"BACK", VK_BACK}, {"TAB", VK_TAB}, |
| 78 | + {"CLEAR", VK_CLEAR}, {"RETURN", VK_RETURN}, {"SHIFT", VK_SHIFT}, {"CONTROL", VK_CONTROL}, |
| 79 | + {"MENU", VK_MENU}, {"PAUSE", VK_PAUSE}, {"CAPITAL", VK_CAPITAL}, {"ESCAPE", VK_ESCAPE}, |
| 80 | + {"SPACE", VK_SPACE}, {"PRIOR", VK_PRIOR}, {"NEXT", VK_NEXT}, {"END", VK_END}, |
| 81 | + {"HOME", VK_HOME}, {"LEFT", VK_LEFT}, {"UP", VK_UP}, {"RIGHT", VK_RIGHT}, |
| 82 | + {"DOWN", VK_DOWN}, {"SELECT", VK_SELECT}, {"PRINT", VK_PRINT}, {"EXECUTE", VK_EXECUTE}, |
| 83 | + {"SNAPSHOT", VK_SNAPSHOT}, {"INSERT", VK_INSERT}, {"DELETE", VK_DELETE}, {"HELP", VK_HELP}, |
| 84 | + {"LWIN", VK_LWIN}, {"RWIN", VK_RWIN}, {"APPS", VK_APPS}, {"SLEEP", VK_SLEEP}, |
| 85 | + {"NUMPAD0", VK_NUMPAD0}, {"NUMPAD1", VK_NUMPAD1}, {"NUMPAD2", VK_NUMPAD2}, {"NUMPAD3", VK_NUMPAD3}, |
| 86 | + {"NUMPAD4", VK_NUMPAD4}, {"NUMPAD5", VK_NUMPAD5}, {"NUMPAD6", VK_NUMPAD6}, {"NUMPAD7", VK_NUMPAD7}, |
| 87 | + {"NUMPAD8", VK_NUMPAD8}, {"NUMPAD9", VK_NUMPAD9}, {"MULTIPLY", VK_MULTIPLY}, {"ADD", VK_ADD}, |
| 88 | + {"SEPARATOR", VK_SEPARATOR}, {"SUBTRACT", VK_SUBTRACT}, {"DECIMAL", VK_DECIMAL}, {"DIVIDE", VK_DIVIDE}, |
| 89 | + {"F1", VK_F1}, {"F2", VK_F2}, {"F3", VK_F3}, {"F4", VK_F4}, {"F5", VK_F5}, |
| 90 | + {"F6", VK_F6}, {"F7", VK_F7}, {"F8", VK_F8}, {"F9", VK_F9}, {"F10", VK_F10}, |
| 91 | + {"F11", VK_F11}, {"F12", VK_F12}, {"F13", VK_F13}, {"F14", VK_F14}, {"F15", VK_F15}, |
| 92 | + {"F16", VK_F16}, {"F17", VK_F17}, {"F18", VK_F18}, {"F19", VK_F19}, {"F20", VK_F20}, |
| 93 | + {"F21", VK_F21}, {"F22", VK_F22}, {"F23", VK_F23}, {"F24", VK_F24}, {"NUMLOCK", VK_NUMLOCK}, |
| 94 | + {"SCROLL", VK_SCROLL} |
| 95 | + // TODO: are there any others worth adding here? |
| 96 | + }; |
| 97 | + |
| 98 | + // Check if key is a single character |
| 99 | + if (keyUpper.size() == 1) |
| 100 | + { |
| 101 | + char ch = keyUpper[0]; |
| 102 | + if (std::isalnum(ch)) |
| 103 | + return std::toupper(ch); |
| 104 | + } |
| 105 | + |
| 106 | + // Search in the vkMap |
| 107 | + auto it = vkMap.find(keyUpper); |
| 108 | + if (it != vkMap.end()) |
| 109 | + return it->second; |
| 110 | + |
| 111 | + // If not found, return -1 or some invalid value |
| 112 | + return 0; |
| 113 | + } |
| 114 | + |
| 115 | + void Update() |
| 116 | + { |
| 117 | + static bool inited = false; |
| 118 | + if (!inited) |
| 119 | + { |
| 120 | + HudToggleVKey = StringToVK(Settings::HudToggleKey); |
| 121 | + inited = true; |
| 122 | + } |
| 123 | + |
| 124 | + // Update gamepad for main controller id |
| 125 | + PadUpdate(Settings::VibrationControllerId); |
| 126 | + |
| 127 | + if (HudToggleVKey) |
| 128 | + HudToggleUpdate(); |
| 129 | + } |
| 130 | +}; |
| 131 | + |
13 | 132 | // Hooks into XINPUT1_4's DeviceIoControl via undocumented DriverHook(0xBAAD0001) call |
14 | 133 | // Allows us to detect SET_GAMEPAD_STATE ioctl and send the GIP HID command for trigger impulses |
15 | 134 | // Hopefully will work for most series controller connection types... |
|
0 commit comments