1 /* RetroArch - A frontend for libretro.
2 * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
3 * Copyright (C) 2011-2020 - Daniel De Matteis
4 *
5 * RetroArch is free software: you can redistribute it and/or modify it under the terms
6 * of the GNU General Public License as published by the Free Software Found-
7 * ation, either version 3 of the License, or (at your option) any later version.
8 *
9 * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along with RetroArch.
14 * If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #ifndef __XINPUT_JOYPAD_INL_H
18 #define __XINPUT_JOYPAD_INL_H
19
20 #include <stdint.h>
21 #include <boolean.h>
22 #include <retro_common_api.h>
23
24 #if defined(HAVE_DYNAMIC) && !defined(__WINRT__)
load_xinput_dll(void)25 static bool load_xinput_dll(void)
26 {
27 const char *version = "1.4";
28 /* Find the correct path to load the DLL from.
29 * Usually this will be from the system directory,
30 * but occasionally a user may wish to use a third-party
31 * wrapper DLL (such as x360ce); support these by checking
32 * the working directory first.
33 *
34 * No need to check for existance as we will be checking dylib_load's
35 * success anyway.
36 */
37
38 g_xinput_dll = dylib_load("xinput1_4.dll");
39 if (!g_xinput_dll)
40 {
41 g_xinput_dll = dylib_load("xinput1_3.dll");
42 version = "1.3";
43 }
44
45 if (!g_xinput_dll)
46 {
47 RARCH_ERR("[XInput]: Failed to load XInput, ensure DirectX and controller drivers are up to date.\n");
48 return false;
49 }
50
51 RARCH_LOG("[XInput]: Found XInput v%s.\n", version);
52 return true;
53 }
54 #endif
55
xinput_joypad_button_state(unsigned xuser,uint16_t btn_word,unsigned port,uint16_t joykey)56 static int16_t xinput_joypad_button_state(
57 unsigned xuser, uint16_t btn_word,
58 unsigned port, uint16_t joykey)
59 {
60 unsigned hat_dir = GET_HAT_DIR(joykey);
61
62 if (hat_dir)
63 {
64 switch (hat_dir)
65 {
66 case HAT_UP_MASK:
67 return (btn_word & XINPUT_GAMEPAD_DPAD_UP);
68 case HAT_DOWN_MASK:
69 return (btn_word & XINPUT_GAMEPAD_DPAD_DOWN);
70 case HAT_LEFT_MASK:
71 return (btn_word & XINPUT_GAMEPAD_DPAD_LEFT);
72 case HAT_RIGHT_MASK:
73 return (btn_word & XINPUT_GAMEPAD_DPAD_RIGHT);
74 default:
75 break;
76 }
77 /* hat requested and no hat button down */
78 }
79 else if (joykey < g_xinput_num_buttons)
80 return (btn_word & button_index_to_bitmap_code[joykey]);
81 return 0;
82 }
83
xinput_joypad_axis_state(XINPUT_GAMEPAD * pad,unsigned port,uint32_t joyaxis)84 static int16_t xinput_joypad_axis_state(
85 XINPUT_GAMEPAD *pad,
86 unsigned port, uint32_t joyaxis)
87 {
88 int16_t val = 0;
89 int axis = -1;
90 bool is_neg = false;
91 bool is_pos = false;
92 /* triggers (axes 4,5) cannot be negative */
93 if (AXIS_NEG_GET(joyaxis) <= 3)
94 {
95 axis = AXIS_NEG_GET(joyaxis);
96 is_neg = true;
97 }
98 else if (AXIS_POS_GET(joyaxis) <= 5)
99 {
100 axis = AXIS_POS_GET(joyaxis);
101 is_pos = true;
102 }
103 else
104 return 0;
105
106 switch (axis)
107 {
108 case 0:
109 val = pad->sThumbLX;
110 break;
111 case 1:
112 val = pad->sThumbLY;
113 break;
114 case 2:
115 val = pad->sThumbRX;
116 break;
117 case 3:
118 val = pad->sThumbRY;
119 break;
120 case 4:
121 val = pad->bLeftTrigger * 32767 / 255;
122 break; /* map 0..255 to 0..32767 */
123 case 5:
124 val = pad->bRightTrigger * 32767 / 255;
125 break;
126 }
127
128 if (is_neg && val > 0)
129 return 0;
130 else if (is_pos && val < 0)
131 return 0;
132 /* Clamp to avoid overflow error. */
133 else if (val == -32768)
134 return -32767;
135 return val;
136 }
137
138 #endif
139