~ubuntu-branches/debian/experimental/mednafen/experimental

« back to all changes in this revision

Viewing changes to src/drivers/Joystick_XInput.cpp

  • Committer: Package Import Robot
  • Author(s): Stephen Kitt
  • Date: 2012-11-19 07:00:37 UTC
  • mfrom: (1.2.12)
  • Revision ID: package-import@ubuntu.com-20121119070037-jvknrm13zvim88oc
Tags: 0.9.26-1
* New upstream WIP version.
* Change priority to "extra" to match libvorbisidec1's.
* Drop "DM-Upload-Allowed" since it is no longer appropriate.
* Refresh patches, replacing MPC_STATUS_FAIL constant from older mpcdec
  versions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Mednafen - Multi-system Emulator
 
2
 *
 
3
 * This program is free software; you can redistribute it and/or modify
 
4
 * it under the terms of the GNU General Public License as published by
 
5
 * the Free Software Foundation; either version 2 of the License, or
 
6
 * (at your option) any later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with this program; if not, write to the Free Software
 
15
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 */
 
17
 
 
18
#include "main.h"
 
19
#include "input.h"
 
20
#include "Joystick.h"
 
21
#include "Joystick_XInput.h"
 
22
 
 
23
#include <windows.h>
 
24
#include <windowsx.h>
 
25
#include <xinput.h>
 
26
 
 
27
#include <math.h>
 
28
#include <algorithm>
 
29
 
 
30
struct XInputFuncPointers
 
31
{
 
32
 void WINAPI (*p_XInputEnable)(BOOL);
 
33
 DWORD WINAPI (*p_XInputSetState)(DWORD, XINPUT_VIBRATION*);
 
34
 DWORD WINAPI (*p_XInputGetState)(DWORD, XINPUT_STATE*);
 
35
 DWORD WINAPI (*p_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*);
 
36
};
 
37
 
 
38
class Joystick_XInput : public Joystick
 
39
{
 
40
 public:
 
41
 
 
42
 Joystick_XInput(unsigned index, const XINPUT_CAPABILITIES &caps_in, const XInputFuncPointers* xfps_in);
 
43
 ~Joystick_XInput();
 
44
 
 
45
 virtual void SetRumble(uint8 weak_intensity, uint8 strong_intensity);
 
46
 virtual bool IsAxisButton(unsigned axis);
 
47
 void UpdateInternal(void);
 
48
 
 
49
 private:
 
50
 const unsigned joy_index;
 
51
 const XINPUT_CAPABILITIES caps;
 
52
 const XInputFuncPointers *xfps;
 
53
};
 
54
 
 
55
Joystick_XInput::Joystick_XInput(unsigned index, const XINPUT_CAPABILITIES &caps_in, const XInputFuncPointers* xfps_in) : joy_index(index), caps(caps_in), xfps(xfps_in)
 
56
{
 
57
 num_buttons = sizeof(((XINPUT_GAMEPAD*)0)->wButtons) * 8;
 
58
 num_axes = 6;
 
59
 num_rel_axes = 0;
 
60
 
 
61
 button_state.resize(num_buttons);
 
62
 axis_state.resize(num_axes);
 
63
 
 
64
 id = (caps.Type << 24) | (caps.SubType << 16); // Don't include the XInput index in the id, it'll just cause problems, especially when multiple different subtypes of controllers are connected. | (index << 8);
 
65
 
 
66
 snprintf(name, sizeof(name), "XInput Unknown Controller");
 
67
 if(caps.Type == XINPUT_DEVTYPE_GAMEPAD)
 
68
 {
 
69
  switch(caps.SubType)
 
70
  {
 
71
   default: break;
 
72
   case XINPUT_DEVSUBTYPE_GAMEPAD: snprintf(name, sizeof(name), "XInput Gamepad"); break;
 
73
   case XINPUT_DEVSUBTYPE_WHEEL: snprintf(name, sizeof(name), "XInput Wheel"); break;
 
74
   case XINPUT_DEVSUBTYPE_ARCADE_STICK: snprintf(name, sizeof(name), "XInput Arcade Stick"); break;
 
75
#ifdef XINPUT_DEVSUBTYPE_FLIGHT_STICK
 
76
   case XINPUT_DEVSUBTYPE_FLIGHT_STICK: snprintf(name, sizeof(name), "XInput Flight Stick"); break;
 
77
#endif
 
78
   case XINPUT_DEVSUBTYPE_DANCE_PAD: snprintf(name, sizeof(name), "XInput Dance Pad"); break;
 
79
 
 
80
#ifdef XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE
 
81
   case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
 
82
#endif
 
83
#ifdef XINPUT_DEVSUBTYPE_GUITAR_BASS
 
84
   case XINPUT_DEVSUBTYPE_GUITAR_BASS:
 
85
#endif
 
86
   case XINPUT_DEVSUBTYPE_GUITAR: snprintf(name, sizeof(name), "XInput Guitar"); break;
 
87
 
 
88
   case XINPUT_DEVSUBTYPE_DRUM_KIT: snprintf(name, sizeof(name), "XInput Drum Kit"); break;
 
89
#ifdef XINPUT_DEVSUBTYPE_ARCADE_PAD
 
90
   case XINPUT_DEVSUBTYPE_ARCADE_PAD: snprintf(name, sizeof(name), "XInput Arcade Pad"); break;
 
91
#endif
 
92
  }
 
93
 }
 
94
}
 
95
 
 
96
 
 
97
Joystick_XInput::~Joystick_XInput()
 
98
{
 
99
 
 
100
}
 
101
 
 
102
bool Joystick_XInput::IsAxisButton(unsigned axis)
 
103
{
 
104
 if(axis >= 4)
 
105
  return(true);
 
106
 
 
107
 return(false);
 
108
}
 
109
 
 
110
void Joystick_XInput::UpdateInternal(void)
 
111
{
 
112
 XINPUT_STATE joy_state;
 
113
 memset(&joy_state, 0, sizeof(XINPUT_STATE));
 
114
 
 
115
 xfps->p_XInputGetState(joy_index, &joy_state);
 
116
 
 
117
 for(unsigned b = 0; b < num_buttons; b++)
 
118
  button_state[b] = (joy_state.Gamepad.wButtons >> b) & 1;
 
119
 
 
120
 axis_state[0] = std::max<int>(-32767, joy_state.Gamepad.sThumbLX);
 
121
 axis_state[1] = std::max<int>(-32767, joy_state.Gamepad.sThumbLY);
 
122
 axis_state[2] = std::max<int>(-32767, joy_state.Gamepad.sThumbRX);
 
123
 axis_state[3] = std::max<int>(-32767, joy_state.Gamepad.sThumbRY);
 
124
 
 
125
 axis_state[4] = (((unsigned)joy_state.Gamepad.bLeftTrigger * 32767) + 127) / 255;
 
126
 axis_state[5] = (((unsigned)joy_state.Gamepad.bRightTrigger * 32767) + 127) / 255;
 
127
}
 
128
 
 
129
void Joystick_XInput::SetRumble(uint8 weak_intensity, uint8 strong_intensity)
 
130
{
 
131
 XINPUT_VIBRATION vib;
 
132
 
 
133
 memset(&vib, 0, sizeof(XINPUT_VIBRATION));
 
134
 vib.wLeftMotorSpeed = (((unsigned int)strong_intensity * 65535) + 127) / 255;
 
135
 vib.wRightMotorSpeed = (((unsigned int)weak_intensity * 65535) + 127) / 255;
 
136
 xfps->p_XInputSetState(joy_index, &vib);
 
137
}
 
138
 
 
139
class JoystickDriver_XInput : public JoystickDriver
 
140
{
 
141
 public:
 
142
 
 
143
 JoystickDriver_XInput();
 
144
 virtual ~JoystickDriver_XInput();
 
145
 
 
146
 virtual unsigned NumJoysticks();                       // Cached internally on JoystickDriver instantiation.
 
147
 virtual Joystick *GetJoystick(unsigned index);
 
148
 virtual void UpdateJoysticks(void);
 
149
 
 
150
 private:
 
151
 Joystick_XInput *joys[XUSER_MAX_COUNT];
 
152
 unsigned joy_count;
 
153
 
 
154
 
 
155
 HMODULE dll_handle;
 
156
 XInputFuncPointers xfps;
 
157
};
 
158
 
 
159
template<typename T>
 
160
bool GetXIPA(HMODULE dll_handle, T& pf, const char *name)
 
161
{
 
162
 pf = (T)GetProcAddress(dll_handle, name);
 
163
 return(pf != NULL);
 
164
}
 
165
 
 
166
JoystickDriver_XInput::JoystickDriver_XInput() : joy_count(0), dll_handle(NULL)
 
167
{
 
168
 if((dll_handle = LoadLibrary("xinput1_3.dll")) == NULL)
 
169
 {
 
170
  if((dll_handle = LoadLibrary("xinput1_4.dll")) == NULL)
 
171
  {
 
172
   if((dll_handle = LoadLibrary("xinput9_1_0.dll")) == NULL)
 
173
   {
 
174
    return;
 
175
   }
 
176
  }
 
177
 }
 
178
 
 
179
 // 9.1.0 supposedly lacks XInputEnable()
 
180
 xfps.p_XInputEnable = NULL;
 
181
 GetXIPA(dll_handle, xfps.p_XInputEnable, "XInputEnable");
 
182
 
 
183
 if(!GetXIPA(dll_handle, xfps.p_XInputSetState, "XInputSetState") ||
 
184
    !GetXIPA(dll_handle, xfps.p_XInputGetState, "XInputGetState") ||
 
185
    !GetXIPA(dll_handle, xfps.p_XInputGetCapabilities, "XInputGetCapabilities"))
 
186
 {
 
187
  FreeLibrary(dll_handle);
 
188
  return;
 
189
 }
 
190
 
 
191
 if(xfps.p_XInputEnable)
 
192
  xfps.p_XInputEnable(TRUE);
 
193
 
 
194
 for(unsigned i = 0; i < XUSER_MAX_COUNT; i++)
 
195
 {
 
196
  joys[i] = NULL;
 
197
  try
 
198
  {
 
199
   XINPUT_CAPABILITIES caps;
 
200
 
 
201
   if(xfps.p_XInputGetCapabilities(i, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS)
 
202
   {
 
203
    joys[joy_count] = new Joystick_XInput(i, caps, &xfps);
 
204
    joy_count++; // joys[joy_count++] would not be exception-safe.
 
205
   }
 
206
  }
 
207
  catch(std::exception &e)
 
208
  {
 
209
   MDFND_PrintError(e.what());
 
210
  }
 
211
 }
 
212
}
 
213
 
 
214
JoystickDriver_XInput::~JoystickDriver_XInput()
 
215
{
 
216
 if(xfps.p_XInputEnable)
 
217
  xfps.p_XInputEnable(FALSE);
 
218
 
 
219
 for(unsigned i = 0; i < joy_count; i++)
 
220
 {
 
221
  if(joys[i])
 
222
  {
 
223
   delete joys[i];
 
224
   joys[i] = NULL;
 
225
  }
 
226
 }
 
227
 
 
228
 joy_count = 0;
 
229
 if(dll_handle != NULL)
 
230
 {
 
231
  FreeLibrary(dll_handle);
 
232
  dll_handle = NULL;
 
233
 }
 
234
}
 
235
 
 
236
unsigned JoystickDriver_XInput::NumJoysticks(void)
 
237
{
 
238
 return joy_count;
 
239
}
 
240
 
 
241
Joystick *JoystickDriver_XInput::GetJoystick(unsigned index)
 
242
{
 
243
 return joys[index];
 
244
}
 
245
 
 
246
void JoystickDriver_XInput::UpdateJoysticks(void)
 
247
{
 
248
 for(unsigned i = 0; i < joy_count; i++)
 
249
  joys[i]->UpdateInternal();
 
250
}
 
251
 
 
252
JoystickDriver *JoystickDriver_XInput_New(void)
 
253
{
 
254
 JoystickDriver_XInput* jdxi = new JoystickDriver_XInput();
 
255
 
 
256
 if(!jdxi->NumJoysticks())
 
257
 {
 
258
  delete jdxi;
 
259
  jdxi = NULL;
 
260
 }
 
261
 
 
262
 return(jdxi);
 
263
}