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