Mercurial > sdl-ios-xcode
comparison src/joystick/win32/SDL_dxjoystick.c @ 2198:fe19afb86473
Split acinclude.m4 into its component parts for easy updating
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 15 Jul 2007 01:51:11 +0000 |
parents | c121d94672cb |
children | 034440120c38 e1da92da346c 0906692aa6a4 |
comparison
equal
deleted
inserted
replaced
2197:2ff40f30af31 | 2198:fe19afb86473 |
---|---|
42 #define WIN32_LEAN_AND_MEAN | 42 #define WIN32_LEAN_AND_MEAN |
43 #include <windows.h> | 43 #include <windows.h> |
44 | 44 |
45 #define DIRECTINPUT_VERSION 0x0500 | 45 #define DIRECTINPUT_VERSION 0x0500 |
46 #include <dinput.h> | 46 #include <dinput.h> |
47 #ifdef _MSC_VER | |
48 /* Used for the c_dfDIJoystick2 symbol (no imports are used) */ | |
49 # pragma comment (lib, "dinput.lib") | |
50 #endif | |
51 #include <dxerr9.h> /* From DirectX SDK 9c */ | |
52 #ifdef _MSC_VER | |
53 # pragma comment (lib, "dxerr9.lib") | |
54 #endif | |
55 | |
56 /* an ISO hack for VisualC++ */ | |
57 #ifdef _MSC_VER | |
58 #define snprintf _snprintf | |
59 #endif | |
47 | 60 |
48 #define INPUT_QSIZE 32 /* Buffer up to 32 input messages */ | 61 #define INPUT_QSIZE 32 /* Buffer up to 32 input messages */ |
49 | |
50 extern HINSTANCE SDL_Instance; | |
51 extern int DX5_Load(); | |
52 extern void DX5_Unload(); | |
53 extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion, | |
54 LPDIRECTINPUT * ppDI, | |
55 LPUNKNOWN punkOuter); | |
56 | |
57 static LPDIRECTINPUT dinput = NULL; | |
58 | |
59 #define MAX_JOYSTICKS 8 | 62 #define MAX_JOYSTICKS 8 |
60 #define MAX_INPUTS 256 /* each joystick can have up to 256 inputs */ | 63 #define MAX_INPUTS 256 /* each joystick can have up to 256 inputs */ |
61 #define AXIS_MIN -32768 /* minimum value for axis coordinate */ | 64 #define AXIS_MIN -32768 /* minimum value for axis coordinate */ |
62 #define AXIS_MAX 32767 /* maximum value for axis coordinate */ | 65 #define AXIS_MAX 32767 /* maximum value for axis coordinate */ |
63 #define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/100) /* 1% motion */ | 66 #define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/100) /* 1% motion */ |
64 | 67 |
68 /* external variables referenced. */ | |
69 extern HINSTANCE SDL_Instance; | |
70 extern HWND SDL_Window; | |
71 | |
72 | |
73 /* local variables */ | |
74 static LPDIRECTINPUT dinput = NULL; | |
75 extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion, | |
76 LPDIRECTINPUT * ppDI, | |
77 LPUNKNOWN punkOuter); | |
78 static DIDEVICEINSTANCE SYS_Joystick[MAX_JOYSTICKS]; /* array to hold joystick ID values */ | |
79 static int SYS_NumJoysticks; | |
80 static HINSTANCE DInputDLL = NULL; | |
81 | |
82 | |
83 /* local prototypes */ | |
84 static void SetDIerror(const char *function, HRESULT code); | |
85 static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE * | |
86 pdidInstance, VOID * pContext); | |
87 static BOOL CALLBACK EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, | |
88 LPVOID pvRef); | |
89 static Uint8 TranslatePOV(DWORD value); | |
90 static int SDL_PrivateJoystickAxis_Int(SDL_Joystick * joystick, Uint8 axis, | |
91 Sint16 value); | |
92 static int SDL_PrivateJoystickHat_Int(SDL_Joystick * joystick, Uint8 hat, | |
93 Uint8 value); | |
94 static int SDL_PrivateJoystickButton_Int(SDL_Joystick * joystick, | |
95 Uint8 button, Uint8 state); | |
96 | |
97 | |
98 /* local types */ | |
65 typedef enum Type | 99 typedef enum Type |
66 { BUTTON, AXIS, HAT } Type; | 100 { BUTTON, AXIS, HAT } Type; |
67 | |
68 /* array to hold joystick ID values */ | |
69 static DIDEVICEINSTANCE SYS_Joystick[MAX_JOYSTICKS]; | |
70 static int SYS_NumJoysticks; | |
71 | |
72 extern HWND SDL_Window; | |
73 | 101 |
74 typedef struct input_t | 102 typedef struct input_t |
75 { | 103 { |
76 /* DirectInput offset for this input type: */ | 104 /* DirectInput offset for this input type: */ |
77 DWORD ofs; | 105 DWORD ofs; |
85 | 113 |
86 /* The private structure used to keep track of a joystick */ | 114 /* The private structure used to keep track of a joystick */ |
87 struct joystick_hwdata | 115 struct joystick_hwdata |
88 { | 116 { |
89 LPDIRECTINPUTDEVICE2 InputDevice; | 117 LPDIRECTINPUTDEVICE2 InputDevice; |
118 DIDEVCAPS Capabilities; | |
90 int buffered; | 119 int buffered; |
91 | 120 |
92 input_t Inputs[MAX_INPUTS]; | 121 input_t Inputs[MAX_INPUTS]; |
93 int NumInputs; | 122 int NumInputs; |
94 }; | 123 }; |
95 | 124 |
96 /* Convert a DirectInput return code to a text message */ | 125 /* Convert a DirectInput return code to a text message */ |
97 static void | 126 static void |
98 SetDIerror(char *function, int code) | 127 SetDIerror(const char *function, HRESULT code) |
99 { | 128 { |
100 static char *error; | 129 SDL_SetError("%s() [%s]: %s", function, |
101 static char errbuf[1024]; | 130 DXGetErrorString9(code), DXGetErrorDescription9(code)); |
102 | 131 } |
103 errbuf[0] = 0; | 132 |
104 switch (code) { | 133 |
105 case DIERR_GENERIC: | 134 /* Function to scan the system for joysticks. |
106 error = "Undefined error!"; | 135 * This function should set SDL_numjoysticks to the number of available |
107 break; | 136 * joysticks. Joystick 0 should be the system default joystick. |
108 case DIERR_OLDDIRECTINPUTVERSION: | 137 * It should return 0, or -1 on an unrecoverable fatal error. |
109 error = "Your version of DirectInput needs upgrading"; | 138 */ |
110 break; | 139 int |
111 case DIERR_INVALIDPARAM: | 140 SDL_SYS_JoystickInit(void) |
112 error = "Invalid parameters"; | 141 { |
113 break; | 142 HRESULT result; |
114 case DIERR_OUTOFMEMORY: | 143 |
115 error = "Out of memory"; | 144 SYS_NumJoysticks = 0; |
116 break; | 145 |
117 case DIERR_DEVICENOTREG: | 146 result = CoInitialize(NULL); |
118 error = "Device not registered"; | 147 if (FAILED(result)) { |
119 break; | 148 SetDIerror("CoInitialize", result); |
120 case DIERR_NOINTERFACE: | 149 return (-1); |
121 error = "Interface not supported"; | 150 } |
122 break; | 151 |
123 case DIERR_NOTINITIALIZED: | 152 result = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER, |
124 error = "Device not initialized"; | 153 &IID_IDirectInput, &dinput); |
125 break; | 154 |
126 default: | 155 if (FAILED(result)) { |
127 sprintf(errbuf, "%s: Unknown DirectInput error: 0x%x", | 156 SetDIerror("CoCreateInstance", result); |
128 function, code); | 157 return (-1); |
129 break; | 158 } |
130 } | 159 |
131 if (!errbuf[0]) { | 160 /* Because we used CoCreateInstance, we need to Initialize it, first. */ |
132 sprintf(errbuf, "%s: %s", function, error); | 161 result = |
133 } | 162 IDirectInput_Initialize(dinput, SDL_Instance, DIRECTINPUT_VERSION); |
134 SDL_SetError("%s", errbuf); | 163 |
135 return; | 164 if (FAILED(result)) { |
136 } | 165 SetDIerror("IDirectInput::Initialize", result); |
137 | 166 return (-1); |
138 | 167 } |
139 BOOL CALLBACK | 168 |
169 /* Look for joysticks, wheels, head trackers, gamepads, etc.. */ | |
170 result = IDirectInput_EnumDevices(dinput, | |
171 DIDEVTYPE_JOYSTICK, | |
172 EnumJoysticksCallback, | |
173 NULL, DIEDFL_ATTACHEDONLY); | |
174 | |
175 return SYS_NumJoysticks; | |
176 } | |
177 | |
178 static BOOL CALLBACK | |
140 EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext) | 179 EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext) |
141 { | 180 { |
142 memcpy(&SYS_Joystick[SYS_NumJoysticks], pdidInstance, | 181 memcpy(&SYS_Joystick[SYS_NumJoysticks], pdidInstance, |
143 sizeof(DIDEVICEINSTANCE)); | 182 sizeof(DIDEVICEINSTANCE)); |
144 SYS_NumJoysticks++; | 183 SYS_NumJoysticks++; |
147 return DIENUM_STOP; | 186 return DIENUM_STOP; |
148 | 187 |
149 return DIENUM_CONTINUE; | 188 return DIENUM_CONTINUE; |
150 } | 189 } |
151 | 190 |
191 /* Function to get the device-dependent name of a joystick */ | |
192 const char * | |
193 SDL_SYS_JoystickName(int index) | |
194 { | |
195 /***-> test for invalid index ? */ | |
196 return (SYS_Joystick[index].tszProductName); | |
197 } | |
198 | |
199 /* Function to open a joystick for use. | |
200 The joystick to open is specified by the index field of the joystick. | |
201 This should fill the nbuttons and naxes fields of the joystick structure. | |
202 It returns 0, or -1 if there is an error. | |
203 */ | |
204 int | |
205 SDL_SYS_JoystickOpen(SDL_Joystick * joystick) | |
206 { | |
207 HRESULT result; | |
208 LPDIRECTINPUTDEVICE device; | |
209 DIPROPDWORD dipdw; | |
210 | |
211 ZeroMemory(&dipdw, sizeof(DIPROPDWORD)); | |
212 dipdw.diph.dwSize = sizeof(DIPROPDWORD); | |
213 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); | |
214 | |
215 | |
216 /* allocate memory for system specific hardware data */ | |
217 joystick->hwdata = | |
218 (struct joystick_hwdata *) malloc(sizeof(struct joystick_hwdata)); | |
219 if (joystick->hwdata == NULL) { | |
220 SDL_OutOfMemory(); | |
221 return (-1); | |
222 } | |
223 ZeroMemory(joystick->hwdata, sizeof(struct joystick_hwdata)); | |
224 joystick->hwdata->buffered = 1; | |
225 joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS); | |
226 | |
227 result = | |
228 IDirectInput_CreateDevice(dinput, | |
229 &SYS_Joystick[joystick->index]. | |
230 guidInstance, &device, NULL); | |
231 if (FAILED(result)) { | |
232 SetDIerror("IDirectInput::CreateDevice", result); | |
233 return (-1); | |
234 } | |
235 | |
236 /* Now get the IDirectInputDevice2 interface, instead. */ | |
237 result = IDirectInputDevice_QueryInterface(device, | |
238 &IID_IDirectInputDevice2, | |
239 (LPVOID *) & joystick-> | |
240 hwdata->InputDevice); | |
241 /* We are done with this object. Use the stored one from now on. */ | |
242 IDirectInputDevice_Release(device); | |
243 | |
244 if (FAILED(result)) { | |
245 SetDIerror("IDirectInputDevice::QueryInterface", result); | |
246 return (-1); | |
247 } | |
248 | |
249 /* Aquire shared access. Exclusive access is required for forces, | |
250 * though. */ | |
251 result = | |
252 IDirectInputDevice2_SetCooperativeLevel(joystick->hwdata-> | |
253 InputDevice, SDL_Window, | |
254 DISCL_EXCLUSIVE | | |
255 DISCL_BACKGROUND); | |
256 if (FAILED(result)) { | |
257 SetDIerror("IDirectInputDevice2::SetCooperativeLevel", result); | |
258 return (-1); | |
259 } | |
260 | |
261 /* Use the extended data structure: DIJOYSTATE2. */ | |
262 result = | |
263 IDirectInputDevice2_SetDataFormat(joystick->hwdata->InputDevice, | |
264 &c_dfDIJoystick2); | |
265 if (FAILED(result)) { | |
266 SetDIerror("IDirectInputDevice2::SetDataFormat", result); | |
267 return (-1); | |
268 } | |
269 | |
270 /* Get device capabilities */ | |
271 result = | |
272 IDirectInputDevice2_GetCapabilities(joystick->hwdata->InputDevice, | |
273 &joystick->hwdata->Capabilities); | |
274 | |
275 if (FAILED(result)) { | |
276 SetDIerror("IDirectInputDevice2::GetCapabilities", result); | |
277 return (-1); | |
278 } | |
279 | |
280 /* Force capable? */ | |
281 if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) { | |
282 | |
283 result = IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice); | |
284 | |
285 if (FAILED(result)) { | |
286 SetDIerror("IDirectInputDevice2::Acquire", result); | |
287 return (-1); | |
288 } | |
289 | |
290 /* reset all accuators. */ | |
291 result = | |
292 IDirectInputDevice2_SendForceFeedbackCommand(joystick->hwdata-> | |
293 InputDevice, | |
294 DISFFC_RESET); | |
295 | |
296 if (FAILED(result)) { | |
297 SetDIerror("IDirectInputDevice2::SendForceFeedbackCommand", | |
298 result); | |
299 return (-1); | |
300 } | |
301 | |
302 result = IDirectInputDevice2_Unacquire(joystick->hwdata->InputDevice); | |
303 | |
304 if (FAILED(result)) { | |
305 SetDIerror("IDirectInputDevice2::Unacquire", result); | |
306 return (-1); | |
307 } | |
308 | |
309 /* Turn on auto-centering for a ForceFeedback device (until told | |
310 * otherwise). */ | |
311 dipdw.diph.dwObj = 0; | |
312 dipdw.diph.dwHow = DIPH_DEVICE; | |
313 dipdw.dwData = DIPROPAUTOCENTER_ON; | |
314 | |
315 result = | |
316 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, | |
317 DIPROP_AUTOCENTER, &dipdw.diph); | |
318 | |
319 if (FAILED(result)) { | |
320 SetDIerror("IDirectInputDevice2::SetProperty", result); | |
321 return (-1); | |
322 } | |
323 } | |
324 | |
325 /* What buttons and axes does it have? */ | |
326 IDirectInputDevice2_EnumObjects(joystick->hwdata->InputDevice, | |
327 EnumDevObjectsCallback, joystick, | |
328 DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV); | |
329 | |
330 dipdw.diph.dwObj = 0; | |
331 dipdw.diph.dwHow = DIPH_DEVICE; | |
332 dipdw.dwData = INPUT_QSIZE; | |
333 | |
334 /* Set the buffer size */ | |
335 result = | |
336 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, | |
337 DIPROP_BUFFERSIZE, &dipdw.diph); | |
338 | |
339 if (result == DI_POLLEDDEVICE) { | |
340 /* This device doesn't support buffering, so we're forced | |
341 * to use less reliable polling. */ | |
342 joystick->hwdata->buffered = 0; | |
343 } else if (FAILED(result)) { | |
344 SetDIerror("IDirectInputDevice2::SetProperty", result); | |
345 return (-1); | |
346 } | |
347 | |
348 return (0); | |
349 } | |
350 | |
152 static BOOL CALLBACK | 351 static BOOL CALLBACK |
153 DIJoystick_EnumDevObjectsProc(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef) | 352 EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef) |
154 { | 353 { |
155 SDL_Joystick *joystick = (SDL_Joystick *) pvRef; | 354 SDL_Joystick *joystick = (SDL_Joystick *) pvRef; |
156 HRESULT result; | 355 HRESULT result; |
157 input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs]; | 356 input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs]; |
158 const int SupportedMask = DIDFT_BUTTON | DIDFT_POV | DIDFT_AXIS; | |
159 if (!(dev->dwType & SupportedMask)) | |
160 return DIENUM_CONTINUE; /* unsupported */ | |
161 | 357 |
162 in->ofs = dev->dwOfs; | 358 in->ofs = dev->dwOfs; |
163 | 359 |
164 if (dev->dwType & DIDFT_BUTTON) { | 360 if (dev->dwType & DIDFT_BUTTON) { |
165 in->type = BUTTON; | 361 in->type = BUTTON; |
167 joystick->nbuttons++; | 363 joystick->nbuttons++; |
168 } else if (dev->dwType & DIDFT_POV) { | 364 } else if (dev->dwType & DIDFT_POV) { |
169 in->type = HAT; | 365 in->type = HAT; |
170 in->num = joystick->nhats; | 366 in->num = joystick->nhats; |
171 joystick->nhats++; | 367 joystick->nhats++; |
172 } else { /* dev->dwType & DIDFT_AXIS */ | 368 } else if (dev->dwType & DIDFT_AXIS) { |
173 DIPROPRANGE diprg; | 369 DIPROPRANGE diprg; |
174 DIPROPDWORD dilong; | 370 DIPROPDWORD dilong; |
175 | 371 |
176 in->type = AXIS; | 372 in->type = AXIS; |
177 in->num = joystick->naxes; | 373 in->num = joystick->naxes; |
184 diprg.lMax = AXIS_MAX; | 380 diprg.lMax = AXIS_MAX; |
185 | 381 |
186 result = | 382 result = |
187 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, | 383 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, |
188 DIPROP_RANGE, &diprg.diph); | 384 DIPROP_RANGE, &diprg.diph); |
189 if (result != DI_OK) | 385 if (FAILED(result)) { |
190 return DIENUM_CONTINUE; /* don't use this axis */ | 386 return DIENUM_CONTINUE; /* don't use this axis */ |
387 } | |
191 | 388 |
192 /* Set dead zone to 0. */ | 389 /* Set dead zone to 0. */ |
193 dilong.diph.dwSize = sizeof(dilong); | 390 dilong.diph.dwSize = sizeof(dilong); |
194 dilong.diph.dwHeaderSize = sizeof(dilong.diph); | 391 dilong.diph.dwHeaderSize = sizeof(dilong.diph); |
195 dilong.diph.dwObj = dev->dwOfs; | 392 dilong.diph.dwObj = dev->dwOfs; |
196 dilong.diph.dwHow = DIPH_BYOFFSET; | 393 dilong.diph.dwHow = DIPH_BYOFFSET; |
197 dilong.dwData = 0; | 394 dilong.dwData = 0; |
198 result = | 395 result = |
199 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, | 396 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, |
200 DIPROP_DEADZONE, &dilong.diph); | 397 DIPROP_DEADZONE, &dilong.diph); |
201 if (result != DI_OK) | 398 if (FAILED(result)) { |
202 return DIENUM_CONTINUE; /* don't use this axis */ | 399 return DIENUM_CONTINUE; /* don't use this axis */ |
400 } | |
203 | 401 |
204 joystick->naxes++; | 402 joystick->naxes++; |
403 } else { | |
404 /* not supported at this time */ | |
405 return DIENUM_CONTINUE; | |
205 } | 406 } |
206 | 407 |
207 joystick->hwdata->NumInputs++; | 408 joystick->hwdata->NumInputs++; |
208 | 409 |
209 if (joystick->hwdata->NumInputs == MAX_INPUTS) | 410 if (joystick->hwdata->NumInputs == MAX_INPUTS) { |
210 return DIENUM_STOP; /* too many */ | 411 return DIENUM_STOP; /* too many */ |
412 } | |
211 | 413 |
212 return DIENUM_CONTINUE; | 414 return DIENUM_CONTINUE; |
213 } | 415 } |
214 | 416 |
215 /* Function to scan the system for joysticks. | 417 /* Function to update the state of a joystick - called as a device poll. |
216 * This function should set SDL_numjoysticks to the number of available | 418 * This function shouldn't update the joystick structure directly, |
217 * joysticks. Joystick 0 should be the system default joystick. | 419 * but instead should call SDL_PrivateJoystick*() to deliver events |
218 * It should return 0, or -1 on an unrecoverable fatal error. | 420 * and update joystick device state. |
219 */ | 421 */ |
220 int | 422 void |
221 SDL_SYS_JoystickInit(void) | 423 SDL_SYS_JoystickUpdate_Polled(SDL_Joystick * joystick) |
222 { | 424 { |
425 DIJOYSTATE2 state; | |
223 HRESULT result; | 426 HRESULT result; |
224 | 427 int i; |
225 SYS_NumJoysticks = 0; | 428 |
226 | 429 result = |
227 /* Create the DirectInput object */ | 430 IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice, |
228 if (DX5_Load() < 0) { | 431 sizeof(DIJOYSTATE2), &state); |
229 SDL_SetError("Couldn't load DirectInput"); | 432 if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) { |
230 return (-1); | 433 IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice); |
231 } | 434 result = |
232 result = DInputCreate(SDL_Instance, DIRECTINPUT_VERSION, &dinput, NULL); | 435 IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice, |
233 if (result != DI_OK) { | 436 sizeof(DIJOYSTATE2), &state); |
234 DX5_Unload(); | 437 } |
235 SetDIerror("DirectInputCreate", result); | 438 |
236 return (-1); | 439 /* Set each known axis, button and POV. */ |
237 } | 440 for (i = 0; i < joystick->hwdata->NumInputs; ++i) { |
238 | 441 const input_t *in = &joystick->hwdata->Inputs[i]; |
239 result = IDirectInput_EnumDevices(dinput, | 442 |
240 DIDEVTYPE_JOYSTICK, | 443 switch (in->type) { |
241 EnumJoysticksCallback, | 444 case AXIS: |
242 NULL, DIEDFL_ATTACHEDONLY); | 445 switch (in->ofs) { |
243 | 446 case DIJOFS_X: |
244 return SYS_NumJoysticks; | 447 SDL_PrivateJoystickAxis_Int(joystick, in->num, |
245 } | 448 (Sint16) state.lX); |
246 | 449 break; |
247 /* Function to get the device-dependent name of a joystick */ | 450 case DIJOFS_Y: |
248 const char * | 451 SDL_PrivateJoystickAxis_Int(joystick, in->num, |
249 SDL_SYS_JoystickName(int index) | 452 (Sint16) state.lY); |
250 { | 453 break; |
251 /***-> test for invalid index ? */ | 454 case DIJOFS_Z: |
252 return (SYS_Joystick[index].tszProductName); | 455 SDL_PrivateJoystickAxis_Int(joystick, in->num, |
253 } | 456 (Sint16) state.lZ); |
254 | 457 break; |
255 /* Function to open a joystick for use. | 458 case DIJOFS_RX: |
256 The joystick to open is specified by the index field of the joystick. | 459 SDL_PrivateJoystickAxis_Int(joystick, in->num, |
257 This should fill the nbuttons and naxes fields of the joystick structure. | 460 (Sint16) state.lRx); |
258 It returns 0, or -1 if there is an error. | 461 break; |
259 */ | 462 case DIJOFS_RY: |
260 int | 463 SDL_PrivateJoystickAxis_Int(joystick, in->num, |
261 SDL_SYS_JoystickOpen(SDL_Joystick * joystick) | 464 (Sint16) state.lRy); |
262 { | 465 break; |
466 case DIJOFS_RZ: | |
467 SDL_PrivateJoystickAxis_Int(joystick, in->num, | |
468 (Sint16) state.lRz); | |
469 break; | |
470 case DIJOFS_SLIDER(0): | |
471 SDL_PrivateJoystickAxis_Int(joystick, in->num, | |
472 (Sint16) state.rglSlider[0]); | |
473 break; | |
474 case DIJOFS_SLIDER(1): | |
475 SDL_PrivateJoystickAxis_Int(joystick, in->num, | |
476 (Sint16) state.rglSlider[1]); | |
477 break; | |
478 } | |
479 | |
480 break; | |
481 | |
482 case BUTTON: | |
483 SDL_PrivateJoystickButton_Int(joystick, in->num, | |
484 (Uint8) (state. | |
485 rgbButtons[in->ofs - | |
486 DIJOFS_BUTTON0] | |
487 ? SDL_PRESSED : | |
488 SDL_RELEASED)); | |
489 break; | |
490 case HAT: | |
491 { | |
492 Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - | |
493 DIJOFS_POV(0)]); | |
494 SDL_PrivateJoystickHat_Int(joystick, in->num, pos); | |
495 break; | |
496 } | |
497 } | |
498 } | |
499 } | |
500 | |
501 void | |
502 SDL_SYS_JoystickUpdate_Buffered(SDL_Joystick * joystick) | |
503 { | |
504 int i; | |
263 HRESULT result; | 505 HRESULT result; |
264 LPDIRECTINPUTDEVICE device; | 506 DWORD numevents; |
265 | 507 DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE]; |
266 /* allocate memory for system specific hardware data */ | 508 |
267 joystick->hwdata = | 509 numevents = INPUT_QSIZE; |
268 (struct joystick_hwdata *) malloc(sizeof(*joystick->hwdata)); | 510 result = |
269 if (joystick->hwdata == NULL) { | 511 IDirectInputDevice2_GetDeviceData(joystick->hwdata->InputDevice, |
270 SDL_OutOfMemory(); | 512 sizeof(DIDEVICEOBJECTDATA), evtbuf, |
271 return (-1); | 513 &numevents, 0); |
272 } | 514 if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) { |
273 memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); | 515 IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice); |
274 joystick->hwdata->buffered = 1; | |
275 | |
276 result = | |
277 IDirectInput_CreateDevice(dinput, | |
278 &SYS_Joystick[joystick->index]. | |
279 guidInstance, &device, NULL); | |
280 if (result != DI_OK) { | |
281 SetDIerror("DirectInput::CreateDevice", result); | |
282 return (-1); | |
283 } | |
284 | |
285 result = IDirectInputDevice_QueryInterface(device, | |
286 &IID_IDirectInputDevice2, | |
287 (LPVOID *) & joystick-> | |
288 hwdata->InputDevice); | |
289 IDirectInputDevice_Release(device); | |
290 if (result != DI_OK) { | |
291 SetDIerror("DirectInputDevice::QueryInterface", result); | |
292 return (-1); | |
293 } | |
294 | |
295 result = | |
296 IDirectInputDevice2_SetCooperativeLevel(joystick->hwdata-> | |
297 InputDevice, SDL_Window, | |
298 DISCL_NONEXCLUSIVE | | |
299 DISCL_BACKGROUND); | |
300 if (result != DI_OK) { | |
301 SetDIerror("DirectInputDevice::SetCooperativeLevel", result); | |
302 return (-1); | |
303 } | |
304 | |
305 result = | |
306 IDirectInputDevice2_SetDataFormat(joystick->hwdata->InputDevice, | |
307 &c_dfDIJoystick); | |
308 if (result != DI_OK) { | |
309 SetDIerror("DirectInputDevice::SetDataFormat", result); | |
310 return (-1); | |
311 } | |
312 | |
313 IDirectInputDevice2_EnumObjects(joystick->hwdata->InputDevice, | |
314 DIJoystick_EnumDevObjectsProc, | |
315 joystick, | |
316 DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV); | |
317 | |
318 { | |
319 DIPROPDWORD dipdw; | |
320 memset(&dipdw, 0, sizeof(dipdw)); | |
321 dipdw.diph.dwSize = sizeof(dipdw); | |
322 dipdw.diph.dwHeaderSize = sizeof(dipdw.diph); | |
323 dipdw.diph.dwObj = 0; | |
324 dipdw.diph.dwHow = DIPH_DEVICE; | |
325 dipdw.dwData = INPUT_QSIZE; | |
326 result = | 516 result = |
327 IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, | 517 IDirectInputDevice2_GetDeviceData(joystick->hwdata->InputDevice, |
328 DIPROP_BUFFERSIZE, &dipdw.diph); | 518 sizeof(DIDEVICEOBJECTDATA), |
329 | 519 evtbuf, &numevents, 0); |
330 if (result == DI_POLLEDDEVICE) { | 520 } |
331 /* This device doesn't support buffering, so we're forced | 521 |
332 * to use less reliable polling. */ | 522 /* Handle the events or punt */ |
333 joystick->hwdata->buffered = 0; | 523 if (FAILED(result)) |
334 } else if (result != DI_OK) { | 524 return; |
335 SetDIerror("DirectInputDevice::SetProperty", result); | 525 |
336 return (-1); | 526 for (i = 0; i < (int) numevents; ++i) { |
337 } | 527 int j; |
338 } | 528 |
339 | 529 for (j = 0; j < joystick->hwdata->NumInputs; ++j) { |
340 return (0); | 530 const input_t *in = &joystick->hwdata->Inputs[j]; |
341 } | 531 |
532 if (evtbuf[i].dwOfs != in->ofs) | |
533 continue; | |
534 | |
535 switch (in->type) { | |
536 case AXIS: | |
537 SDL_PrivateJoystickAxis(joystick, in->num, | |
538 (Sint16) evtbuf[i].dwData); | |
539 break; | |
540 case BUTTON: | |
541 SDL_PrivateJoystickButton(joystick, in->num, | |
542 (Uint8) (evtbuf[i]. | |
543 dwData ? SDL_PRESSED : | |
544 SDL_RELEASED)); | |
545 break; | |
546 case HAT: | |
547 { | |
548 Uint8 pos = TranslatePOV(evtbuf[i].dwData); | |
549 SDL_PrivateJoystickHat(joystick, in->num, pos); | |
550 } | |
551 } | |
552 } | |
553 } | |
554 } | |
555 | |
342 | 556 |
343 static Uint8 | 557 static Uint8 |
344 TranslatePOV(DWORD value) | 558 TranslatePOV(DWORD value) |
345 { | 559 { |
346 const int HAT_VALS[] = { | 560 const int HAT_VALS[] = { |
393 if (joystick->buttons[button] != state) | 607 if (joystick->buttons[button] != state) |
394 return SDL_PrivateJoystickButton(joystick, button, state); | 608 return SDL_PrivateJoystickButton(joystick, button, state); |
395 return 0; | 609 return 0; |
396 } | 610 } |
397 | 611 |
398 /* Function to update the state of a joystick - called as a device poll. | |
399 * This function shouldn't update the joystick structure directly, | |
400 * but instead should call SDL_PrivateJoystick*() to deliver events | |
401 * and update joystick device state. | |
402 */ | |
403 void | |
404 SDL_SYS_JoystickUpdate_Polled(SDL_Joystick * joystick) | |
405 { | |
406 DIJOYSTATE state; | |
407 HRESULT result; | |
408 int i; | |
409 | |
410 result = | |
411 IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice, | |
412 sizeof(state), &state); | |
413 if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) { | |
414 IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice); | |
415 result = | |
416 IDirectInputDevice2_GetDeviceState(joystick->hwdata-> | |
417 InputDevice, sizeof(state), | |
418 &state); | |
419 } | |
420 | |
421 /* Set each known axis, button and POV. */ | |
422 for (i = 0; i < joystick->hwdata->NumInputs; ++i) { | |
423 const input_t *in = &joystick->hwdata->Inputs[i]; | |
424 | |
425 switch (in->type) { | |
426 case AXIS: | |
427 switch (in->ofs) { | |
428 case DIJOFS_X: | |
429 SDL_PrivateJoystickAxis_Int(joystick, in->num, | |
430 (Sint16) state.lX); | |
431 break; | |
432 case DIJOFS_Y: | |
433 SDL_PrivateJoystickAxis_Int(joystick, in->num, | |
434 (Sint16) state.lY); | |
435 break; | |
436 case DIJOFS_Z: | |
437 SDL_PrivateJoystickAxis_Int(joystick, in->num, | |
438 (Sint16) state.lZ); | |
439 break; | |
440 case DIJOFS_RX: | |
441 SDL_PrivateJoystickAxis_Int(joystick, in->num, | |
442 (Sint16) state.lRx); | |
443 break; | |
444 case DIJOFS_RY: | |
445 SDL_PrivateJoystickAxis_Int(joystick, in->num, | |
446 (Sint16) state.lRy); | |
447 break; | |
448 case DIJOFS_RZ: | |
449 SDL_PrivateJoystickAxis_Int(joystick, in->num, | |
450 (Sint16) state.lRz); | |
451 break; | |
452 case DIJOFS_SLIDER(0): | |
453 SDL_PrivateJoystickAxis_Int(joystick, in->num, | |
454 (Sint16) state.rglSlider[0]); | |
455 break; | |
456 case DIJOFS_SLIDER(1): | |
457 SDL_PrivateJoystickAxis_Int(joystick, in->num, | |
458 (Sint16) state.rglSlider[0]); | |
459 break; | |
460 } | |
461 | |
462 break; | |
463 | |
464 case BUTTON: | |
465 SDL_PrivateJoystickButton_Int(joystick, in->num, | |
466 (Uint8) (state. | |
467 rgbButtons[in->ofs - | |
468 DIJOFS_BUTTON0] | |
469 ? SDL_PRESSED : | |
470 SDL_RELEASED)); | |
471 break; | |
472 case HAT: | |
473 { | |
474 Uint8 pos = | |
475 TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]); | |
476 SDL_PrivateJoystickHat_Int(joystick, in->num, pos); | |
477 break; | |
478 } | |
479 } | |
480 } | |
481 } | |
482 | |
483 void | |
484 SDL_SYS_JoystickUpdate_Buffered(SDL_Joystick * joystick) | |
485 { | |
486 int i; | |
487 HRESULT result; | |
488 DWORD numevents; | |
489 DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE]; | |
490 | |
491 numevents = INPUT_QSIZE; | |
492 result = | |
493 IDirectInputDevice2_GetDeviceData(joystick->hwdata->InputDevice, | |
494 sizeof(DIDEVICEOBJECTDATA), | |
495 evtbuf, &numevents, 0); | |
496 if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) { | |
497 IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice); | |
498 result = | |
499 IDirectInputDevice2_GetDeviceData(joystick->hwdata-> | |
500 InputDevice, | |
501 sizeof(DIDEVICEOBJECTDATA), | |
502 evtbuf, &numevents, 0); | |
503 } | |
504 | |
505 /* Handle the events */ | |
506 if (result != DI_OK) | |
507 return; | |
508 | |
509 for (i = 0; i < (int) numevents; ++i) { | |
510 int j; | |
511 | |
512 for (j = 0; j < joystick->hwdata->NumInputs; ++j) { | |
513 const input_t *in = &joystick->hwdata->Inputs[j]; | |
514 | |
515 if (evtbuf[i].dwOfs != in->ofs) | |
516 continue; | |
517 | |
518 switch (in->type) { | |
519 case AXIS: | |
520 SDL_PrivateJoystickAxis(joystick, in->num, | |
521 (Sint16) evtbuf[i].dwData); | |
522 break; | |
523 case BUTTON: | |
524 SDL_PrivateJoystickButton(joystick, in->num, | |
525 (Uint8) (evtbuf[i]. | |
526 dwData ? SDL_PRESSED | |
527 : SDL_RELEASED)); | |
528 break; | |
529 case HAT: | |
530 { | |
531 Uint8 pos = TranslatePOV(evtbuf[i].dwData); | |
532 SDL_PrivateJoystickHat(joystick, in->num, pos); | |
533 } | |
534 } | |
535 } | |
536 } | |
537 } | |
538 | |
539 void | 612 void |
540 SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) | 613 SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) |
541 { | 614 { |
542 HRESULT result; | 615 HRESULT result; |
543 | 616 |
570 void | 643 void |
571 SDL_SYS_JoystickQuit(void) | 644 SDL_SYS_JoystickQuit(void) |
572 { | 645 { |
573 IDirectInput_Release(dinput); | 646 IDirectInput_Release(dinput); |
574 dinput = NULL; | 647 dinput = NULL; |
575 DX5_Unload(); | |
576 } | 648 } |
577 | 649 |
578 #endif /* SDL_JOYSTICK_DINPUT */ | 650 #endif /* SDL_JOYSTICK_DINPUT */ |
579 /* vi: set ts=4 sw=4 expandtab: */ | 651 /* vi: set ts=4 sw=4 expandtab: */ |