1 /*
2 * control.c
3 * MACT library controller handling
4 *
5 * Derived from MACT386.LIB disassembly by Jonathon Fowler
6 *
7 */
8
9 #include "build.h"
10 #include "baselayer.h"
11 #include "pragmas.h"
12
13 #include "types.h"
14 #include "keyboard.h"
15 #include "mouse.h"
16 #include "control.h"
17 #include "_control.h"
18 #include "util_lib.h"
19
20
21 boolean CONTROL_JoyPresent = false;
22 boolean CONTROL_JoystickEnabled = false;
23 boolean CONTROL_MousePresent = false;
24 boolean CONTROL_MouseEnabled = false;
25 uint32 CONTROL_ButtonState1 = 0;
26 uint32 CONTROL_ButtonHeldState1 = 0;
27 uint32 CONTROL_ButtonState2 = 0;
28 uint32 CONTROL_ButtonHeldState2 = 0;
29
30 static int32 CONTROL_UserInputDelay = -1;
31 static int32 CONTROL_MouseSensitivity = DEFAULTMOUSESENSITIVITY;
32 static int32 CONTROL_NumMouseButtons = 0;
33 static int32 CONTROL_NumMouseAxes = 0;
34 static int32 CONTROL_NumJoyButtons = 0;
35 static int32 CONTROL_NumJoyAxes = 0;
36 static controlflags CONTROL_Flags[CONTROL_NUM_FLAGS];
37 static controlbuttontype CONTROL_MouseButtonMapping[MAXMOUSEBUTTONS];
38 static controlbuttontype CONTROL_JoyButtonMapping[MAXJOYBUTTONS];
39 static controlkeymaptype CONTROL_KeyMapping[CONTROL_NUM_FLAGS];
40 static controlaxismaptype CONTROL_MouseAxesMap[MAXMOUSEAXES]; // maps physical axes onto virtual ones
41 static controlaxismaptype CONTROL_JoyAxesMap[MAXJOYAXES];
42 static controlaxistype CONTROL_MouseAxes[MAXMOUSEAXES]; // physical axes
43 static controlaxistype CONTROL_JoyAxes[MAXJOYAXES];
44 static controlaxistype CONTROL_LastMouseAxes[MAXMOUSEAXES];
45 static controlaxistype CONTROL_LastJoyAxes[MAXJOYAXES];
46 static int32 CONTROL_MouseAxesScale[MAXMOUSEAXES];
47 static int32 CONTROL_JoyAxesScale[MAXJOYAXES];
48 static int32 CONTROL_JoyAxesDead[MAXJOYAXES];
49 static int32 CONTROL_JoyAxesSaturate[MAXJOYAXES];
50 static int32 CONTROL_MouseButtonState[MAXMOUSEBUTTONS];
51 static int32 CONTROL_JoyButtonState[MAXJOYBUTTONS];
52 static int32 CONTROL_MouseButtonClickedTime[MAXMOUSEBUTTONS];
53 static int32 CONTROL_JoyButtonClickedTime[MAXJOYBUTTONS];
54 static boolean CONTROL_MouseButtonClickedState[MAXMOUSEBUTTONS];
55 static boolean CONTROL_JoyButtonClickedState[MAXJOYBUTTONS];
56 static boolean CONTROL_MouseButtonClicked[MAXMOUSEBUTTONS];
57 static boolean CONTROL_JoyButtonClicked[MAXJOYBUTTONS];
58 static byte CONTROL_MouseButtonClickedCount[MAXMOUSEBUTTONS];
59 static byte CONTROL_JoyButtonClickedCount[MAXJOYBUTTONS];
60 static boolean CONTROL_UserInputCleared[3];
61 static int32 (*GetTime)(void);
62 static boolean CONTROL_Started = false;
63 static int32 ticrate;
64 static int32 CONTROL_DoubleClickSpeed;
65
66
CONTROL_GetMouseDelta(void)67 void CONTROL_GetMouseDelta(void)
68 {
69 int32 x,y;
70
71 MOUSE_GetDelta(&x, &y);
72
73 /* What in the name of all things sacred is this?
74 if (labs(*x) > labs(*y)) {
75 *x /= 3;
76 } else {
77 *y /= 3;
78 }
79 *y = *y * 96;
80 *x = (*x * 32 * CONTROL_MouseSensitivity) >> 15;
81 */
82
83 //CONTROL_MouseAxes[0].analog = mulscale8(x, CONTROL_MouseSensitivity);
84 //CONTROL_MouseAxes[1].analog = mulscale6(y, CONTROL_MouseSensitivity);
85
86 // DOS axis coefficients = 32,96
87 CONTROL_MouseAxes[0].analog = (x * CONTROL_MouseSensitivity) >> 15;
88 CONTROL_MouseAxes[1].analog = (y * CONTROL_MouseSensitivity) >> 15;
89 }
90
CONTROL_GetMouseSensitivity(void)91 int32 CONTROL_GetMouseSensitivity(void)
92 {
93 return (CONTROL_MouseSensitivity - MINIMUMMOUSESENSITIVITY);
94 }
95
CONTROL_SetMouseSensitivity(int32 newsensitivity)96 void CONTROL_SetMouseSensitivity(int32 newsensitivity)
97 {
98 CONTROL_MouseSensitivity = newsensitivity + MINIMUMMOUSESENSITIVITY;
99 }
100
CONTROL_SetJoyAxisDead(int32 axis,int32 newdead)101 void CONTROL_SetJoyAxisDead(int32 axis, int32 newdead)
102 {
103 if ((unsigned)axis >= MAXJOYAXES) return;
104 if (newdead < 0) newdead = 0;
105 if (newdead > 32767) newdead = 32767;
106 CONTROL_JoyAxesDead[axis] = newdead;
107 }
108
CONTROL_SetJoyAxisSaturate(int32 axis,int32 newsatur)109 void CONTROL_SetJoyAxisSaturate(int32 axis, int32 newsatur)
110 {
111 if ((unsigned)axis >= MAXJOYAXES) return;
112 if (newsatur < 0) newsatur = 0;
113 if (newsatur > 32767) newsatur = 32767;
114 CONTROL_JoyAxesSaturate[axis] = newsatur;
115 }
116
CONTROL_StartMouse(void)117 boolean CONTROL_StartMouse(void)
118 {
119 CONTROL_NumMouseButtons = MAXMOUSEBUTTONS;
120 return MOUSE_Init();
121 }
122
CONTROL_GetJoyAbs(void)123 void CONTROL_GetJoyAbs( void )
124 {
125 }
126
CONTROL_FilterJoyDelta(void)127 void CONTROL_FilterJoyDelta(void)
128 {
129 }
130
CONTROL_GetJoyDelta(void)131 void CONTROL_GetJoyDelta( void )
132 {
133 int32 i, delta, sign;
134
135 // for paired axes, like with a dual-stick controller,
136 // it would make more sense to use a circular dead-zone
137
138 for (i=0; i<joynumaxes; i++) {
139 sign = (joyaxis[i] < 0) ? -1 : 1;
140 delta = abs(joyaxis[i]);
141 if (delta < CONTROL_JoyAxesDead[i]) {
142 delta = 0;
143 } else if (delta > CONTROL_JoyAxesSaturate[i]) {
144 delta = 32767;
145 } else {
146 // scale the axis delta value to cover the clipped range
147 delta = (32767 * (delta - CONTROL_JoyAxesDead[i]))
148 / (CONTROL_JoyAxesSaturate[i] - CONTROL_JoyAxesDead[i]);
149 }
150
151 // apply a cube transform to make the axis react more strongly
152 // the further it is pushed. The multiply-dividing is to avoid
153 // overflowing the 32bit integer. It's really doing
154 // (delta*delta*delta) / (32767*32767)
155 // to yield 0-32767
156 delta = (((delta * delta) / 32767) * delta) / 32767;
157
158 CONTROL_JoyAxes[i].analog = delta * sign;
159 }
160 }
161
162
CONTROL_SetJoyScale(void)163 void CONTROL_SetJoyScale( void )
164 {
165 }
166
CONTROL_CenterJoystick(void (* CenterCenter)(void),void (* UpperLeft)(void),void (* LowerRight)(void),void (* CenterThrottle)(void),void (* CenterRudder)(void))167 void CONTROL_CenterJoystick
168 (
169 void ( *CenterCenter )( void ),
170 void ( *UpperLeft )( void ),
171 void ( *LowerRight )( void ),
172 void ( *CenterThrottle )( void ),
173 void ( *CenterRudder )( void )
174 )
175 {
176 }
177
CONTROL_StartJoy(int32 joy)178 boolean CONTROL_StartJoy(int32 joy)
179 {
180 return (inputdevices & 4) == 4;
181 }
182
CONTROL_ShutJoy(int32 joy)183 void CONTROL_ShutJoy(int32 joy)
184 {
185 CONTROL_JoyPresent = false;
186 }
187
CONTROL_GetTime(void)188 int32 CONTROL_GetTime(void)
189 {
190 static int32 t = 0;
191 t += 5;
192 return t;
193 }
194
CONTROL_CheckRange(int32 which)195 boolean CONTROL_CheckRange(int32 which)
196 {
197 if ((uint32)which < (uint32)CONTROL_NUM_FLAGS) return false;
198 //Error("CONTROL_CheckRange: Index %d out of valid range for %d control flags.",
199 // which, CONTROL_NUM_FLAGS);
200 return true;
201 }
202
CONTROL_SetFlag(int32 which,boolean active)203 void CONTROL_SetFlag(int32 which, boolean active)
204 {
205 if (CONTROL_CheckRange(which)) return;
206
207 if (CONTROL_Flags[which].toggle == INSTANT_ONOFF) {
208 CONTROL_Flags[which].active = active;
209 } else {
210 if (active) {
211 CONTROL_Flags[which].buttonheld = false;
212 } else if (CONTROL_Flags[which].buttonheld == false) {
213 CONTROL_Flags[which].buttonheld = true;
214 CONTROL_Flags[which].active = (CONTROL_Flags[which].active ? false : true);
215 }
216 }
217 }
218
CONTROL_KeyboardFunctionPressed(int32 which)219 boolean CONTROL_KeyboardFunctionPressed(int32 which)
220 {
221 boolean key1 = 0, key2 = 0;
222
223 if (CONTROL_CheckRange(which)) return false;
224
225 if (!CONTROL_Flags[which].used) return false;
226
227 if (CONTROL_KeyMapping[which].key1 != KEYUNDEFINED)
228 key1 = KB_KeyDown[ CONTROL_KeyMapping[which].key1 ] ? true : false;
229
230 if (CONTROL_KeyMapping[which].key2 != KEYUNDEFINED)
231 key2 = KB_KeyDown[ CONTROL_KeyMapping[which].key2 ] ? true : false;
232
233 return (key1 | key2);
234 }
235
CONTROL_ClearKeyboardFunction(int32 which)236 void CONTROL_ClearKeyboardFunction(int32 which)
237 {
238 if (CONTROL_CheckRange(which)) return;
239
240 if (!CONTROL_Flags[which].used) return;
241
242 if (CONTROL_KeyMapping[which].key1 != KEYUNDEFINED)
243 KB_KeyDown[ CONTROL_KeyMapping[which].key1 ] = 0;
244
245 if (CONTROL_KeyMapping[which].key2 != KEYUNDEFINED)
246 KB_KeyDown[ CONTROL_KeyMapping[which].key2 ] = 0;
247 }
248
CONTROL_DefineFlag(int32 which,boolean toggle)249 void CONTROL_DefineFlag( int32 which, boolean toggle )
250 {
251 if (CONTROL_CheckRange(which)) return;
252
253 CONTROL_Flags[which].active = false;
254 CONTROL_Flags[which].used = true;
255 CONTROL_Flags[which].toggle = toggle;
256 CONTROL_Flags[which].buttonheld = false;
257 CONTROL_Flags[which].cleared = 0;
258 }
259
CONTROL_FlagActive(int32 which)260 boolean CONTROL_FlagActive( int32 which )
261 {
262 if (CONTROL_CheckRange(which)) return false;
263
264 return CONTROL_Flags[which].used;
265 }
266
CONTROL_MapKey(int32 which,kb_scancode key1,kb_scancode key2)267 void CONTROL_MapKey( int32 which, kb_scancode key1, kb_scancode key2 )
268 {
269 if (CONTROL_CheckRange(which)) return;
270
271 CONTROL_KeyMapping[which].key1 = key1 ? key1 : KEYUNDEFINED;
272 CONTROL_KeyMapping[which].key2 = key2 ? key2 : KEYUNDEFINED;
273 }
274
CONTROL_PrintKeyMap(void)275 void CONTROL_PrintKeyMap(void)
276 {
277 int32 i;
278
279 for (i=0;i<CONTROL_NUM_FLAGS;i++) {
280 buildprintf("function %2d key1=%3x key2=%3x\n",
281 i, CONTROL_KeyMapping[i].key1, CONTROL_KeyMapping[i].key2);
282 }
283 }
284
CONTROL_PrintControlFlag(int32 which)285 void CONTROL_PrintControlFlag(int32 which)
286 {
287 buildprintf("function %2d active=%d used=%d toggle=%d buttonheld=%d cleared=%d\n",
288 which, CONTROL_Flags[which].active, CONTROL_Flags[which].used,
289 CONTROL_Flags[which].toggle, CONTROL_Flags[which].buttonheld,
290 CONTROL_Flags[which].cleared);
291 }
292
CONTROL_PrintAxes(void)293 void CONTROL_PrintAxes(void)
294 {
295 int32 i;
296
297 buildprintf("nummouseaxes=%d\n", CONTROL_NumMouseAxes);
298 for (i=0;i<CONTROL_NumMouseAxes;i++) {
299 buildprintf("axis=%d analog=%d digital1=%d digital2=%d\n",
300 i, CONTROL_MouseAxesMap[i].analogmap,
301 CONTROL_MouseAxesMap[i].minmap, CONTROL_MouseAxesMap[i].maxmap);
302 }
303
304 buildprintf("numjoyaxes=%d\n", CONTROL_NumJoyAxes);
305 for (i=0;i<CONTROL_NumJoyAxes;i++) {
306 buildprintf("axis=%d analog=%d digital1=%d digital2=%d\n",
307 i, CONTROL_JoyAxesMap[i].analogmap,
308 CONTROL_JoyAxesMap[i].minmap, CONTROL_JoyAxesMap[i].maxmap);
309 }
310 }
311
CONTROL_MapButton(int32 whichfunction,int32 whichbutton,boolean doubleclicked,controldevice device)312 void CONTROL_MapButton( int32 whichfunction, int32 whichbutton, boolean doubleclicked, controldevice device )
313 {
314 controlbuttontype *set;
315
316 if (CONTROL_CheckRange(whichfunction)) whichfunction = BUTTONUNDEFINED;
317
318 switch (device) {
319 case controldevice_mouse:
320 if ((uint32)whichbutton >= (uint32)MAXMOUSEBUTTONS) {
321 //Error("CONTROL_MapButton: button %d out of valid range for %d mouse buttons.",
322 // whichbutton, CONTROL_NumMouseButtons);
323 return;
324 }
325 set = CONTROL_MouseButtonMapping;
326 break;
327
328 case controldevice_joystick:
329 if ((uint32)whichbutton >= (uint32)MAXJOYBUTTONS) {
330 //Error("CONTROL_MapButton: button %d out of valid range for %d joystick buttons.",
331 // whichbutton, CONTROL_NumJoyButtons);
332 return;
333 }
334 set = CONTROL_JoyButtonMapping;
335 break;
336
337 default:
338 //Error("CONTROL_MapButton: invalid controller device type");
339 return;
340 }
341
342 if (doubleclicked)
343 set[whichbutton].doubleclicked = whichfunction;
344 else
345 set[whichbutton].singleclicked = whichfunction;
346 }
347
CONTROL_MapAnalogAxis(int32 whichaxis,int32 whichanalog,controldevice device)348 void CONTROL_MapAnalogAxis( int32 whichaxis, int32 whichanalog, controldevice device )
349 {
350 controlaxismaptype *set;
351
352 if ((uint32)whichanalog >= (uint32)analog_maxtype) {
353 //Error("CONTROL_MapAnalogAxis: analog function %d out of valid range for %d analog functions.",
354 // whichanalog, analog_maxtype);
355 return;
356 }
357
358 switch (device) {
359 case controldevice_mouse:
360 if ((uint32)whichaxis >= (uint32)MAXMOUSEAXES) {
361 //Error("CONTROL_MapAnalogAxis: axis %d out of valid range for %d mouse axes.",
362 // whichaxis, MAXMOUSEAXES);
363 return;
364 }
365
366 set = CONTROL_MouseAxesMap;
367 break;
368
369 case controldevice_joystick:
370 if ((uint32)whichaxis >= (uint32)MAXJOYAXES) {
371 //Error("CONTROL_MapAnalogAxis: axis %d out of valid range for %d joystick axes.",
372 // whichaxis, MAXJOYAXES);
373 return;
374 }
375
376 set = CONTROL_JoyAxesMap;
377 break;
378
379 default:
380 //Error("CONTROL_MapAnalogAxis: invalid controller device type");
381 return;
382 }
383
384 set[whichaxis].analogmap = whichanalog;
385 }
386
CONTROL_SetAnalogAxisScale(int32 whichaxis,int32 axisscale,controldevice device)387 void CONTROL_SetAnalogAxisScale( int32 whichaxis, int32 axisscale, controldevice device )
388 {
389 int32 *set;
390
391 switch (device) {
392 case controldevice_mouse:
393 if ((uint32)whichaxis >= (uint32)MAXMOUSEAXES) {
394 //Error("CONTROL_SetAnalogAxisScale: axis %d out of valid range for %d mouse axes.",
395 // whichaxis, MAXMOUSEAXES);
396 return;
397 }
398
399 set = CONTROL_MouseAxesScale;
400 break;
401
402 case controldevice_joystick:
403 if ((uint32)whichaxis >= (uint32)MAXJOYAXES) {
404 //Error("CONTROL_SetAnalogAxisScale: axis %d out of valid range for %d joystick axes.",
405 // whichaxis, MAXJOYAXES);
406 return;
407 }
408
409 set = CONTROL_JoyAxesScale;
410 break;
411
412 default:
413 //Error("CONTROL_SetAnalogAxisScale: invalid controller device type");
414 return;
415 }
416
417 set[whichaxis] = axisscale;
418 }
419
CONTROL_MapDigitalAxis(int32 whichaxis,int32 whichfunction,int32 direction,controldevice device)420 void CONTROL_MapDigitalAxis( int32 whichaxis, int32 whichfunction, int32 direction, controldevice device )
421 {
422 controlaxismaptype *set;
423
424 if (CONTROL_CheckRange(whichfunction)) whichfunction = AXISUNDEFINED;
425
426 switch (device) {
427 case controldevice_mouse:
428 if ((uint32)whichaxis >= (uint32)MAXMOUSEAXES) {
429 //Error("CONTROL_MapDigitalAxis: axis %d out of valid range for %d mouse axes.",
430 // whichaxis, MAXMOUSEAXES);
431 return;
432 }
433
434 set = CONTROL_MouseAxesMap;
435 break;
436
437 case controldevice_joystick:
438 if ((uint32)whichaxis >= (uint32)MAXJOYAXES) {
439 //Error("CONTROL_MapDigitalAxis: axis %d out of valid range for %d joystick axes.",
440 // whichaxis, MAXJOYAXES);
441 return;
442 }
443
444 set = CONTROL_JoyAxesMap;
445 break;
446
447 default:
448 //Error("CONTROL_MapDigitalAxis: invalid controller device type");
449 return;
450 }
451
452 switch (direction) { // JBF: this is all very much a guess. The ASM puzzles me.
453 case axis_up:
454 case axis_left:
455 set[whichaxis].minmap = whichfunction;
456 break;
457 case axis_down:
458 case axis_right:
459 set[whichaxis].maxmap = whichfunction;
460 break;
461 default:
462 break;
463 }
464 }
465
CONTROL_ClearFlags(void)466 void CONTROL_ClearFlags(void)
467 {
468 int32 i;
469
470 for (i=0;i<CONTROL_NUM_FLAGS;i++)
471 CONTROL_Flags[i].used = false;
472 }
473
CONTROL_ClearAssignments(void)474 void CONTROL_ClearAssignments( void )
475 {
476 int32 i;
477
478 memset(CONTROL_MouseButtonMapping, BUTTONUNDEFINED, sizeof(CONTROL_MouseButtonMapping));
479 memset(CONTROL_JoyButtonMapping, BUTTONUNDEFINED, sizeof(CONTROL_JoyButtonMapping));
480 memset(CONTROL_KeyMapping, KEYUNDEFINED, sizeof(CONTROL_KeyMapping));
481 memset(CONTROL_MouseAxesMap, AXISUNDEFINED, sizeof(CONTROL_MouseAxesMap));
482 memset(CONTROL_JoyAxesMap, AXISUNDEFINED, sizeof(CONTROL_JoyAxesMap));
483 memset(CONTROL_MouseAxes, 0, sizeof(CONTROL_MouseAxes));
484 memset(CONTROL_JoyAxes, 0, sizeof(CONTROL_JoyAxes));
485 memset(CONTROL_LastMouseAxes, 0, sizeof(CONTROL_LastMouseAxes));
486 memset(CONTROL_LastJoyAxes, 0, sizeof(CONTROL_LastJoyAxes));
487 for (i=0;i<MAXMOUSEAXES;i++)
488 CONTROL_MouseAxesScale[i] = NORMALAXISSCALE;
489 for (i=0;i<MAXJOYAXES;i++) {
490 CONTROL_JoyAxesScale[i] = NORMALAXISSCALE;
491 CONTROL_JoyAxesDead[i] = 0;
492 CONTROL_JoyAxesSaturate[i] = 32767;
493 }
494 }
495
DoGetDeviceButtons(int32 buttons,int32 tm,int32 NumButtons,int32 * DeviceButtonState,int32 * ButtonClickedTime,boolean * ButtonClickedState,boolean * ButtonClicked,byte * ButtonClickedCount)496 static void DoGetDeviceButtons(
497 int32 buttons, int32 tm,
498 int32 NumButtons,
499 int32 *DeviceButtonState,
500 int32 *ButtonClickedTime,
501 boolean *ButtonClickedState,
502 boolean *ButtonClicked,
503 byte *ButtonClickedCount
504 ) {
505 int32 i, bs;
506
507 for (i=0;i<NumButtons;i++) {
508 bs = (buttons >> i) & 1;
509
510 DeviceButtonState[i] = bs;
511 ButtonClickedState[i] = false;
512
513 if (bs) {
514 if (ButtonClicked[i] == false) {
515 ButtonClicked[i] = true;
516
517 if (ButtonClickedCount[i] == 0 || tm > ButtonClickedTime[i]) {
518 ButtonClickedTime[i] = tm + CONTROL_DoubleClickSpeed;
519 ButtonClickedCount[i] = 1;
520 }
521 else if (tm < ButtonClickedTime[i]) {
522 ButtonClickedState[i] = true;
523 ButtonClickedTime[i] = 0;
524 ButtonClickedCount[i] = 2;
525 }
526 }
527 else if (ButtonClickedCount[i] == 2) {
528 ButtonClickedState[i] = true;
529 }
530 } else {
531 if (ButtonClickedCount[i] == 2)
532 ButtonClickedCount[i] = 0;
533
534 ButtonClicked[i] = false;
535 }
536 }
537 }
538
CONTROL_GetDeviceButtons(void)539 void CONTROL_GetDeviceButtons(void)
540 {
541 int32 t;
542
543 t = GetTime();
544
545 if (CONTROL_MouseEnabled) {
546 DoGetDeviceButtons(
547 MOUSE_GetButtons(), t,
548 CONTROL_NumMouseButtons,
549 CONTROL_MouseButtonState,
550 CONTROL_MouseButtonClickedTime,
551 CONTROL_MouseButtonClickedState,
552 CONTROL_MouseButtonClicked,
553 CONTROL_MouseButtonClickedCount
554 );
555 }
556
557 if (CONTROL_JoystickEnabled) {
558 int32 buttons = joyb;
559 DoGetDeviceButtons(
560 buttons, t,
561 CONTROL_NumJoyButtons,
562 CONTROL_JoyButtonState,
563 CONTROL_JoyButtonClickedTime,
564 CONTROL_JoyButtonClickedState,
565 CONTROL_JoyButtonClicked,
566 CONTROL_JoyButtonClickedCount
567 );
568 }
569 }
570
CONTROL_DigitizeAxis(int32 axis,controldevice device)571 void CONTROL_DigitizeAxis(int32 axis, controldevice device)
572 {
573 controlaxistype *set, *lastset;
574 int32 delta, shiftval, threshold;
575
576 switch (device) {
577 case controldevice_mouse:
578 set = CONTROL_MouseAxes;
579 lastset = CONTROL_LastMouseAxes;
580 shiftval = 0;
581 threshold = MINTHRESHOLD;
582 break;
583
584 case controldevice_joystick:
585 set = CONTROL_JoyAxes;
586 lastset = CONTROL_LastJoyAxes;
587 shiftval = 8;
588 threshold = THRESHOLD;
589 break;
590
591 default:
592 return;
593 }
594
595 delta = set[axis].analog >> shiftval;
596
597 if (delta > 0) {
598 if (delta > threshold) { // if very much in one direction,
599 set[axis].digital = 1; // set affirmative
600 } else {
601 if (delta > MINTHRESHOLD) { // if hanging in limbo,
602 if (lastset[axis].digital == 1) // set if in same direction as last time
603 set[axis].digital = 1;
604 }
605 }
606 } else if (delta < 0) {
607 if (delta < -threshold) {
608 set[axis].digital = -1;
609 } else {
610 if (delta < -MINTHRESHOLD) {
611 if (lastset[axis].digital == -1)
612 set[axis].digital = -1;
613 }
614 }
615 }
616 }
617
CONTROL_ScaleAxis(int32 axis,controldevice device)618 void CONTROL_ScaleAxis(int32 axis, controldevice device)
619 {
620 controlaxistype *set;
621 int32 *scale;
622
623 switch (device) {
624 case controldevice_mouse:
625 set = CONTROL_MouseAxes;
626 scale = CONTROL_MouseAxesScale;
627 break;
628
629 case controldevice_joystick:
630 set = CONTROL_JoyAxes;
631 scale = CONTROL_JoyAxesScale;
632 break;
633
634 default: return;
635 }
636
637 set[axis].analog = mulscale16(set[axis].analog, scale[axis]);
638 }
639
CONTROL_ApplyAxis(int32 axis,ControlInfo * info,controldevice device)640 void CONTROL_ApplyAxis(int32 axis, ControlInfo *info, controldevice device)
641 {
642 controlaxistype *set;
643 controlaxismaptype *map;
644 int32 shiftval;
645
646 switch (device) {
647 case controldevice_mouse:
648 set = CONTROL_MouseAxes;
649 map = CONTROL_MouseAxesMap;
650 shiftval = 0;
651 break;
652
653 case controldevice_joystick:
654 set = CONTROL_JoyAxes;
655 map = CONTROL_JoyAxesMap;
656
657 // joystick axes are |0-32767| so chop them back to something
658 // closer to a mouse input range so the game sees similar sort
659 // of motion regardless of the device that contributed it
660 shiftval = 8;
661 break;
662
663 default: return;
664 }
665
666 switch (map[axis].analogmap) {
667 case analog_turning: info->dyaw += set[axis].analog >> shiftval; break;
668 case analog_strafing: info->dx += set[axis].analog >> shiftval; break;
669 case analog_lookingupanddown: info->dpitch += set[axis].analog >> shiftval; break;
670 case analog_elevation: info->dy += set[axis].analog >> shiftval; break;
671 case analog_rolling: info->droll += set[axis].analog >> shiftval; break;
672 case analog_moving: info->dz += set[axis].analog >> shiftval; break;
673 default: break;
674 }
675 }
676
CONTROL_PollDevices(ControlInfo * info)677 void CONTROL_PollDevices(ControlInfo *info)
678 {
679 int32 i;
680
681 memcpy(CONTROL_LastMouseAxes, CONTROL_MouseAxes, sizeof(CONTROL_MouseAxes));
682 memcpy(CONTROL_LastJoyAxes, CONTROL_JoyAxes, sizeof(CONTROL_JoyAxes));
683
684 memset(CONTROL_MouseAxes, 0, sizeof(CONTROL_MouseAxes));
685 memset(CONTROL_JoyAxes, 0, sizeof(CONTROL_JoyAxes));
686 memset(info, 0, sizeof(ControlInfo));
687
688 if (CONTROL_MouseEnabled) {
689 CONTROL_GetMouseDelta();
690
691 for (i=0; i<MAXMOUSEAXES; i++) {
692 CONTROL_DigitizeAxis(i, controldevice_mouse);
693 CONTROL_ScaleAxis(i, controldevice_mouse);
694 LIMITCONTROL(&CONTROL_MouseAxes[i].analog);
695 CONTROL_ApplyAxis(i, info, controldevice_mouse);
696 }
697 }
698 if (CONTROL_JoystickEnabled) {
699 CONTROL_GetJoyDelta();
700
701 for (i=0; i<MAXJOYAXES; i++) {
702 CONTROL_DigitizeAxis(i, controldevice_joystick);
703 CONTROL_ScaleAxis(i, controldevice_joystick);
704 LIMITCONTROL(&CONTROL_JoyAxes[i].analog);
705 CONTROL_ApplyAxis(i, info, controldevice_joystick);
706 }
707 }
708
709 CONTROL_GetDeviceButtons();
710 }
711
CONTROL_AxisFunctionState(int32 * p1)712 void CONTROL_AxisFunctionState(int32 *p1)
713 {
714 int32 i, j;
715
716 for (i=0; i<CONTROL_NumMouseAxes; i++) {
717 if (!CONTROL_MouseAxes[i].digital) continue;
718
719 if (CONTROL_MouseAxes[i].digital < 0)
720 j = CONTROL_MouseAxesMap[i].minmap;
721 else
722 j = CONTROL_MouseAxesMap[i].maxmap;
723
724 if (j != AXISUNDEFINED)
725 p1[j] = 1;
726 }
727
728 for (i=0; i<CONTROL_NumJoyAxes; i++) {
729 if (!CONTROL_JoyAxes[i].digital) continue;
730
731 if (CONTROL_JoyAxes[i].digital < 0)
732 j = CONTROL_JoyAxesMap[i].minmap;
733 else
734 j = CONTROL_JoyAxesMap[i].maxmap;
735
736 if (j != AXISUNDEFINED)
737 p1[j] = 1;
738 }
739 }
740
CONTROL_ButtonFunctionState(int32 * p1)741 void CONTROL_ButtonFunctionState( int32 *p1 )
742 {
743 int32 i, j;
744
745 for (i=0; i<CONTROL_NumMouseButtons; i++) {
746 j = CONTROL_MouseButtonMapping[i].doubleclicked;
747 if (j != KEYUNDEFINED)
748 p1[j] |= CONTROL_MouseButtonClickedState[i];
749
750 j = CONTROL_MouseButtonMapping[i].singleclicked;
751 if (j != KEYUNDEFINED)
752 p1[j] |= CONTROL_MouseButtonState[i];
753 }
754
755 for (i=0; i<CONTROL_NumJoyButtons; i++) {
756 j = CONTROL_JoyButtonMapping[i].doubleclicked;
757 if (j != KEYUNDEFINED)
758 p1[j] |= CONTROL_JoyButtonClickedState[i];
759
760 j = CONTROL_JoyButtonMapping[i].singleclicked;
761 if (j != KEYUNDEFINED)
762 p1[j] |= CONTROL_JoyButtonState[i];
763 }
764 }
765
CONTROL_GetUserInput(UserInput * info)766 void CONTROL_GetUserInput( UserInput *info )
767 {
768 ControlInfo ci;
769
770 CONTROL_PollDevices( &ci );
771
772 info->dir = dir_None;
773
774 // checks if CONTROL_UserInputDelay is too far in the future due to clock skew?
775 if (GetTime() + ((ticrate * USERINPUTDELAY) / 1000) < CONTROL_UserInputDelay)
776 CONTROL_UserInputDelay = -1;
777
778 if (GetTime() >= CONTROL_UserInputDelay) {
779 if (CONTROL_MouseAxes[1].digital == -1)
780 info->dir = dir_North;
781 else if (CONTROL_MouseAxes[1].digital == 1)
782 info->dir = dir_South;
783 else if (CONTROL_MouseAxes[0].digital == -1)
784 info->dir = dir_West;
785 else if (CONTROL_MouseAxes[0].digital == 1)
786 info->dir = dir_East;
787
788 if (CONTROL_JoyAxes[1].digital == -1)
789 info->dir = dir_North;
790 else if (CONTROL_JoyAxes[1].digital == 1)
791 info->dir = dir_South;
792 else if (CONTROL_JoyAxes[0].digital == -1)
793 info->dir = dir_West;
794 else if (CONTROL_JoyAxes[0].digital == 1)
795 info->dir = dir_East;
796
797 if (CONTROL_JoyButtonState[joybutton_DpadUp])
798 info->dir = dir_North;
799 else if (CONTROL_JoyButtonState[joybutton_DpadDown])
800 info->dir = dir_South;
801 else if (CONTROL_JoyButtonState[joybutton_DpadLeft])
802 info->dir = dir_West;
803 else if (CONTROL_JoyButtonState[joybutton_DpadRight])
804 info->dir = dir_East;
805
806 if (KB_KeyDown[sc_kpad_8] || KB_KeyDown[sc_UpArrow])
807 info->dir = dir_North;
808 else if (KB_KeyDown[sc_kpad_2] || KB_KeyDown[sc_DownArrow])
809 info->dir = dir_South;
810 else if (KB_KeyDown[sc_kpad_4] || KB_KeyDown[sc_LeftArrow])
811 info->dir = dir_West;
812 else if (KB_KeyDown[sc_kpad_6] || KB_KeyDown[sc_RightArrow])
813 info->dir = dir_East;
814 }
815
816 info->button0 = CONTROL_MouseButtonState[mousebutton_Left] | CONTROL_JoyButtonState[joybutton_A];
817 info->button1 = CONTROL_MouseButtonState[mousebutton_Right] | CONTROL_JoyButtonState[joybutton_B];
818
819 if (KB_KeyDown[BUTTON0_SCAN_1] || KB_KeyDown[BUTTON0_SCAN_2] || KB_KeyDown[BUTTON0_SCAN_3])
820 info->button0 = 1;
821 if (KB_KeyDown[BUTTON1_SCAN])
822 info->button1 = 1;
823
824 if (CONTROL_UserInputCleared[1]) {
825 if (!info->button0)
826 CONTROL_UserInputCleared[1] = false;
827 else
828 info->button0 = false;
829 }
830 if (CONTROL_UserInputCleared[2]) {
831 if (!info->button1)
832 CONTROL_UserInputCleared[2] = false;
833 else
834 info->button1 = false;
835 }
836 }
837
CONTROL_ClearUserInput(UserInput * info)838 void CONTROL_ClearUserInput( UserInput *info )
839 {
840 switch (info->dir) {
841 case dir_North:
842 case dir_South:
843 case dir_East:
844 case dir_West:
845 CONTROL_UserInputCleared[0] = true;
846 CONTROL_UserInputDelay = GetTime() + ((ticrate * USERINPUTDELAY) / 1000);
847 break;
848 default: break;
849 }
850 if (info->button0) CONTROL_UserInputCleared[1] = true;
851 if (info->button1) CONTROL_UserInputCleared[2] = true;
852 }
853
CONTROL_ClearButton(int32 whichbutton)854 void CONTROL_ClearButton( int32 whichbutton )
855 {
856 if (CONTROL_CheckRange( whichbutton )) return;
857 BUTTONCLEAR( whichbutton );
858 CONTROL_Flags[whichbutton].cleared = true;
859 }
860
CONTROL_GetInput(ControlInfo * info)861 void CONTROL_GetInput( ControlInfo *info )
862 {
863 int32 i, periphs[CONTROL_NUM_FLAGS];
864
865 CONTROL_PollDevices( info );
866
867 memset(periphs, 0, sizeof(periphs));
868 CONTROL_ButtonFunctionState(periphs);
869 CONTROL_AxisFunctionState(periphs);
870
871 CONTROL_ButtonHeldState1 = CONTROL_ButtonState1;
872 CONTROL_ButtonHeldState2 = CONTROL_ButtonState2;
873 CONTROL_ButtonState1 = CONTROL_ButtonState2 = 0;
874
875 for (i=0; i<CONTROL_NUM_FLAGS; i++) {
876 CONTROL_SetFlag(i, CONTROL_KeyboardFunctionPressed(i) | periphs[i]);
877
878 if (CONTROL_Flags[i].cleared == false) BUTTONSET(i, CONTROL_Flags[i].active);
879 else if (CONTROL_Flags[i].active == false) CONTROL_Flags[i].cleared = 0;
880 }
881 }
882
CONTROL_WaitRelease(void)883 void CONTROL_WaitRelease( void )
884 {
885 }
886
CONTROL_Ack(void)887 void CONTROL_Ack( void )
888 {
889 }
890
CONTROL_Startup(controltype which,int32 (* TimeFunction)(void),int32 ticspersecond)891 boolean CONTROL_Startup(controltype which, int32 ( *TimeFunction )( void ), int32 ticspersecond)
892 {
893 int32 i;
894 char *p;
895
896 if (CONTROL_Started) return false;
897
898 if (TimeFunction) GetTime = TimeFunction;
899 else GetTime = CONTROL_GetTime;
900
901 ticrate = ticspersecond;
902
903 CONTROL_DoubleClickSpeed = (ticspersecond*57)/100;
904 if (CONTROL_DoubleClickSpeed <= 0)
905 CONTROL_DoubleClickSpeed = 1;
906
907 if (initinput()) return true;
908
909 CONTROL_MousePresent = CONTROL_MouseEnabled = false;
910 CONTROL_JoyPresent = CONTROL_JoystickEnabled = false;
911 CONTROL_NumMouseButtons = CONTROL_NumJoyButtons = 0;
912 CONTROL_NumMouseAxes = CONTROL_NumJoyAxes = 0;
913 KB_Startup();
914
915 //switch (which) {
916 // case controltype_keyboard:
917 // break;
918
919 // case controltype_keyboardandmouse:
920 CONTROL_NumMouseAxes = MAXMOUSEAXES;
921 CONTROL_NumMouseButtons = MAXMOUSEBUTTONS;
922 CONTROL_MousePresent = MOUSE_Init();
923 CONTROL_MouseEnabled = CONTROL_MousePresent;
924 // break;
925
926 // case controltype_keyboardandjoystick:
927 CONTROL_NumJoyAxes = min(MAXJOYAXES,joynumaxes);
928 CONTROL_NumJoyButtons = min(MAXJOYBUTTONS,joynumbuttons);
929 CONTROL_JoyPresent = CONTROL_StartJoy(0);
930 CONTROL_JoystickEnabled = CONTROL_JoyPresent;
931 // break;
932 //}
933
934 if (CONTROL_MousePresent)
935 buildprintf("CONTROL_Startup: Mouse Present\n");
936 if (CONTROL_JoyPresent)
937 buildprintf("CONTROL_Startup: Joystick Present\n");
938
939 CONTROL_ButtonState1 = 0;
940 CONTROL_ButtonState2 = 0;
941 CONTROL_ButtonHeldState1 = 0;
942 CONTROL_ButtonHeldState2 = 0;
943
944 memset(CONTROL_UserInputCleared, 0, sizeof(CONTROL_UserInputCleared));
945
946 for (i=0; i<CONTROL_NUM_FLAGS; i++)
947 CONTROL_Flags[i].used = false;
948
949 CONTROL_Started = true;
950
951 return false;
952 }
953
CONTROL_Shutdown(void)954 void CONTROL_Shutdown(void)
955 {
956 if (!CONTROL_Started) return;
957
958 CONTROL_JoyPresent = false;
959
960 MOUSE_Shutdown();
961 uninitinput();
962
963 CONTROL_Started = false;
964 }
965
966