1 /*
2 joy_win.c
3
4 Joystick device driver for Win32
5
6 Copyright (C) 2000 Jeff Teunissen <deek@dusknet.dhs.org>
7 Copyright (C) 2000 Jukka Sorjonen <jukka.sorjone@asikkala.fi>
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18 See the GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to:
22
23 Free Software Foundation, Inc.
24 59 Temple Place - Suite 330
25 Boston, MA 02111-1307, USA
26
27 */
28 // FIXME: THIS IS NOT FINISHED YET
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <math.h>
35
36 #include "winquake.h"
37
38 #include "QF/cmd.h"
39 #include "QF/cvar.h"
40 #include "QF/input.h"
41 #include "QF/joystick.h"
42 #include "QF/keys.h"
43 #include "QF/qargs.h"
44 #include "QF/sys.h"
45
46 #include "compat.h"
47
48 // Joystick variables and structures
49 cvar_t *joy_sensitivity; // Joystick sensitivity
50
51 // joystick defines and variables
52 // where should defines be moved?
53
54 #define JOY_ABSOLUTE_AXIS 0x00000000 // control like a joystick
55 #define JOY_RELATIVE_AXIS 0x00000010 // control like a mouse, spinner,
56 // trackball
57 #define JOY_AXIS_X 0
58 #define JOY_AXIS_Y 1
59 #define JOY_AXIS_Z 2
60 #define JOY_AXIS_R 3
61 #define JOY_AXIS_U 4
62 #define JOY_AXIS_V 5
63
64 enum _ControlList {
65 AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn
66 };
67
68 DWORD dwAxisFlags[JOY_MAX_AXES] = {
69 JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU,
70 JOY_RETURNV
71 };
72
73 DWORD dwAxisMap[JOY_MAX_AXES];
74 DWORD dwControlMap[JOY_MAX_AXES];
75 PDWORD pdwRawValue[JOY_MAX_AXES];
76
77 JOYINFOEX ji;
78
79 // none of these cvars are saved over a session
80 // this means that advanced controller configuration needs to be executed
81 // each time. this avoids any problems with getting back to a default usage or
82 // when changing from one controller to another. this way at least something
83 // works.
84
85 cvar_t *in_joystick;
86 cvar_t *joy_name;
87 cvar_t *joy_advanced;
88 cvar_t *joy_advaxisx;
89 cvar_t *joy_advaxisy;
90 cvar_t *joy_advaxisz;
91 cvar_t *joy_advaxisr;
92 cvar_t *joy_advaxisu;
93 cvar_t *joy_advaxisv;
94 cvar_t *joy_forwardthreshold;
95 cvar_t *joy_sidethreshold;
96 cvar_t *joy_pitchthreshold;
97 cvar_t *joy_yawthreshold;
98 cvar_t *joy_forwardsensitivity;
99 cvar_t *joy_sidesensitivity;
100 cvar_t *joy_pitchsensitivity;
101 cvar_t *joy_yawsensitivity;
102 cvar_t *joy_wwhack1;
103 cvar_t *joy_wwhack2;
104
105 cvar_t *joy_debug;
106
107 qboolean joy_advancedinit, joy_haspov;
108 DWORD joy_oldbuttonstate, joy_oldpovstate;
109 int joy_id;
110 DWORD joy_flags;
111 DWORD joy_numbuttons;
112 #if 0
113 static PDWORD
114 RawValuePointer (int axis)
115 {
116 switch (axis) {
117 case JOY_AXIS_X:
118 return &ji.dwXpos;
119 case JOY_AXIS_Y:
120 return &ji.dwYpos;
121 case JOY_AXIS_Z:
122 return &ji.dwZpos;
123 case JOY_AXIS_R:
124 return &ji.dwRpos;
125 case JOY_AXIS_U:
126 return &ji.dwUpos;
127 case JOY_AXIS_V:
128 return &ji.dwVpos;
129 }
130 return NULL;
131 }
132
133 static qboolean
134 _JOY_Read (void)
135 {
136 memset (&ji, 0, sizeof (ji));
137 ji.dwSize = sizeof (ji);
138 ji.dwFlags = joy_flags;
139
140 if (joyGetPosEx (joy_id, &ji) == JOYERR_NOERROR) {
141 // HACK HACK HACK -- there's a bug in the Logitech Wingman Warrior's
142 // DInput driver that causes it to make 32668 the center point
143 // instead
144 // of 32768
145 if (joy_wwhack1->int_val) {
146 ji.dwUpos += 100;
147 }
148 if (joy_debug->int_val) {
149 if (ji.dwXpos) Sys_Printf("X: %ld\n",ji.dwXpos);
150 if (ji.dwYpos) Sys_Printf("Y: %ld\n",ji.dwYpos);
151 if (ji.dwZpos) Sys_Printf("Z: %ld\n",ji.dwZpos);
152 if (ji.dwRpos) Sys_Printf("R: %ld\n",ji.dwRpos);
153 if (ji.dwUpos) Sys_Printf("U: %ld\n",ji.dwUpos);
154 if (ji.dwVpos) Sys_Printf("V: %ld\n",ji.dwVpos);
155 if (ji.dwButtons) Sys_Printf("B: %ld\n",ji.dwButtons);
156 }
157 return true;
158 } else { // read error
159 return false;
160 }
161 }
162 #endif
163 void
JOY_Read(void)164 JOY_Read (void)
165 {
166 DWORD i;
167 DWORD buttonstate, povstate;
168
169 if (!joy_found) {
170 return;
171 }
172 // loop through the joystick buttons
173 // key a joystick event or auxillary event for higher number buttons for
174 // each state change
175 buttonstate = ji.dwButtons;
176 for (i = 0; i < joy_numbuttons; i++) {
177 if ((buttonstate & (1 << i)) && !(joy_oldbuttonstate & (1 << i))) {
178 Key_Event (QFJ_BUTTON1 + i, 0, true);
179 }
180
181 if (!(buttonstate & (1 << i)) && (joy_oldbuttonstate & (1 << i))) {
182 Key_Event (QFJ_BUTTON1 + i, 0, false);
183 }
184 }
185 joy_oldbuttonstate = buttonstate;
186
187 if (joy_haspov) {
188 // convert POV information into 4 bits of state information
189 // this avoids any potential problems related to moving from one
190 // direction to another without going through the center position
191 povstate = 0;
192 if (ji.dwPOV != JOY_POVCENTERED) {
193 if (ji.dwPOV == JOY_POVFORWARD)
194 povstate |= 0x01;
195 if (ji.dwPOV == JOY_POVRIGHT)
196 povstate |= 0x02;
197 if (ji.dwPOV == JOY_POVBACKWARD)
198 povstate |= 0x04;
199 if (ji.dwPOV == JOY_POVLEFT)
200 povstate |= 0x08;
201 }
202 // determine which bits have changed and key an auxillary event for
203 // each change
204 for (i = 0; i < 4; i++) {
205 if ((povstate & (1 << i)) && !(joy_oldpovstate & (1 << i))) {
206 Key_Event (QFJ_BUTTON29 + i, -1, true);
207 }
208
209 if (!(povstate & (1 << i)) && (joy_oldpovstate & (1 << i))) {
210 Key_Event (QFJ_BUTTON29 + i, -1, false);
211 }
212 }
213 joy_oldpovstate = povstate;
214 }
215 }
216
217 static int
JOY_StartupJoystick(void)218 JOY_StartupJoystick (void)
219 {
220 int /* i, */ numdevs;
221 JOYCAPS jc;
222 MMRESULT mmr = !JOYERR_NOERROR;
223
224 // assume no joystick
225 joy_found = false;
226
227 // abort startup if user requests no joystick
228 if (COM_CheckParm ("-nojoy"))
229 return -1;
230
231 // verify joystick driver is present
232 if ((numdevs = joyGetNumDevs ()) == 0) {
233 Sys_Printf ("\njoystick not found -- driver not present\n\n");
234 return -1;
235 }
236 // cycle through the joystick ids for the first valid one
237 for (joy_id = 0; joy_id < numdevs; joy_id++) {
238 memset (&ji, 0, sizeof (ji));
239 ji.dwSize = sizeof (ji);
240 ji.dwFlags = JOY_RETURNCENTERED;
241
242 if ((mmr = joyGetPosEx (joy_id, &ji)) == JOYERR_NOERROR)
243 break;
244 }
245
246 // abort startup if we didn't find a valid joystick
247 if (mmr != JOYERR_NOERROR) {
248 Sys_Printf ("\njoystick not found -- no valid joysticks (%x)\n\n",
249 mmr);
250 return -1;
251 }
252 // get the capabilities of the selected joystick
253 // abort startup if command fails
254 memset (&jc, 0, sizeof (jc));
255 if ((mmr = joyGetDevCaps (joy_id, &jc, sizeof (jc))) != JOYERR_NOERROR) {
256 Sys_Printf
257 ("\njoystick not found -- invalid joystick capabilities (%x)\n\n",
258 mmr);
259 return -1;
260 }
261 // save the joystick's number of buttons and POV status
262 joy_numbuttons = jc.wNumButtons;
263 joy_haspov = jc.wCaps & JOYCAPS_HASPOV;
264
265 // old button and POV states default to no buttons pressed
266 joy_oldbuttonstate = joy_oldpovstate = 0;
267
268 // mark the joystick as available and advanced initialization not
269 // completed
270 // this is needed as cvars are not available during initialization
271
272 joy_advancedinit = false;
273 joy_found = true;
274 // FIXME: do this right
275 joy_active = true;
276 Sys_Printf ("\njoystick detected\n\n");
277 return 0;
278 }
279
280 int
JOY_Open(void)281 JOY_Open (void)
282 {
283 return JOY_StartupJoystick();
284 // Cmd_AddCommand ("joyadvancedupdate", JOY_AdvancedUpdate_f, "FIXME: This "
285 // "appears to update the joystick poll? No Description");
286 }
287
288 void
JOY_Close(void)289 JOY_Close (void)
290 {
291 }
292 #if 0
293 static void
294 JOY_AdvancedUpdate_f (void)
295 {
296 // called once by JOY_ReadJoystick and by user whenever an update is
297 // needed
298 // cvars are now available
299 int i;
300 DWORD dwTemp;
301
302 // initialize all the maps
303 for (i = 0; i < JOY_MAX_AXES; i++) {
304 dwAxisMap[i] = AxisNada;
305 dwControlMap[i] = JOY_ABSOLUTE_AXIS;
306 pdwRawValue[i] = RawValuePointer (i);
307 }
308
309 if (joy_advanced->int_val) {
310 // default joystick initialization
311 // only 2 axes with joystick control
312 dwAxisMap[JOY_AXIS_X] = AxisTurn;
313 // dwControlMap[JOY_AXIS_X] = JOY_ABSOLUTE_AXIS;
314 dwAxisMap[JOY_AXIS_Y] = AxisForward;
315 // dwControlMap[JOY_AXIS_Y] = JOY_ABSOLUTE_AXIS;
316 } else {
317 if (strcmp (joy_name->string, "joystick") != 0) {
318 // notify user of advanced controller
319 Sys_Printf ("\n%s configured\n\n", joy_name->string);
320 }
321 // advanced initialization here
322 // data supplied by user via joy_axisn cvars
323 dwTemp = joy_advaxisx->int_val;
324 dwAxisMap[JOY_AXIS_X] = dwTemp & 0x0000000f;
325 dwControlMap[JOY_AXIS_X] = dwTemp & JOY_RELATIVE_AXIS;
326 dwTemp = joy_advaxisy->int_val;
327 dwAxisMap[JOY_AXIS_Y] = dwTemp & 0x0000000f;
328 dwControlMap[JOY_AXIS_Y] = dwTemp & JOY_RELATIVE_AXIS;
329 dwTemp = joy_advaxisz->int_val;
330 dwAxisMap[JOY_AXIS_Z] = dwTemp & 0x0000000f;
331 dwControlMap[JOY_AXIS_Z] = dwTemp & JOY_RELATIVE_AXIS;
332 dwTemp = joy_advaxisr->int_val;
333 dwAxisMap[JOY_AXIS_R] = dwTemp & 0x0000000f;
334 dwControlMap[JOY_AXIS_R] = dwTemp & JOY_RELATIVE_AXIS;
335 dwTemp = joy_advaxisu->int_val;
336 dwAxisMap[JOY_AXIS_U] = dwTemp & 0x0000000f;
337 dwControlMap[JOY_AXIS_U] = dwTemp & JOY_RELATIVE_AXIS;
338 dwTemp = joy_advaxisv->int_val;
339 dwAxisMap[JOY_AXIS_V] = dwTemp & 0x0000000f;
340 dwControlMap[JOY_AXIS_V] = dwTemp & JOY_RELATIVE_AXIS;
341 }
342
343 // compute the axes to collect from DirectInput
344 joy_flags = JOY_RETURNCENTERED | JOY_RETURNBUTTONS | JOY_RETURNPOV;
345 for (i = 0; i < JOY_MAX_AXES; i++) {
346 if (dwAxisMap[i] != AxisNada) {
347 joy_flags |= dwAxisFlags[i];
348 }
349 }
350 }
351
352 void
353 JOY_Init_Cvars(void)
354 {
355 // joystick variables
356 joy_device = Cvar_Get ("joy_device", "none", CVAR_NONE | CVAR_ROM, 0,
357 "Joystick device");
358 joy_enable = Cvar_Get ("joy_enable", "1", CVAR_NONE | CVAR_ARCHIVE, 0,
359 "Joystick enable flag");
360 joy_sensitivity = Cvar_Get ("joy_sensitivity", "1", CVAR_NONE |
361 CVAR_ARCHIVE, 0, "Joystick sensitivity");
362 in_joystick = Cvar_Get ("joystick", "0", CVAR_ARCHIVE, 0, "FIXME: No "
363 "Description");
364 joy_name = Cvar_Get ("joyname", "joystick", CVAR_NONE, 0, "FIXME: No "
365 "Description");
366 joy_advanced = Cvar_Get ("joyadvanced", "0", CVAR_NONE, 0, "FIXME: No "
367 "Description");
368 joy_advaxisx = Cvar_Get ("joyadvaxisx", "0", CVAR_NONE, 0, "FIXME: No "
369 "Description");
370 joy_advaxisy = Cvar_Get ("joyadvaxisy", "0", CVAR_NONE, 0, "FIXME: No "
371 "Description");
372 joy_advaxisz = Cvar_Get ("joyadvaxisz", "0", CVAR_NONE, 0, "FIXME: No "
373 "Description");
374 joy_advaxisr = Cvar_Get ("joyadvaxisr", "0", CVAR_NONE, 0, "FIXME: No "
375 "Description");
376 joy_advaxisu = Cvar_Get ("joyadvaxisu", "0", CVAR_NONE, 0, "FIXME: No "
377 "Description");
378 joy_advaxisv = Cvar_Get ("joyadvaxisv", "0", CVAR_NONE, 0, "FIXME: No "
379 "Description");
380 joy_forwardthreshold = Cvar_Get ("joyforwardthreshold", "0.15", CVAR_NONE,
381 0, "FIXME: No Description");
382 joy_sidethreshold = Cvar_Get ("joysidethreshold", "0.15", CVAR_NONE, 0,
383 "FIXME: No Description");
384 joy_pitchthreshold = Cvar_Get ("joypitchthreshold", "0.15", CVAR_NONE, 0,
385 "FIXME: No Description");
386 joy_yawthreshold = Cvar_Get ("joyyawthreshold", "0.15", CVAR_NONE, 0,
387 "FIXME: No Description");
388 joy_forwardsensitivity = Cvar_Get ("joyforwardsensitivity", "-1.0",
389 CVAR_NONE, 0, "FIXME: No Description");
390 joy_sidesensitivity = Cvar_Get ("joysidesensitivity", "-1.0", CVAR_NONE,
391 0, "FIXME: No Description");
392 joy_pitchsensitivity = Cvar_Get ("joypitchsensitivity", "1.0", CVAR_NONE,
393 0, "FIXME: No Description");
394 joy_yawsensitivity = Cvar_Get ("joyyawsensitivity", "-1.0", CVAR_NONE, 0,
395 "FIXME: No Description");
396 joy_wwhack1 = Cvar_Get ("joywwhack1", "0.0", CVAR_NONE, 0, "FIXME: No "
397 "Description");
398 joy_wwhack2 = Cvar_Get ("joywwhack2", "0.0", CVAR_NONE, 0, "FIXME: No "
399 "Description");
400
401 joy_debug = Cvar_Get ("joy_debug", "0.0", CVAR_NONE, 0, "FIXME: No "
402 "Description");
403 return;
404 }
405 #endif
406