1 // Interface  functions (written in C++) for
2 // Direct3D immediate mode system
3 
4 // Must link to C code in main engine system
5 
6 extern "C" {
7 
8 // Note: INITGUID has NOT been defined here,
9 // since the definition in d3_func.cpp is amply
10 // sufficient.
11 
12 #include "3dc.h"
13 #include "module.h"
14 #include "inline.h"
15 #include "stratdef.h"
16 #include "gamedef.h"
17 #include "gameplat.h"
18 #include "usr_io.h"
19 extern "C++"{
20 #include "iofocus.h"
21 };
22 
23 #include "showcmds.h"
24 
25 // DirectInput key down value
26 #define DikOn 0x80
27 
28 // Internal DirectInput driver
29 // buffer Size for direct mouse read
30 #define DMouse_BufferSize         128
31 
32 // Maximum number of buffered events retrievable
33 // from a mouse data acquisition
34 #define DMouse_RetrieveSize       128
35 
36 /*
37 	These are (hopefully) temporary #defines,
38 	introduced as a hack because the curious
39 	FIELD_OFFSET macros in the dinput.h header
40 	don't appear to compile, at least in Watcom 10.6.
41 	They will obviously have to be kept up to date
42 	with changes in the DIMOUSESTATE structure manually.
43 */
44 
45 #define DIMouseXOffset 0
46 
47 #define DIMouseYOffset 4
48 #define DIMouseZOffset 8
49 
50 #define DIMouseButton0Offset 12
51 
52 #define DIMouseButton1Offset 13
53 
54 #define DIMouseButton2Offset 14
55 
56 #define DIMouseButton3Offset 15
57 
58 
59 /*
60 	Globals
61 */
62 
63 
64 static LPDIRECTINPUT            lpdi;          // DirectInput interface
65 static LPDIRECTINPUTDEVICE      lpdiKeyboard;  // keyboard device interface
66 static LPDIRECTINPUTDEVICE      lpdiMouse;     // mouse device interface
67 static BOOL                     DIKeyboardOkay;  // Is the keyboard acquired?
68 
69 static IDirectInputDevice*     g_pJoystick         = NULL;
70 static IDirectInputDevice2*    g_pJoystickDevice2  = NULL;  // needed to poll joystick
71 
72 	static char bGravePressed = No;
73 		// added 14/1/98 by DHM as a temporary hack to debounce the GRAVE key
74 
75 /*
76 	Externs for input communication
77 */
78 
79 extern HINSTANCE hInst;
80 extern HWND hWndMain;
81 
82 int GotMouse;
83 unsigned int MouseButton;
84 int MouseVelX;
85 int MouseVelY;
86 int MouseVelZ;
87 int MouseX;
88 int MouseY;
89 int MouseZ;
90 
91 extern unsigned char KeyboardInput[];
92 extern unsigned char GotAnyKey;
93 static unsigned char LastGotAnyKey;
94 unsigned char DebouncedGotAnyKey;
95 
96 int GotJoystick;
97 JOYCAPS JoystickCaps;
98 JOYINFOEX JoystickData;
99 int JoystickEnabled;
100 
101 DIJOYSTATE JoystickState;          // DirectInput joystick state
102 
103 
104 /*
105 	8/4/98 DHM: A new array, analagous to KeyboardInput, except it's debounced
106 */
107 extern "C"
108 {
109 	unsigned char DebouncedKeyboardInput[MAX_NUMBER_OF_INPUT_KEYS];
110 }
111 
112 // Implementation of the debounced KeyboardInput
113 // There's probably a more efficient way of getting it direct from DirectInput
114 // but it's getting late and I can't face reading any more Microsoft documentation...
115 static unsigned char LastFramesKeyboardInput[MAX_NUMBER_OF_INPUT_KEYS];
116 
117 
118 extern int NormalFrameTime;
119 
120 static char IngameKeyboardInput[256];
121 extern IngameKeyboardInput_KeyDown(unsigned char key);
122 extern IngameKeyboardInput_KeyUp(unsigned char key);
123 extern IngameKeyboardInput_ClearBuffer(void);
124 
125 /*
126 
127  Create DirectInput via CoCreateInstance
128 
129 */
130 
131 
InitialiseDirectInput(void)132 BOOL InitialiseDirectInput(void)
133 
134 {
135     // try to create di object
136     if (DirectInputCreate(hInst, DIRECTINPUT_VERSION, &lpdi, NULL) != DI_OK)
137       {
138 	   #if debug
139 	   ReleaseDirect3D();
140 	   exit(0x4111);
141 	   #else
142 	   return FALSE;
143 	   #endif
144       }
145 
146     return TRUE;
147 }
148 
149 /*
150 
151 	Release DirectInput object
152 
153 */
154 
155 
ReleaseDirectInput(void)156 void ReleaseDirectInput(void)
157 
158 {
159     if (lpdi!= NULL)
160 	  {
161        lpdi->Release();
162 	   lpdi = NULL;
163 	  }
164 }
165 
166 
167 
168 
169 // see comments below
170 
171 #define UseForegroundKeyboard No
172 
173 GUID     guid = GUID_SysKeyboard;
InitialiseDirectKeyboard()174 BOOL InitialiseDirectKeyboard()
175 
176 {
177     HRESULT  hRes;
178 
179     // try to create keyboard device
180     if (lpdi->CreateDevice(guid, &lpdiKeyboard, NULL) !=DI_OK)
181       {
182 	   #if debug
183 	   ReleaseDirect3D();
184 	   exit(0x4112);
185 	   #else
186 	   return FALSE;
187 	   #endif
188       }
189 
190     // Tell DirectInput that we want to receive data in keyboard format
191     if (lpdiKeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK)
192       {
193 	   #if debug
194 	   ReleaseDirect3D();
195 	   exit(0x4113);
196 	   #else
197 	   return FALSE;
198 	   #endif
199       }
200 
201     // set cooperative level
202 	// this level is the most likely to work across
203 	// multiple hardware targets
204 	// (i.e. this is probably best for a production
205 	// release)
206 	#if UseForegroundKeyboard
207     if (lpdiKeyboard->SetCooperativeLevel(hWndMain,
208                          DISCL_NONEXCLUSIVE | DISCL_FOREGROUND) != DI_OK)
209 	#else
210 	// this level makes alt-tabbing multiple instances in
211 	// SunWindow mode possible without receiving lots
212 	// of false inputs
213     if (lpdiKeyboard->SetCooperativeLevel(hWndMain,
214                          DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK)
215 	#endif
216       {
217 	   #if debug
218 	   ReleaseDirect3D();
219 	   exit(0x4114);
220 	   #else
221 	   return FALSE;
222 	   #endif
223       }
224 
225     // try to acquire the keyboard
226     hRes = lpdiKeyboard->Acquire();
227     if (hRes == DI_OK)
228       {
229        // keyboard was acquired
230        DIKeyboardOkay = TRUE;
231       }
232     else
233       {
234        // keyboard was NOT acquired
235        DIKeyboardOkay = FALSE;
236       }
237 
238     // if we get here, all objects were created successfully
239     return TRUE;
240 }
241 
242 
243 
244 /*
245 
246  Use DirectInput to read keyboard
247 
248  PS: I know this function involves an
249  apparently unnecessary layer of translation
250  between one keyboard array and another one.
251  This is to allow people to swap from a windows
252  procedure keyboard handler to a DirectInput one
253  without having to change their IDemand functions.
254 
255  I can't think of a faster way to do the translation
256  below, but given that it only runs once per frame
257  it shouldn't be too bad.  BUT NOTE THAT IT DOES
258  ONLY RUN ONCE PER FRAME (FROM READUSERINPUT) AND
259  SO YOU MUST HAVE A DECENT FRAME RATE IF KEYS ARE NOT
260  TO BE MISSED.
261 
262  NOTE ALSO THAT IF YOU ARE USING THIS SYSTEM YOU CAN
263  ACCESS THE KEYBOARD ARRAY IN A TIGHT LOOP WHILE CALLING
264  READUSERINPUT BUT -->NOT<-- CHECKWINDOWSMESSAGES (AS REQUIRED
265  FOR THE WINPROC HANDLER).  BUT CHECKFORWINDOWSMESSAGES WON'T DO
266  ANY HARM.
267 */
268 
DirectReadKeyboard(void)269 void DirectReadKeyboard(void)
270 {
271     // Local array for map of all 256 characters on
272 	// keyboard
273 	BYTE DiKeybd[256];
274 	HRESULT hRes;
275 
276     // Get keyboard state
277     hRes = lpdiKeyboard->GetDeviceState(sizeof(DiKeybd), DiKeybd);
278 	if (hRes != DI_OK)
279       {
280 	   if (hRes == DIERR_INPUTLOST)
281 	     {
282 	      // keyboard control lost; try to reacquire
283 	      DIKeyboardOkay = FALSE;
284 	      hRes = lpdiKeyboard->Acquire();
285 	      if (hRes == DI_OK)
286 		    DIKeyboardOkay = TRUE;
287 		 }
288       }
289 
290     // Check for error values on routine exit
291 	if (hRes != DI_OK)
292 	  {
293        // failed to read the keyboard
294 	   #if debug
295        ReleaseDirect3D();
296 	   exit(0x999774);
297 	   #else
298        return;
299 	   #endif
300 	  }
301 
302 	// Take a copy of last frame's inputs:
303 	memcpy((void*)LastFramesKeyboardInput, (void*)KeyboardInput, MAX_NUMBER_OF_INPUT_KEYS);
304 	LastGotAnyKey=GotAnyKey;
305 
306     // Zero current inputs (i.e. set all keys to FALSE,
307 	// or not pressed)
308     memset((void*)KeyboardInput, FALSE, MAX_NUMBER_OF_INPUT_KEYS);
309 	GotAnyKey = FALSE;
310 
311 	#if 1
312 	{
313 		int c;
314 
315 		for (c='a'; c<='z'; c++)
316 		{
317 			if (IngameKeyboardInput[c])
318 			{
319 				KeyboardInput[KEY_A + c - 'a'] = TRUE;
320 				GotAnyKey = TRUE;
321 			}
322 		}
323 		if (IngameKeyboardInput[246])
324 		{
325 			KeyboardInput[KEY_O_UMLAUT] = TRUE;
326 			GotAnyKey = TRUE;
327 		}
328 		if (IngameKeyboardInput[228])
329 		{
330 			KeyboardInput[KEY_A_UMLAUT] = TRUE;
331 			GotAnyKey = TRUE;
332 		}
333 		if (IngameKeyboardInput[252])
334 		{
335 			KeyboardInput[KEY_U_UMLAUT] = TRUE;
336 			GotAnyKey = TRUE;
337 		}
338 		if (IngameKeyboardInput[223])
339 		{
340 			KeyboardInput[KEY_BETA] = TRUE;
341 			GotAnyKey = TRUE;
342 		}
343 		if (IngameKeyboardInput['+'])
344 		{
345 			KeyboardInput[KEY_PLUS] = TRUE;
346 			GotAnyKey = TRUE;
347 		}
348 		if (IngameKeyboardInput['#'])
349 		{
350 			KeyboardInput[KEY_HASH] = TRUE;
351 			GotAnyKey = TRUE;
352 		}
353 		if (IngameKeyboardInput[161])
354 		{
355 			KeyboardInput[KEY_UPSIDEDOWNEXCLAMATION] = TRUE;
356 			GotAnyKey = TRUE;
357 		}
358 		if (IngameKeyboardInput[231])
359 		{
360 			KeyboardInput[KEY_C_CEDILLA] = TRUE;
361 			GotAnyKey = TRUE;
362 		}
363 		if (IngameKeyboardInput[241])
364 		{
365 			KeyboardInput[KEY_N_TILDE] = TRUE;
366 			GotAnyKey = TRUE;
367 		}
368 		if (IngameKeyboardInput[')'])
369 		{
370 			KeyboardInput[KEY_RIGHTBRACKET] = TRUE;
371 			GotAnyKey = TRUE;
372 		}
373 		if (IngameKeyboardInput['*'])
374 		{
375 			KeyboardInput[KEY_ASTERISK] = TRUE;
376 			GotAnyKey = TRUE;
377 		}
378 		if (IngameKeyboardInput['$'])
379 		{
380 			KeyboardInput[KEY_DOLLAR] = TRUE;
381 			GotAnyKey = TRUE;
382 		}
383 		if (IngameKeyboardInput[249])
384 		{
385 			KeyboardInput[KEY_U_GRAVE] = TRUE;
386 			GotAnyKey = TRUE;
387 		}
388 		if (IngameKeyboardInput['!'])
389 		{
390 			KeyboardInput[KEY_EXCLAMATION] = TRUE;
391 			GotAnyKey = TRUE;
392 		}
393 		if (IngameKeyboardInput[':'])
394 		{
395 			KeyboardInput[KEY_COLON] = TRUE;
396 			GotAnyKey = TRUE;
397 		}
398 		if (IngameKeyboardInput[96])
399 		{
400 			KeyboardInput[KEY_DIACRITIC_GRAVE] = TRUE;
401 			GotAnyKey = TRUE;
402 		}
403 		if (IngameKeyboardInput[180])
404 		{
405 			KeyboardInput[KEY_DIACRITIC_ACUTE] = TRUE;
406 			GotAnyKey = TRUE;
407 		}
408 		if (IngameKeyboardInput[94])
409 		{
410 			KeyboardInput[KEY_DIACRITIC_CARET] = TRUE;
411 			GotAnyKey = TRUE;
412 		}
413 		if (IngameKeyboardInput[168])
414 		{
415 			KeyboardInput[KEY_DIACRITIC_UMLAUT] = TRUE;
416 			GotAnyKey = TRUE;
417 		}
418 		if (IngameKeyboardInput['<'])
419 		{
420 			KeyboardInput[KEY_LESSTHAN] = TRUE;
421 			GotAnyKey = TRUE;
422 		}
423 		if (IngameKeyboardInput[176])
424 		{
425 			KeyboardInput[KEY_ORDINAL] = TRUE;
426 			GotAnyKey = TRUE;
427 		}
428 
429 
430 		if (IngameKeyboardInput['['])
431 		{
432 			KeyboardInput[KEY_LBRACKET] = TRUE;
433 			GotAnyKey = TRUE;
434 		}
435 		if (IngameKeyboardInput[']'])
436 		{
437 			KeyboardInput[KEY_RBRACKET] = TRUE;
438 			GotAnyKey = TRUE;
439 		}
440 		if (IngameKeyboardInput[';'])
441 		{
442 			KeyboardInput[KEY_SEMICOLON] = TRUE;
443 			GotAnyKey = TRUE;
444 		}
445 		if (IngameKeyboardInput['\''])
446 		{
447 			KeyboardInput[KEY_APOSTROPHE] = TRUE;
448 			GotAnyKey = TRUE;
449 		}
450 		if (IngameKeyboardInput['\\'])
451 		{
452 			KeyboardInput[KEY_BACKSLASH] = TRUE;
453 			GotAnyKey = TRUE;
454 		}
455 		if (IngameKeyboardInput['/'])
456 		{
457 			KeyboardInput[KEY_SLASH] = TRUE;
458 			GotAnyKey = TRUE;
459 		}
460 		if (IngameKeyboardInput['-'])
461 		{
462 			KeyboardInput[KEY_MINUS] = TRUE;
463 			GotAnyKey = TRUE;
464 		}
465 		if (IngameKeyboardInput['='])
466 		{
467 			KeyboardInput[KEY_EQUALS] = TRUE;
468 			GotAnyKey = TRUE;
469 		}
470 		if (IngameKeyboardInput[','])
471 		{
472 			KeyboardInput[KEY_COMMA] = TRUE;
473 			GotAnyKey = TRUE;
474 		}
475 		if (IngameKeyboardInput['.'])
476 		{
477 			KeyboardInput[KEY_FSTOP] = TRUE;
478 			GotAnyKey = TRUE;
479 		}
480 
481 	}
482 
483 	#endif
484 
485     // Check and set keyboard array
486 	// (test checks only for the moment)
487     if (DiKeybd[DIK_LEFT] & DikOn)
488 	  {
489 	   KeyboardInput[KEY_LEFT] = TRUE;
490 	   GotAnyKey = TRUE;
491 	  }
492 
493     if (DiKeybd[DIK_RIGHT] & DikOn)
494 	  {
495 	   KeyboardInput[KEY_RIGHT] = TRUE;
496 	   GotAnyKey = TRUE;
497 	  }
498 
499     if (DiKeybd[DIK_UP] & DikOn)
500 	  {
501 	   KeyboardInput[KEY_UP] = TRUE;
502 	   GotAnyKey = TRUE;
503 	  }
504 
505     if (DiKeybd[DIK_DOWN] & DikOn)
506 	  {
507 	   KeyboardInput[KEY_DOWN] = TRUE;
508 	   GotAnyKey = TRUE;
509 	  }
510 
511     if (DiKeybd[DIK_ESCAPE] & DikOn)
512 	  {
513 	   KeyboardInput[KEY_ESCAPE] = TRUE;
514 	   GotAnyKey = TRUE;
515 	  }
516 
517     if (DiKeybd[DIK_RETURN] & DikOn)
518 	  {
519 	   KeyboardInput[KEY_CR] = TRUE;
520 	   GotAnyKey = TRUE;
521 	  }
522 
523     if (DiKeybd[DIK_TAB] & DikOn)
524 	  {
525 	   KeyboardInput[KEY_TAB] = TRUE;
526 	   GotAnyKey = TRUE;
527 	  }
528 
529     if (DiKeybd[DIK_F1] & DikOn)
530 	  {
531 	   KeyboardInput[KEY_F1] = TRUE;
532 	   GotAnyKey = TRUE;
533 	  }
534 
535     if (DiKeybd[DIK_F2] & DikOn)
536 	  {
537 	   KeyboardInput[KEY_F2] = TRUE;
538 	   GotAnyKey = TRUE;
539 	  }
540 
541     if (DiKeybd[DIK_F3] & DikOn)
542 	  {
543 	   KeyboardInput[KEY_F3] = TRUE;
544 	   GotAnyKey = TRUE;
545 	  }
546 
547     if (DiKeybd[DIK_F4] & DikOn)
548 	  {
549 	   KeyboardInput[KEY_F4] = TRUE;
550 	   GotAnyKey = TRUE;
551 	  }
552 
553     if (DiKeybd[DIK_F5] & DikOn)
554 	  {
555 	   KeyboardInput[KEY_F5] = TRUE;
556 	   GotAnyKey = TRUE;
557 	  }
558 
559     if (DiKeybd[DIK_F6] & DikOn)
560 	  {
561 	   KeyboardInput[KEY_F6] = TRUE;
562 	   GotAnyKey = TRUE;
563 	  }
564 
565     if (DiKeybd[DIK_F7] & DikOn)
566 	  {
567 	   KeyboardInput[KEY_F7] = TRUE;
568 	   GotAnyKey = TRUE;
569 	  }
570 
571     if (DiKeybd[DIK_F8] & DikOn)
572 	  {
573 	   KeyboardInput[KEY_F8] = TRUE;
574 /* KJL 14:51:38 21/04/98 - F8 does screen shots, and so this is a hack
575 to make F8 not count in a 'press any key' situation */
576 //	   GotAnyKey = TRUE;
577 	  }
578 
579     if (DiKeybd[DIK_F9] & DikOn)
580 	  {
581 	   KeyboardInput[KEY_F9] = TRUE;
582 	   GotAnyKey = TRUE;
583 	  }
584 
585     if (DiKeybd[DIK_F10] & DikOn)
586 	  {
587 	   KeyboardInput[KEY_F10] = TRUE;
588 	   GotAnyKey = TRUE;
589 	  }
590 
591     if (DiKeybd[DIK_F11] & DikOn)
592 	  {
593 	   KeyboardInput[KEY_F11] = TRUE;
594 	   GotAnyKey = TRUE;
595 	  }
596 
597     if (DiKeybd[DIK_F12] & DikOn)
598 	  {
599 	   KeyboardInput[KEY_F12] = TRUE;
600 	   GotAnyKey = TRUE;
601 	  }
602 
603     if (DiKeybd[DIK_INSERT] & DikOn)
604 	  {
605 	   KeyboardInput[KEY_INS] = TRUE;
606 	   GotAnyKey = TRUE;
607 	  }
608 
609     if (DiKeybd[DIK_DELETE] & DikOn)
610 	  {
611 	   KeyboardInput[KEY_DEL] = TRUE;
612 	   GotAnyKey = TRUE;
613 	  }
614 
615     if (DiKeybd[DIK_END] & DikOn)
616 	  {
617 	   KeyboardInput[KEY_END] = TRUE;
618 	   GotAnyKey = TRUE;
619 	  }
620 
621     if (DiKeybd[DIK_HOME] & DikOn)
622 	  {
623 	   KeyboardInput[KEY_HOME] = TRUE;
624 	   GotAnyKey = TRUE;
625 	  }
626 
627     if (DiKeybd[DIK_PRIOR] & DikOn)
628 	  {
629 	   KeyboardInput[KEY_PAGEUP] = TRUE;
630 	   GotAnyKey = TRUE;
631 	  }
632 
633     if (DiKeybd[DIK_NEXT] & DikOn)
634 	  {
635 	   KeyboardInput[KEY_PAGEDOWN] = TRUE;
636 	   GotAnyKey = TRUE;
637 	  }
638 
639     if (DiKeybd[DIK_BACK] & DikOn)
640 	  {
641 	   KeyboardInput[KEY_BACKSPACE] = TRUE;
642 	   GotAnyKey = TRUE;
643 	  }
644 
645     if (DiKeybd[DIK_SPACE] & DikOn)
646 	  {
647 	   KeyboardInput[KEY_SPACE] = TRUE;
648 	   GotAnyKey = TRUE;
649 	  }
650 
651     if (DiKeybd[DIK_LSHIFT] & DikOn)
652 	  {
653 	   KeyboardInput[KEY_LEFTSHIFT] = TRUE;
654 	   GotAnyKey = TRUE;
655 	  }
656 
657     if (DiKeybd[DIK_RSHIFT] & DikOn)
658 	  {
659 	   KeyboardInput[KEY_RIGHTSHIFT] = TRUE;
660 	   GotAnyKey = TRUE;
661 	  }
662 
663     if (DiKeybd[DIK_LCONTROL] & DikOn)
664 	  {
665 	   KeyboardInput[KEY_LEFTCTRL] = TRUE;
666 	   GotAnyKey = TRUE;
667 	  }
668 
669     if (DiKeybd[DIK_RCONTROL] & DikOn)
670 	  {
671 	   KeyboardInput[KEY_RIGHTCTRL] = TRUE;
672 	   GotAnyKey = TRUE;
673 	  }
674 
675     if (DiKeybd[DIK_CAPSLOCK] & DikOn)
676 	  {
677 	   KeyboardInput[KEY_CAPS] = TRUE;
678 	   GotAnyKey = TRUE;
679 	  }
680 
681     if (DiKeybd[DIK_NUMLOCK] & DikOn)
682 	  {
683 	   KeyboardInput[KEY_NUMLOCK] = TRUE;
684 	   GotAnyKey = TRUE;
685 	  }
686 
687     if (DiKeybd[DIK_SCROLL] & DikOn)
688 	  {
689 	   KeyboardInput[KEY_SCROLLOK] = TRUE;
690 	   GotAnyKey = TRUE;
691 	  }
692 
693     if (DiKeybd[DIK_LMENU] & DikOn)
694 	  {
695 	   KeyboardInput[KEY_LEFTALT] = TRUE;
696 	   GotAnyKey = TRUE;
697 	  }
698 
699     if (DiKeybd[DIK_RMENU] & DikOn)
700 	  {
701 	   KeyboardInput[KEY_RIGHTALT] = TRUE;
702 	   GotAnyKey = TRUE;
703 	  }
704 
705     if (DiKeybd[DIK_0] & DikOn)
706 	  {
707 	   KeyboardInput[KEY_0] = TRUE;
708 	   GotAnyKey = TRUE;
709 	  }
710 
711     if (DiKeybd[DIK_1] & DikOn)
712 	  {
713 	   KeyboardInput[KEY_1] = TRUE;
714 	   GotAnyKey = TRUE;
715 	  }
716 
717     if (DiKeybd[DIK_2] & DikOn)
718 	  {
719 	   KeyboardInput[KEY_2] = TRUE;
720 	   GotAnyKey = TRUE;
721 	  }
722 
723     if (DiKeybd[DIK_3] & DikOn)
724 	  {
725 	   KeyboardInput[KEY_3] = TRUE;
726 	   GotAnyKey = TRUE;
727 	  }
728 
729     if (DiKeybd[DIK_4] & DikOn)
730 	  {
731 	   KeyboardInput[KEY_4] = TRUE;
732 	   GotAnyKey = TRUE;
733 	  }
734 
735     if (DiKeybd[DIK_5] & DikOn)
736 	  {
737 	   KeyboardInput[KEY_5] = TRUE;
738 	   GotAnyKey = TRUE;
739 	  }
740 
741     if (DiKeybd[DIK_6] & DikOn)
742 	  {
743 	   KeyboardInput[KEY_6] = TRUE;
744 	   GotAnyKey = TRUE;
745 	  }
746 
747     if (DiKeybd[DIK_7] & DikOn)
748 	  {
749 	   KeyboardInput[KEY_7] = TRUE;
750 	   GotAnyKey = TRUE;
751 	  }
752 
753     if (DiKeybd[DIK_8] & DikOn)
754 	  {
755 	   KeyboardInput[KEY_8] = TRUE;
756 	   GotAnyKey = TRUE;
757 	  }
758 
759     if (DiKeybd[DIK_9] & DikOn)
760 	  {
761 	   KeyboardInput[KEY_9] = TRUE;
762 	   GotAnyKey = TRUE;
763 	  }
764 
765 
766 	/* KJL 16:12:19 05/11/97 - numeric pad follows */
767 	if (DiKeybd[DIK_NUMPAD7] & DikOn)
768 	{
769 		KeyboardInput[KEY_NUMPAD7] = TRUE;
770 		GotAnyKey = TRUE;
771 	}
772 	if (DiKeybd[DIK_NUMPAD8] & DikOn)
773 	{
774 		KeyboardInput[KEY_NUMPAD8] = TRUE;
775 		GotAnyKey = TRUE;
776 	}
777 	if (DiKeybd[DIK_NUMPAD9] & DikOn)
778 	{
779 		KeyboardInput[KEY_NUMPAD9] = TRUE;
780 		GotAnyKey = TRUE;
781 	}
782 	if (DiKeybd[DIK_SUBTRACT] & DikOn)
783 	{
784 		KeyboardInput[KEY_NUMPADSUB] = TRUE;
785 		GotAnyKey = TRUE;
786 	}
787 	if (DiKeybd[DIK_NUMPAD4] & DikOn)
788 	{
789 		KeyboardInput[KEY_NUMPAD4] = TRUE;
790 		GotAnyKey = TRUE;
791 	}
792 	if (DiKeybd[DIK_NUMPAD5] & DikOn)
793 	{
794 		KeyboardInput[KEY_NUMPAD5] = TRUE;
795 		GotAnyKey = TRUE;
796 	}
797 	if (DiKeybd[DIK_NUMPAD6] & DikOn)
798 	{
799 		KeyboardInput[KEY_NUMPAD6] = TRUE;
800 		GotAnyKey = TRUE;
801 	}
802 	if (DiKeybd[DIK_ADD] & DikOn)
803 	{
804 		KeyboardInput[KEY_NUMPADADD] = TRUE;
805 		GotAnyKey = TRUE;
806 	}
807 	if (DiKeybd[DIK_NUMPAD1] & DikOn)
808 	{
809 		KeyboardInput[KEY_NUMPAD1] = TRUE;
810 		GotAnyKey = TRUE;
811 	}
812 	if (DiKeybd[DIK_NUMPAD2] & DikOn)
813 	{
814 		KeyboardInput[KEY_NUMPAD2] = TRUE;
815 		GotAnyKey = TRUE;
816 	}
817 	if (DiKeybd[DIK_NUMPAD3] & DikOn)
818 	{
819 		KeyboardInput[KEY_NUMPAD3] = TRUE;
820 		GotAnyKey = TRUE;
821 	}
822 	if (DiKeybd[DIK_NUMPAD0] & DikOn)
823 	{
824 		KeyboardInput[KEY_NUMPAD0] = TRUE;
825 		GotAnyKey = TRUE;
826 	}
827 	if (DiKeybd[DIK_DECIMAL] & DikOn)
828 	{
829 		KeyboardInput[KEY_NUMPADDEL] = TRUE;
830 		GotAnyKey = TRUE;
831 	}
832 	if (DiKeybd[DIK_NUMPADENTER] & DikOn)
833 	{
834 		KeyboardInput[KEY_NUMPADENTER] = TRUE;
835 		GotAnyKey = TRUE;
836 	}
837 	if (DiKeybd[DIK_DIVIDE] & DikOn)
838 	{
839 		KeyboardInput[KEY_NUMPADDIVIDE] = TRUE;
840 		GotAnyKey = TRUE;
841 	}
842 	if (DiKeybd[DIK_MULTIPLY] & DikOn)
843 	{
844 		KeyboardInput[KEY_NUMPADMULTIPLY] = TRUE;
845 		GotAnyKey = TRUE;
846 	}
847 	if (DiKeybd[DIK_CAPITAL] & DikOn)
848 	{
849 		KeyboardInput[KEY_CAPITAL] = TRUE;
850 		GotAnyKey = TRUE;
851 	}
852 	if (DiKeybd[DIK_LWIN] & DikOn)
853 	{
854 		KeyboardInput[KEY_LWIN] = TRUE;
855 		GotAnyKey = TRUE;
856 	}
857 	if (DiKeybd[DIK_RWIN] & DikOn)
858 	{
859 		KeyboardInput[KEY_RWIN] = TRUE;
860 		GotAnyKey = TRUE;
861 	}
862 	if (DiKeybd[DIK_APPS] & DikOn)
863 	{
864 		KeyboardInput[KEY_APPS] = TRUE;
865 		GotAnyKey = TRUE;
866 	}
867 
868 
869 	#if 0
870 	// Added 14/1/98 by DHM: Process the grave key (known to some as the tilde key)
871 	// Done this way as a bit of a hack to avoid touching PLATFORM.H
872 	// which would force big recompiles
873 	if (DiKeybd[DIK_GRAVE] & DikOn)
874 	{
875 		if ( !bGravePressed )
876 		{
877 			IOFOCUS_Toggle();
878 		}
879 
880 		bGravePressed = Yes;
881 
882 		GotAnyKey = TRUE;
883 	}
884 	else
885 	{
886 		bGravePressed = No;
887 	}
888 	#else
889 	if (DiKeybd[DIK_GRAVE] & DikOn)
890 	{
891 		KeyboardInput[KEY_GRAVE] = TRUE;
892 	}
893 	#endif
894 
895 	/* mouse keys */
896 	if (MouseButton & LeftButton)
897 	{
898 		KeyboardInput[KEY_LMOUSE] = TRUE;
899 		GotAnyKey = TRUE;
900 	}
901 	if (MouseButton & MiddleButton)
902 	{
903 		KeyboardInput[KEY_MMOUSE] = TRUE;
904 		GotAnyKey = TRUE;
905 	}
906 	if (MouseButton & RightButton)
907 	{
908 		KeyboardInput[KEY_RMOUSE] = TRUE;
909 		GotAnyKey = TRUE;
910 	}
911 
912 	/* mouse wheel - read using windows messages */
913 	{
914 		extern signed int MouseWheelStatus;
915 		if (MouseWheelStatus>0)
916 		{
917 			KeyboardInput[KEY_MOUSEWHEELUP] = TRUE;
918 			GotAnyKey = TRUE;
919 		}
920 		else if (MouseWheelStatus<0)
921 		{
922 			KeyboardInput[KEY_MOUSEWHEELDOWN] = TRUE;
923 			GotAnyKey = TRUE;
924 		}
925 	}
926 
927 
928 	/* joystick buttons */
929 	if (GotJoystick)
930 	{
931 		unsigned int n,bit;
932 
933 		for (n=0,bit=1; n<16; n++,bit*=2)
934 		{
935 			if(JoystickData.dwButtons&bit)
936 			{
937 				KeyboardInput[KEY_JOYSTICK_BUTTON_1+n]=TRUE;
938 				GotAnyKey = TRUE;
939 			}
940 		}
941 
942 	}
943 
944 
945 	/* update debounced keys array */
946 	{
947 		for (int i=0;i<MAX_NUMBER_OF_INPUT_KEYS;i++)
948 		{
949 			DebouncedKeyboardInput[i] =
950 			(
951 				KeyboardInput[i] && !LastFramesKeyboardInput[i]
952 			);
953 		}
954 		DebouncedGotAnyKey = GotAnyKey && !LastGotAnyKey;
955 	}
956 
957 
958 }
959 /*
960 
961  Clean up direct keyboard objects
962 
963 */
964 
ReleaseDirectKeyboard(void)965 void ReleaseDirectKeyboard(void)
966 {
967 	if (DIKeyboardOkay)
968       {
969        lpdiKeyboard->Unacquire();
970        DIKeyboardOkay = FALSE;
971       }
972 
973     if (lpdiKeyboard != NULL)
974 	  {
975        lpdiKeyboard->Release();
976 	   lpdiKeyboard = NULL;
977 	  }
978 }
979 
980 
InitialiseDirectMouse()981 BOOL InitialiseDirectMouse()
982 
983 {
984     GUID    guid = GUID_SysMouse;
985 	HRESULT hres;
986 
987 	//MouseButton = 0;
988 
989     // Obtain an interface to the system mouse device.
990     hres = lpdi->CreateDevice(guid, &lpdiMouse, NULL);
991 	if (hres != DI_OK) return FALSE;
992 
993     // Set the data format to "mouse format".
994     hres = lpdiMouse->SetDataFormat(&c_dfDIMouse);
995     if (hres != DI_OK) return FALSE;
996 
997     //  Set the cooperativity level.
998 
999     #if debug
1000 	// This level should allow the debugger to actually work
1001 	// not to mention drop 'n' drag in sub-window mode
1002     hres = lpdiMouse->SetCooperativeLevel(hWndMain,
1003                        DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
1004 	#else
1005 	// this level is the most likely to work across
1006 	// multiple mouse drivers
1007     hres = lpdiMouse->SetCooperativeLevel(hWndMain,
1008                        DISCL_EXCLUSIVE | DISCL_FOREGROUND);
1009 	#endif
1010     if (hres != DI_OK) return FALSE;
1011 
1012     //  Set the buffer size for reading the mouse to
1013 	//  DMouse_BufferSize elements
1014     //  mouse-type should be relative by default, so there
1015 	//  is no need to change axis mode.
1016     DIPROPDWORD dipdw =
1017     {
1018         {
1019             sizeof(DIPROPDWORD),        // diph.dwSize
1020             sizeof(DIPROPHEADER),       // diph.dwHeaderSize
1021             0,                          // diph.dwObj
1022             DIPH_DEVICE,                // diph.dwHow
1023         },
1024         DMouse_BufferSize,              // dwData
1025     };
1026 
1027     hres = lpdiMouse->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph);
1028 
1029     if (hres != DI_OK) return FALSE;
1030 
1031     // try to acquire the mouse
1032     hres = lpdiMouse->Acquire();
1033 
1034 	return TRUE;
1035 }
1036 
DirectReadMouse(void)1037 void DirectReadMouse(void)
1038 {
1039     DIDEVICEOBJECTDATA od[DMouse_RetrieveSize];
1040     DWORD dwElements = DMouse_RetrieveSize;
1041 	HRESULT hres;
1042 	int OldMouseX, OldMouseY, OldMouseZ;
1043 
1044  	GotMouse = No;
1045 	MouseVelX = 0;
1046 	MouseVelY = 0;
1047 	MouseVelZ = 0;
1048 
1049     hres = lpdiMouse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA),&od[0],&dwElements, 0);
1050 
1051 
1052     if (hres == DIERR_INPUTLOST || hres==DIERR_NOTACQUIRED)
1053 	{
1054 		// We had acquisition, but lost it.  Try to reacquire it.
1055 		hres = lpdiMouse->Acquire();
1056 		// No data this time
1057     	return;
1058     }
1059 
1060     // Unable to read data
1061 	if (hres != DI_OK) return;
1062 
1063     // Check for any data being picked up
1064 	GotMouse = Yes;
1065 	if (dwElements == 0) return;
1066 
1067     // Save mouse x and y for velocity determination
1068 	OldMouseX = MouseX;
1069 	OldMouseY = MouseY;
1070 	OldMouseZ = MouseZ;
1071 
1072     // Process all recovered elements and
1073 	// make appropriate modifications to mouse
1074 	// status variables.
1075 
1076     int i;
1077 
1078     for (i=0; i<dwElements; i++)
1079 	{
1080 	// Look at the element to see what happened
1081 
1082 		switch (od[i].dwOfs)
1083 		{
1084 			// DIMOFS_X: Mouse horizontal motion
1085 			case DIMouseXOffset:
1086 			    MouseX += od[i].dwData;
1087 			    break;
1088 
1089 			// DIMOFS_Y: Mouse vertical motion
1090 			case DIMouseYOffset:
1091 			    MouseY += od[i].dwData;
1092 			    break;
1093 
1094 			case DIMouseZOffset:
1095 			    MouseZ += od[i].dwData;
1096 				textprint("z info received %d\n",MouseZ);
1097 			    break;
1098 
1099 			// DIMOFS_BUTTON0: Button 0 pressed or released
1100 			case DIMouseButton0Offset:
1101 			    if (od[i].dwData & DikOn)
1102 			      // Button pressed
1103 				  MouseButton |= LeftButton;
1104 				else
1105 			      // Button released
1106 				  MouseButton &= ~LeftButton;
1107 			    break;
1108 
1109 			// DIMOFS_BUTTON1: Button 1 pressed or released
1110 			case DIMouseButton1Offset:
1111 			  if (od[i].dwData & DikOn)
1112 			      // Button pressed
1113 				  MouseButton |= RightButton;
1114 			  else
1115 			      // Button released
1116 				  MouseButton &= ~RightButton;
1117 			  break;
1118 
1119 			case DIMouseButton2Offset:
1120 			case DIMouseButton3Offset:
1121 			  if (od[i].dwData & DikOn)
1122 			      // Button pressed
1123 				  MouseButton |= MiddleButton;
1124 			  else
1125 			      // Button released
1126 				  MouseButton &= ~MiddleButton;
1127 			  break;
1128 
1129 			default:
1130 			  break;
1131 		}
1132 	}
1133 
1134     MouseVelX = DIV_FIXED(MouseX-OldMouseX,NormalFrameTime);
1135     MouseVelY = DIV_FIXED(MouseY-OldMouseY,NormalFrameTime);
1136     //MouseVelZ = DIV_FIXED(MouseZ-OldMouseZ,NormalFrameTime);
1137 
1138 
1139     #if 0
1140 	textprint("MouseNormalFrameTime %d\n",MouseNormalFrameTime);
1141 	textprint("Got Mouse %d\n", GotMouse);
1142 	textprint("Vel X %d\n", MouseVelX);
1143 	textprint("Vel Y %d\n", MouseVelY);
1144 	#endif
1145 }
1146 
ReleaseDirectMouse(void)1147 void ReleaseDirectMouse(void)
1148 
1149 {
1150     if (lpdiMouse != NULL)
1151 	  {
1152        lpdiMouse->Release();
1153 	   lpdiMouse = NULL;
1154 	  }
1155 }
1156 
1157 
1158 
1159 /*KJL****************************************************************
1160 *                                                                   *
1161 *    JOYSTICK SUPPORT - I've moved all joystick support to here.    *
1162 *                                                                   *
1163 ****************************************************************KJL*/
1164 
1165 
1166 /* KJL 11:32:46 04/30/97 -
1167 
1168 	Okay, this has been changed for the sake of AvP. I know that this
1169 	isn't in AvP\win95\..., but moving this file probably isn't worth
1170 	the trouble.
1171 
1172 	This code is designed to read only one joystick.
1173 
1174 */
1175 
1176 
1177 /*
1178   Decide which (if any) joysticks
1179   exist, access capabilities,
1180   initialise internal variables.
1181 */
1182 #if 1
InitJoysticks(void)1183 void InitJoysticks(void)
1184 {
1185 	JoystickData.dwFlags = (JOY_RETURNALL |	JOY_RETURNCENTERED | JOY_USEDEADZONE);
1186 	JoystickData.dwSize = sizeof(JoystickData);
1187 
1188     GotJoystick = CheckForJoystick();
1189 }
1190 
ReadJoysticks(void)1191 void ReadJoysticks(void)
1192 {
1193 	GotJoystick = ReadJoystick();
1194 }
1195 
ReadJoystick(void)1196 int ReadJoystick(void)
1197 {
1198 	MMRESULT joyreturn;
1199 
1200 	if(!JoystickControlMethods.JoystickEnabled) return No;
1201 
1202 	joyreturn = joyGetPosEx(JOYSTICKID1,&JoystickData);
1203 
1204 	if (joyreturn == JOYERR_NOERROR) return Yes;
1205 
1206 	return No;
1207 }
1208 
CheckForJoystick(void)1209 int CheckForJoystick(void)
1210 {
1211 	MMRESULT joyreturn;
1212 
1213     joyreturn = joyGetDevCaps(JOYSTICKID1,
1214                 &JoystickCaps,
1215                 sizeof(JOYCAPS));
1216 
1217     if (joyreturn == JOYERR_NOERROR) return Yes;
1218 
1219 	return No;
1220 }
1221 #else
1222 // Eleventh hour rewrite of joystick code, to support PantherXL trackerball.
1223 // Typical. KJL, 99/5/1
1224 BOOL CALLBACK EnumJoysticksCallback( LPCDIDEVICEINSTANCE pInst, LPVOID lpvContext );
1225 
1226 
InitJoysticks(void)1227 void InitJoysticks(void)
1228 {
1229 	HRESULT hr;
1230 	GotJoystick = No;
1231 	g_pJoystick = NULL;
1232 
1233 	hr = lpdi->EnumDevices(DIDEVTYPE_JOYSTICK, EnumJoysticksCallback, NULL, DIEDFL_ATTACHEDONLY);
1234     if ( FAILED(hr) ) return;
1235 
1236     hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick );
1237     if ( FAILED(hr) ) return;
1238 
1239     hr = g_pJoystick->SetCooperativeLevel( hWndMain, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
1240     if ( FAILED(hr) ) return;
1241 
1242 	GotJoystick = Yes;
1243 }
1244 
ReadJoysticks(void)1245 void ReadJoysticks(void)
1246 {
1247 
1248 	GotJoystick = No;
1249 
1250 	if(!JoystickControlMethods.JoystickEnabled || g_pJoystick==NULL)
1251 	{
1252 		return;
1253 	}
1254 
1255     HRESULT hr = DIERR_INPUTLOST;
1256 
1257     // if input is lost then acquire and keep trying
1258     while ( DIERR_INPUTLOST == hr )
1259     {
1260         // poll the joystick to read the current state
1261         hr = g_pJoystickDevice2->Poll();
1262         if ( FAILED(hr) ) return;
1263 
1264         // get the input's device state, and put the state in dims
1265         hr = g_pJoystick->GetDeviceState( sizeof(DIJOYSTATE), &JoystickState );
1266 
1267         if ( hr == DIERR_INPUTLOST )
1268         {
1269             // DirectInput is telling us that the input stream has
1270             // been interrupted.  We aren't tracking any state
1271             // between polls, so we don't have any special reset
1272             // that needs to be done.  We just re-acquire and
1273             // try again.
1274             hr = g_pJoystick->Acquire();
1275             if ( FAILED(hr) ) return;
1276         }
1277     }
1278 
1279     if ( FAILED(hr) ) return;
1280 
1281 	GotJoystick = Yes;
1282 	PrintDebuggingText("%d %d\n",JoystickState.rglSlider[0],JoystickState.rglSlider[1]);
1283 
1284 }
1285 //-----------------------------------------------------------------------------
1286 // Function: EnumJoysticksCallback
1287 //
1288 // Description:
1289 //      Called once for each enumerated joystick. If we find one,
1290 //       create a device interface on it so we can play with it.
1291 //
1292 //-----------------------------------------------------------------------------
EnumJoysticksCallback(LPCDIDEVICEINSTANCE pInst,LPVOID lpvContext)1293 BOOL CALLBACK EnumJoysticksCallback( LPCDIDEVICEINSTANCE pInst,
1294                                      LPVOID lpvContext )
1295 {
1296     HRESULT             hr;
1297     LPDIRECTINPUTDEVICE pDevice;
1298 
1299     // obtain an interface to the enumerated force feedback joystick.
1300     hr = lpdi->CreateDevice( pInst->guidInstance, &pDevice, NULL );
1301 
1302     // if it failed, then we can't use this joystick for some
1303     // bizarre reason.  (Maybe the user unplugged it while we
1304     // were in the middle of enumerating it.)  So continue enumerating
1305     if ( FAILED(hr) )
1306         return DIENUM_CONTINUE;
1307 
1308     // we successfully created an IDirectInputDevice.  So stop looking
1309     // for another one.
1310     g_pJoystick = pDevice;
1311 
1312     // query for IDirectInputDevice2 - we need this to poll the joystick
1313     pDevice->QueryInterface( IID_IDirectInputDevice2, (LPVOID *)&g_pJoystickDevice2 );
1314 
1315     return DIENUM_STOP;
1316 }
1317 #endif
1318 
1319 
IngameKeyboardInput_KeyDown(unsigned char key)1320 extern IngameKeyboardInput_KeyDown(unsigned char key)
1321 {
1322 	IngameKeyboardInput[key] = 1;
1323 }
1324 
IngameKeyboardInput_KeyUp(unsigned char key)1325 extern IngameKeyboardInput_KeyUp(unsigned char key)
1326 {
1327 	IngameKeyboardInput[key] = 0;
1328 }
1329 
IngameKeyboardInput_ClearBuffer(void)1330 extern IngameKeyboardInput_ClearBuffer(void)
1331 {
1332 	int i;
1333 
1334 	for (i=0; i<=255; i++)
1335 	{
1336 		IngameKeyboardInput[i] = 0;
1337 	}
1338 }
1339 
1340 // For extern "C"
1341 };
1342 
1343 
1344 
1345