comparison src/joystick/win32/SDL_mmjoystick.c @ 0:74212992fb08

Initial revision
author Sam Lantinga <slouken@lokigames.com>
date Thu, 26 Apr 2001 16:45:43 +0000
parents
children 6f3c474f9abd
comparison
equal deleted inserted replaced
-1:000000000000 0:74212992fb08
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@devolution.com
21 */
22
23 #ifdef SAVE_RCSID
24 static char rcsid =
25 "@(#) $Id$";
26 #endif
27
28 /* Win32 MultiMedia Joystick driver, contributed by Andrei de A. Formiga */
29
30 #include <stdlib.h>
31 #include <stdio.h> /* For the definition of NULL */
32
33 #include "SDL_error.h"
34 #include "SDL_joystick.h"
35 #include "SDL_sysjoystick.h"
36 #include "SDL_joystick_c.h"
37
38 #include <windows.h>
39 #include <mmsystem.h>
40
41 #define MAX_JOYSTICKS 2 /* only 2 are supported in the multimedia API */
42 #define MAX_AXES 6 /* each joystick can have up to 6 axes */
43 #define MAX_BUTTONS 32 /* and 32 buttons */
44 #define AXIS_MIN -32768 /* minimum value for axis coordinate */
45 #define AXIS_MAX 32767 /* maximum value for axis coordinate */
46 #define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/100) /* 1% motion */
47 #define JOY_BUTTON_FLAG(n) (1<<n)
48
49
50 /* array to hold joystick ID values */
51 static UINT SYS_JoystickID[MAX_JOYSTICKS];
52 static JOYCAPS SYS_Joystick[MAX_JOYSTICKS];
53
54 /* The private structure used to keep track of a joystick */
55 struct joystick_hwdata
56 {
57 /* joystick ID */
58 UINT id;
59
60 /* values used to translate device-specific coordinates into
61 SDL-standard ranges */
62 struct _transaxis {
63 int offset;
64 float scale;
65 } transaxis[6];
66 };
67
68 /* Convert a win32 Multimedia API return code to a text message */
69 static void SetMMerror(char *function, int code);
70
71
72 /* Function to scan the system for joysticks.
73 * This function should set SDL_numjoysticks to the number of available
74 * joysticks. Joystick 0 should be the system default joystick.
75 * It should return 0, or -1 on an unrecoverable fatal error.
76 */
77 int SDL_SYS_JoystickInit(void)
78 {
79 int i;
80 int maxdevs;
81 int numdevs;
82 JOYINFOEX joyinfo;
83 JOYCAPS joycaps;
84 MMRESULT result;
85
86 numdevs = 0;
87 maxdevs = joyGetNumDevs();
88 if ( maxdevs > MAX_JOYSTICKS ) {
89 maxdevs = MAX_JOYSTICKS;
90 }
91
92 SYS_JoystickID[0] = JOYSTICKID1;
93 SYS_JoystickID[1] = JOYSTICKID2;
94
95 for ( i = 0; (i < maxdevs); ++i ) {
96 result = joyGetPosEx(SYS_JoystickID[i], &joyinfo);
97 if ( result == JOYERR_NOERROR ) {
98 result = joyGetDevCaps(SYS_JoystickID[i], &joycaps, sizeof(joycaps));
99 if ( result == JOYERR_NOERROR ) {
100 SYS_JoystickID[numdevs] = SYS_JoystickID[i];
101 SYS_Joystick[numdevs] = joycaps;
102 numdevs++;
103 }
104 }
105 }
106 return(numdevs);
107 }
108
109 /* Function to get the device-dependent name of a joystick */
110 const char *SDL_SYS_JoystickName(int index)
111 {
112 /***-> test for invalid index ? */
113 return(SYS_Joystick[index].szPname);
114 }
115
116 /* Function to open a joystick for use.
117 The joystick to open is specified by the index field of the joystick.
118 This should fill the nbuttons and naxes fields of the joystick structure.
119 It returns 0, or -1 if there is an error.
120 */
121 int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
122 {
123 int index, i;
124 int caps_flags[MAX_AXES-2] =
125 { JOYCAPS_HASZ, JOYCAPS_HASR, JOYCAPS_HASU, JOYCAPS_HASV };
126 int axis_min[MAX_AXES], axis_max[MAX_AXES];
127
128
129 /* shortcut */
130 index = joystick->index;
131 axis_min[0] = SYS_Joystick[index].wXmin;
132 axis_max[0] = SYS_Joystick[index].wXmax;
133 axis_min[1] = SYS_Joystick[index].wYmin;
134 axis_max[1] = SYS_Joystick[index].wYmax;
135 axis_min[2] = SYS_Joystick[index].wZmin;
136 axis_max[2] = SYS_Joystick[index].wZmax;
137 axis_min[3] = SYS_Joystick[index].wRmin;
138 axis_max[3] = SYS_Joystick[index].wRmax;
139 axis_min[4] = SYS_Joystick[index].wUmin;
140 axis_max[4] = SYS_Joystick[index].wUmax;
141 axis_min[5] = SYS_Joystick[index].wVmin;
142 axis_max[5] = SYS_Joystick[index].wVmax;
143
144 /* allocate memory for system specific hardware data */
145 joystick->hwdata = (struct joystick_hwdata *) malloc(sizeof(*joystick->hwdata));
146 if (joystick->hwdata == NULL)
147 {
148 SDL_OutOfMemory();
149 return(-1);
150 }
151 memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
152
153 /* set hardware data */
154 joystick->hwdata->id = SYS_JoystickID[index];
155 for ( i = 0; i < MAX_AXES; ++i ) {
156 if ( (i<2) || (SYS_Joystick[index].wCaps & caps_flags[i-2]) ) {
157 joystick->hwdata->transaxis[i].offset =
158 AXIS_MIN - axis_min[i];
159 joystick->hwdata->transaxis[i].scale =
160 (float)(AXIS_MAX - AXIS_MIN) / (axis_max[i] - axis_min[i]);
161 } else {
162 joystick->hwdata->transaxis[i].offset = 0;
163 joystick->hwdata->transaxis[i].scale = 1.0; /* Just in case */
164 }
165 }
166
167 /* fill nbuttons, naxes, and nhats fields */
168 joystick->nbuttons = SYS_Joystick[index].wNumButtons;
169 joystick->naxes = SYS_Joystick[index].wNumAxes;
170 if ( SYS_Joystick[index].wCaps & JOYCAPS_HASPOV ) {
171 joystick->nhats = 1;
172 } else {
173 joystick->nhats = 0;
174 }
175 return(0);
176 }
177
178 static Uint8 TranslatePOV(DWORD value)
179 {
180 Uint8 pos;
181
182 pos = SDL_HAT_CENTERED;
183 if ( value != JOY_POVCENTERED ) {
184 if ( (value > JOY_POVLEFT) || (value < JOY_POVRIGHT) ) {
185 pos |= SDL_HAT_UP;
186 }
187 if ( (value > JOY_POVFORWARD) && (value < JOY_POVBACKWARD) ) {
188 pos |= SDL_HAT_RIGHT;
189 }
190 if ( (value > JOY_POVRIGHT) && (value < JOY_POVLEFT) ) {
191 pos |= SDL_HAT_DOWN;
192 }
193 if ( value > JOY_POVBACKWARD ) {
194 pos |= SDL_HAT_LEFT;
195 }
196 }
197 return(pos);
198 }
199
200 /* Function to update the state of a joystick - called as a device poll.
201 * This function shouldn't update the joystick structure directly,
202 * but instead should call SDL_PrivateJoystick*() to deliver events
203 * and update joystick device state.
204 */
205 void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
206 {
207 MMRESULT result;
208 int i;
209 DWORD flags[MAX_AXES] = { JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ,
210 JOY_RETURNR, JOY_RETURNU, JOY_RETURNV };
211 DWORD pos[MAX_AXES];
212 struct _transaxis *transaxis;
213 int value, change;
214 JOYINFOEX joyinfo;
215
216 joyinfo.dwSize = sizeof(joyinfo);
217 joyinfo.dwFlags = JOY_RETURNALL|JOY_RETURNPOVCTS;
218 if ( ! joystick->hats ) {
219 joyinfo.dwFlags &= ~(JOY_RETURNPOV|JOY_RETURNPOVCTS);
220 }
221 result = joyGetPosEx(joystick->hwdata->id, &joyinfo);
222 if ( result != JOYERR_NOERROR ) {
223 SetMMerror("joyGetPosEx", result);
224 return;
225 }
226
227 /* joystick motion events */
228 pos[0] = joyinfo.dwXpos;
229 pos[1] = joyinfo.dwYpos;
230 pos[2] = joyinfo.dwZpos;
231 pos[3] = joyinfo.dwRpos;
232 pos[4] = joyinfo.dwUpos;
233 pos[5] = joyinfo.dwVpos;
234
235 transaxis = joystick->hwdata->transaxis;
236 for (i = 0; i < joystick->naxes; i++) {
237 if (joyinfo.dwFlags & flags[i]) {
238 value = (int)((float)(pos[i] + transaxis[i].offset) * transaxis[i].scale);
239 change = (value - joystick->axes[i]);
240 if ( (change < -JOY_AXIS_THRESHOLD) || (change > JOY_AXIS_THRESHOLD) ) {
241 SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)value);
242 }
243 }
244 }
245
246 /* joystick button events */
247 if ( joyinfo.dwFlags & JOY_RETURNBUTTONS ) {
248 for ( i = 0; i < joystick->nbuttons; ++i ) {
249 if ( joyinfo.dwButtons & JOY_BUTTON_FLAG(i) ) {
250 if ( ! joystick->buttons[i] ) {
251 SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_PRESSED);
252 }
253 } else {
254 if ( joystick->buttons[i] ) {
255 SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_RELEASED);
256 }
257 }
258 }
259 }
260
261 /* joystick hat events */
262 if ( joyinfo.dwFlags & JOY_RETURNPOV ) {
263 Uint8 pos;
264
265 pos = TranslatePOV(joyinfo.dwPOV);
266 if ( pos != joystick->hats[0] ) {
267 SDL_PrivateJoystickHat(joystick, 0, pos);
268 }
269 }
270 }
271
272 /* Function to close a joystick after use */
273 void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
274 {
275 if (joystick->hwdata != NULL) {
276 /* free system specific hardware data */
277 free(joystick->hwdata);
278 }
279 }
280
281 /* Function to perform any system-specific joystick related cleanup */
282 void SDL_SYS_JoystickQuit(void)
283 {
284 return;
285 }
286
287
288 /* implementation functions */
289 void SetMMerror(char *function, int code)
290 {
291 static char *error;
292 static char errbuf[BUFSIZ];
293
294 errbuf[0] = 0;
295 switch (code)
296 {
297 case MMSYSERR_NODRIVER:
298 error = "Joystick driver not present";
299 break;
300
301 case MMSYSERR_INVALPARAM:
302 case JOYERR_PARMS:
303 error = "Invalid parameter(s)";
304 break;
305
306 case MMSYSERR_BADDEVICEID:
307 error = "Bad device ID";
308 break;
309
310 case JOYERR_UNPLUGGED:
311 error = "Joystick not attached";
312 break;
313
314 case JOYERR_NOCANDO:
315 error = "Can't capture joystick input";
316 break;
317
318 default:
319 sprintf(errbuf, "%s: Unknown Multimedia system error: 0x%x",
320 function, code);
321 break;
322 }
323
324 if ( ! errbuf[0] ) {
325 sprintf(errbuf, "%s: %s", function, error);
326 }
327 SDL_SetError("%s", errbuf);
328 }