1 /*
2 BStone: A Source port of
3 Blake Stone: Aliens of Gold and Blake Stone: Planet Strike
4 
5 Copyright (c) 1992-2013 Apogee Entertainment, LLC
6 Copyright (c) 2013-2015 Boris I. Bendovsky (bibendovsky@hotmail.com)
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the
20 Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 */
23 
24 
25 //
26 //      ID Engine
27 //      ID_IN.c - Input Manager
28 //      v1.0d1
29 //      By Jason Blochowiak
30 //
31 
32 //
33 //      This module handles dealing with the various input devices
34 //
35 //      Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff),
36 //                              User Mgr (for command line parms)
37 //
38 //      Globals:
39 //              LastScan - The keyboard scan code of the last key pressed
40 //              LastASCII - The ASCII value of the last key pressed
41 //      DEBUG - there are more globals
42 //
43 
44 
45 #include "3d_def.h"
46 
47 
48 #define KeyInt 9 // The keyboard ISR number
49 
50 //
51 // mouse constants
52 //
53 #define MReset 0
54 #define MButtons 3
55 #define MDelta 11
56 
57 #define MouseInt 0x33
58 
59 //
60 // joystick constants
61 //
62 #define JoyScaleMax 32768
63 #define JoyScaleShift 8
64 
65 
66 /*
67 =============================================================================
68 
69                                         GLOBAL VARIABLES
70 
71 =============================================================================
72 */
73 
74 //
75 // configuration variables
76 //
77 bool MousePresent;
78 bool JoysPresent[MaxJoys];
79 bool JoyPadPresent;
80 bool NGinstalled = false;
81 
82 
83 //      Global variables
84 bool JoystickCalibrated; // JAM - added
85 ControlType ControlTypeUsed; // JAM - added
86 KeyboardState Keyboard;
87 bool Paused;
88 char LastASCII;
89 ScanCode LastScan;
90 
91 KeyboardDef KbdDefs = {
92     ScanCode::sc_control,
93     ScanCode::sc_alt,
94     ScanCode::sc_home,
95     ScanCode::sc_up_arrow,
96     ScanCode::sc_page_up,
97     ScanCode::sc_left_arrow,
98     ScanCode::sc_right_arrow,
99     ScanCode::sc_end,
100     ScanCode::sc_down_arrow,
101     ScanCode::sc_page_down
102 }; // KeyboardDef KbdDefs
103 
104 JoystickDef JoyDefs[MaxJoys];
105 ControlType Controls[MaxPlayers];
106 
107 uint32_t MouseDownCount;
108 
109 bool in_use_modern_bindings = default_in_use_modern_bindings;
110 Bindings in_bindings;
111 bool in_is_mouse_grabbed = false;
112 static bool in_last_is_mouse_grabbed = false;
113 
114 /*
115 =============================================================================
116 
117                                         LOCAL VARIABLES
118 
119 =============================================================================
120 */
121 
122 bool IN_Started;
123 
124 static Direction DirTable[] = // Quick lookup for total direction
125 {
126     dir_NorthWest, dir_North, dir_NorthEast,
127     dir_West, dir_None, dir_East,
128     dir_SouthWest, dir_South, dir_SouthEast
129 };
130 
131 
132 //      Internal routines
133 
134 // BBi
in_grab_mouse(bool grab)135 bool in_grab_mouse(
136     bool grab)
137 {
138     if (grab == ::in_is_mouse_grabbed) {
139         return grab;
140     }
141 
142     auto sdl_result = ::SDL_SetRelativeMouseMode(
143         grab ? SDL_TRUE : SDL_FALSE);
144 
145     if (sdl_result == 0) {
146         ::in_is_mouse_grabbed = grab;
147     } else {
148         ::in_is_mouse_grabbed = false;
149     }
150 
151     return ::in_is_mouse_grabbed;
152 }
153 
in_keyboard_map_to_bstone(SDL_Keycode key_code,SDL_Keymod key_mod)154 static ScanCode in_keyboard_map_to_bstone(
155     SDL_Keycode key_code,
156     SDL_Keymod key_mod)
157 {
158     static_cast<void>(key_mod);
159 
160     // FIXME There is no reliable way to check for numlock state in SDL2.
161     bool is_numlock_active = true;
162 
163     switch (key_code) {
164     case SDLK_RETURN:
165     case SDLK_KP_ENTER:
166         return ScanCode::sc_return;
167 
168     case SDLK_ESCAPE:
169         return ScanCode::sc_escape;
170 
171     case SDLK_SPACE:
172     case SDLK_KP_SPACE:
173         return ScanCode::sc_space;
174 
175     case SDLK_MINUS:
176         return ScanCode::sc_minus;
177 
178     case SDLK_EQUALS:
179         return ScanCode::sc_equals;
180 
181     case SDLK_BACKSPACE:
182     case SDLK_KP_BACKSPACE:
183         return ScanCode::sc_backspace;
184 
185     case SDLK_TAB:
186     case SDLK_KP_TAB:
187         return ScanCode::sc_tab;
188 
189     case SDLK_LALT:
190     case SDLK_RALT:
191         return ScanCode::sc_alt;
192 
193     case SDLK_LEFTBRACKET:
194     case SDLK_KP_LEFTBRACE:
195         return ScanCode::sc_left_bracket;
196 
197     case SDLK_RIGHTBRACKET:
198     case SDLK_KP_RIGHTBRACE:
199         return ScanCode::sc_right_bracket;
200 
201     case SDLK_LCTRL:
202     case SDLK_RCTRL:
203         return ScanCode::sc_control;
204 
205     case SDLK_CAPSLOCK:
206         return ScanCode::sc_caps_lock;
207 
208     case SDLK_NUMLOCKCLEAR:
209         return ScanCode::sc_num_lock;
210 
211     case SDLK_SCROLLLOCK:
212         return ScanCode::sc_scroll_lock;
213 
214     case SDLK_LSHIFT:
215         return ScanCode::sc_left_shift;
216 
217     case SDLK_RSHIFT:
218         return ScanCode::sc_right_shift;
219 
220     case SDLK_UP:
221         return ScanCode::sc_up_arrow;
222 
223     case SDLK_KP_8:
224         if (is_numlock_active) {
225             return ScanCode::sc_up_arrow;
226         } else {
227             return ScanCode::sc_8;
228         }
229 
230     case SDLK_DOWN:
231         return ScanCode::sc_down_arrow;
232 
233     case SDLK_KP_2:
234         if (is_numlock_active) {
235             return ScanCode::sc_down_arrow;
236         } else {
237             return ScanCode::sc_2;
238         }
239 
240     case SDLK_LEFT:
241         return ScanCode::sc_left_arrow;
242 
243     case SDLK_KP_4:
244         if (is_numlock_active) {
245             return ScanCode::sc_left_arrow;
246         } else {
247             return ScanCode::sc_4;
248         }
249 
250     case SDLK_RIGHT:
251         return ScanCode::sc_right_arrow;
252 
253     case SDLK_KP_6:
254         if (is_numlock_active) {
255             return ScanCode::sc_right_arrow;
256         } else {
257             return ScanCode::sc_6;
258         }
259 
260     case SDLK_INSERT:
261         return ScanCode::sc_insert;
262 
263     case SDLK_KP_0:
264         if (is_numlock_active) {
265             return ScanCode::sc_insert;
266         } else {
267             return ScanCode::sc_0;
268         }
269 
270     case SDLK_DELETE:
271         return ScanCode::sc_delete;
272 
273     case SDLK_KP_COMMA:
274         if (is_numlock_active) {
275             return ScanCode::sc_delete;
276         } else {
277             return ScanCode::sc_comma;
278         }
279 
280     case SDLK_HOME:
281         return ScanCode::sc_home;
282 
283     case SDLK_KP_7:
284         if (is_numlock_active) {
285             return ScanCode::sc_home;
286         } else {
287             return ScanCode::sc_7;
288         }
289 
290     case SDLK_END:
291         return ScanCode::sc_end;
292 
293     case SDLK_KP_1:
294         if (is_numlock_active) {
295             return ScanCode::sc_end;
296         } else {
297             return ScanCode::sc_1;
298         }
299 
300     case SDLK_PAGEUP:
301         return ScanCode::sc_page_up;
302 
303     case SDLK_KP_9:
304         if (is_numlock_active) {
305             return ScanCode::sc_page_up;
306         } else {
307             return ScanCode::sc_9;
308         }
309 
310     case SDLK_PAGEDOWN:
311         return ScanCode::sc_page_down;
312 
313     case SDLK_KP_3:
314         if (is_numlock_active) {
315             return ScanCode::sc_page_down;
316         } else {
317             return ScanCode::sc_3;
318         }
319 
320     case SDLK_SLASH:
321     case SDLK_KP_DIVIDE:
322         return ScanCode::sc_slash;
323 
324     case SDLK_BACKSLASH:
325         return ScanCode::sc_backslash;
326 
327     case SDLK_SEMICOLON:
328         return ScanCode::sc_semicolon;
329 
330     case SDLK_QUOTE:
331         return ScanCode::sc_quote;
332 
333     case SDLK_PERIOD:
334         return ScanCode::sc_period;
335 
336     case SDLK_F1:
337         return ScanCode::sc_f1;
338 
339     case SDLK_F2:
340         return ScanCode::sc_f2;
341 
342     case SDLK_F3:
343         return ScanCode::sc_f3;
344 
345     case SDLK_F4:
346         return ScanCode::sc_f4;
347 
348     case SDLK_F5:
349         return ScanCode::sc_f5;
350 
351     case SDLK_F6:
352         return ScanCode::sc_f6;
353 
354     case SDLK_F7:
355         return ScanCode::sc_f7;
356 
357     case SDLK_F8:
358         return ScanCode::sc_f8;
359 
360     case SDLK_F9:
361         return ScanCode::sc_f9;
362 
363     case SDLK_F10:
364         return ScanCode::sc_f10;
365 
366     case SDLK_F11:
367         return ScanCode::sc_f11;
368 
369     case SDLK_F12:
370         return ScanCode::sc_f12;
371 
372     case SDLK_PRINTSCREEN:
373         return ScanCode::sc_print_screen;
374 
375     case SDLK_PAUSE:
376         return ScanCode::sc_pause;
377 
378     case SDLK_BACKQUOTE:
379         return ScanCode::sc_back_quote;
380 
381     case SDLK_1:
382         return ScanCode::sc_1;
383 
384     case SDLK_2:
385         return ScanCode::sc_2;
386 
387     case SDLK_3:
388         return ScanCode::sc_3;
389 
390     case SDLK_4:
391         return ScanCode::sc_4;
392 
393     case SDLK_5:
394         return ScanCode::sc_5;
395 
396     case SDLK_6:
397         return ScanCode::sc_6;
398 
399     case SDLK_7:
400         return ScanCode::sc_7;
401 
402     case SDLK_8:
403         return ScanCode::sc_8;
404 
405     case SDLK_9:
406         return ScanCode::sc_9;
407 
408     case SDLK_0:
409         return ScanCode::sc_0;
410 
411     case SDLK_a:
412     case SDLK_KP_A:
413         return ScanCode::sc_a;
414 
415     case SDLK_b:
416     case SDLK_KP_B:
417         return ScanCode::sc_b;
418 
419     case SDLK_c:
420     case SDLK_KP_C:
421         return ScanCode::sc_c;
422 
423     case SDLK_d:
424     case SDLK_KP_D:
425         return ScanCode::sc_d;
426 
427     case SDLK_e:
428     case SDLK_KP_E:
429         return ScanCode::sc_e;
430 
431     case SDLK_f:
432     case SDLK_KP_F:
433         return ScanCode::sc_f;
434 
435     case SDLK_g:
436         return ScanCode::sc_g;
437 
438     case SDLK_h:
439         return ScanCode::sc_h;
440 
441     case SDLK_i:
442         return ScanCode::sc_i;
443 
444     case SDLK_j:
445         return ScanCode::sc_j;
446 
447     case SDLK_k:
448         return ScanCode::sc_k;
449 
450     case SDLK_l:
451         return ScanCode::sc_l;
452 
453     case SDLK_m:
454         return ScanCode::sc_m;
455 
456     case SDLK_n:
457         return ScanCode::sc_n;
458 
459     case SDLK_o:
460         return ScanCode::sc_o;
461 
462     case SDLK_p:
463         return ScanCode::sc_p;
464 
465     case SDLK_q:
466         return ScanCode::sc_q;
467 
468     case SDLK_r:
469         return ScanCode::sc_r;
470 
471     case SDLK_s:
472         return ScanCode::sc_s;
473 
474     case SDLK_t:
475         return ScanCode::sc_t;
476 
477     case SDLK_u:
478         return ScanCode::sc_u;
479 
480     case SDLK_v:
481         return ScanCode::sc_v;
482 
483     case SDLK_w:
484         return ScanCode::sc_w;
485 
486     case SDLK_x:
487         return ScanCode::sc_x;
488 
489     case SDLK_y:
490         return ScanCode::sc_y;
491 
492     case SDLK_z:
493         return ScanCode::sc_z;
494 
495     case SDLK_KP_MINUS:
496         return ScanCode::sc_kp_minus;
497 
498     case SDLK_KP_PLUS:
499         return ScanCode::sc_kp_plus;
500 
501     default:
502         return ScanCode::sc_none;
503     }
504 }
505 
in_keyboard_map_to_char(const SDL_KeyboardEvent & e)506 static char in_keyboard_map_to_char(
507     const SDL_KeyboardEvent& e)
508 {
509     uint16_t flags = e.keysym.mod;
510     bool is_caps = false;
511     bool is_shift = false;
512     SDL_Keycode key_code = e.keysym.sym;
513 
514     if ((flags & (
515              KMOD_LCTRL |
516              KMOD_RCTRL |
517              KMOD_LALT |
518              KMOD_RALT |
519              KMOD_LGUI |
520              KMOD_RGUI |
521              KMOD_MODE)) != 0)
522     {
523         return '\0';
524     }
525 
526     switch (key_code) {
527     case SDLK_ESCAPE:
528     case SDLK_BACKSPACE:
529     case SDLK_TAB:
530     case SDLK_RETURN:
531     case SDLK_SPACE:
532     case SDLK_DELETE:
533         return static_cast<char>(key_code);
534     }
535 
536 
537     is_shift = ((flags & (KMOD_LSHIFT | KMOD_RSHIFT)) != 0);
538 
539     if (allcaps) {
540         is_caps = true;
541     } else {
542         if ((flags & KMOD_CAPS) != 0) {
543             is_caps = !is_caps;
544         }
545 
546         if (is_shift) {
547             is_caps = !is_caps;
548         }
549     }
550 
551     //
552     // Keys which depends on L/R Shift
553     //
554 
555     if (is_shift) {
556         switch (key_code) {
557         case SDLK_1:
558             return '!';
559 
560         case SDLK_2:
561             return '@';
562 
563         case SDLK_3:
564             return '#';
565 
566         case SDLK_4:
567             return '$';
568 
569         case SDLK_5:
570             return '%';
571 
572         case SDLK_6:
573             return '^';
574 
575         case SDLK_7:
576             return '&';
577 
578         case SDLK_8:
579             return '*';
580 
581         case SDLK_9:
582             return '(';
583 
584         case SDLK_0:
585             return ')';
586 
587         case SDLK_MINUS:
588             return '_';
589 
590         case SDLK_EQUALS:
591             return '+';
592 
593         case SDLK_LEFTBRACKET:
594             return '{';
595 
596         case SDLK_RIGHTBRACKET:
597             return '}';
598 
599         case SDLK_SEMICOLON:
600             return ':';
601 
602         case SDLK_QUOTE:
603             return '"';
604 
605         case SDLK_BACKQUOTE:
606             return '~';
607 
608         case SDLK_BACKSLASH:
609             return '|';
610 
611         case SDLK_COMMA:
612             return '<';
613 
614         case SDLK_PERIOD:
615             return '>';
616 
617         case SDLK_SLASH:
618             return '?';
619         }
620     } else {
621         switch (key_code) {
622         case SDLK_1:
623         case SDLK_2:
624         case SDLK_3:
625         case SDLK_4:
626         case SDLK_5:
627         case SDLK_6:
628         case SDLK_7:
629         case SDLK_8:
630         case SDLK_9:
631         case SDLK_0:
632         case SDLK_MINUS:
633         case SDLK_EQUALS:
634         case SDLK_LEFTBRACKET:
635         case SDLK_RIGHTBRACKET:
636         case SDLK_SEMICOLON:
637         case SDLK_QUOTE:
638         case SDLK_BACKQUOTE:
639         case SDLK_BACKSLASH:
640         case SDLK_COMMA:
641         case SDLK_PERIOD:
642         case SDLK_SLASH:
643             return static_cast<char>(key_code);
644         }
645     }
646 
647 
648     //
649     // Keys which depends on Caps Lock & L/R Shift
650     //
651 
652     switch (key_code) {
653     case SDLK_a:
654     case SDLK_b:
655     case SDLK_c:
656     case SDLK_d:
657     case SDLK_e:
658     case SDLK_f:
659     case SDLK_g:
660     case SDLK_h:
661     case SDLK_i:
662     case SDLK_j:
663     case SDLK_k:
664     case SDLK_l:
665     case SDLK_m:
666     case SDLK_n:
667     case SDLK_o:
668     case SDLK_p:
669     case SDLK_q:
670     case SDLK_r:
671     case SDLK_s:
672     case SDLK_t:
673     case SDLK_u:
674     case SDLK_v:
675     case SDLK_w:
676     case SDLK_x:
677     case SDLK_y:
678     case SDLK_z:
679         return is_caps ? static_cast<char>(::SDL_toupper(key_code)) :
680                static_cast<char>(key_code);
681     }
682 
683     return '\0';
684 }
685 
in_handle_keyboard(const SDL_KeyboardEvent & e)686 static void in_handle_keyboard(
687     const SDL_KeyboardEvent& e)
688 {
689     SDL_Keycode key_code = e.keysym.sym;
690     SDL_Keymod key_mod = ::SDL_GetModState();
691     ScanCode key = ::in_keyboard_map_to_bstone(key_code, key_mod);
692 
693     if (key == ScanCode::sc_none) {
694         return;
695     }
696 
697     // Check for special keys
698     if (e.state == SDL_PRESSED) {
699         const auto& grab_mouse_binding = ::in_bindings[e_bi_grab_mouse];
700 
701         if (grab_mouse_binding[0] == key || grab_mouse_binding[1] == key) {
702             ::in_grab_mouse(!::in_is_mouse_grabbed);
703         }
704     }
705 
706 
707     bool is_pressed;
708 
709     switch (key) {
710     case ScanCode::sc_alt:
711         is_pressed = ((key_mod & KMOD_ALT) != 0);
712         break;
713 
714     case ScanCode::sc_control:
715         is_pressed = ((key_mod & KMOD_CTRL) != 0);
716         break;
717 
718     default:
719         is_pressed = (e.state == SDL_PRESSED);
720         break;
721     }
722 
723     Keyboard[key] = is_pressed;
724 
725     if (is_pressed) {
726         LastScan = key;
727 
728         char key_char = ::in_keyboard_map_to_char(e);
729 
730         if (key_char != '\0') {
731             LastASCII = key_char;
732         }
733     }
734 }
735 
in_handle_mouse_buttons(const SDL_MouseButtonEvent & e)736 static void in_handle_mouse_buttons(
737     const SDL_MouseButtonEvent& e)
738 {
739     ScanCode key = ScanCode::sc_none;
740     bool is_pressed = (e.state == SDL_PRESSED);
741 
742     switch (e.button) {
743     case SDL_BUTTON_LEFT:
744         key = ScanCode::sc_mouse_left;
745         break;
746 
747     case SDL_BUTTON_MIDDLE:
748         key = ScanCode::sc_mouse_middle;
749         break;
750 
751     case SDL_BUTTON_RIGHT:
752         key = ScanCode::sc_mouse_right;
753         break;
754 
755     case SDL_BUTTON_X1:
756         key = ScanCode::sc_mouse_x1;
757         break;
758 
759     case SDL_BUTTON_X2:
760         key = ScanCode::sc_mouse_x2;
761         break;
762     }
763 
764     if (key != ScanCode::sc_none) {
765         bool apply_key = true;
766 
767         if (!::in_is_mouse_grabbed) {
768             if (::in_grab_mouse(true)) {
769                 apply_key = false;
770             }
771         }
772 
773         if (apply_key) {
774             Keyboard[key] = is_pressed;
775 
776             if (is_pressed) {
777                 LastScan = key;
778             }
779         }
780     }
781 }
782 
783 static int in_mouse_dx;
784 static int in_mouse_dy;
785 
in_handle_mouse_motion(const SDL_MouseMotionEvent & e)786 static void in_handle_mouse_motion(
787     const SDL_MouseMotionEvent& e)
788 {
789     if (::in_is_mouse_grabbed) {
790         in_mouse_dx += e.xrel;
791         in_mouse_dy += e.yrel;
792     } else {
793         in_mouse_dx = 0;
794         in_mouse_dy = 0;
795     }
796 }
797 
in_handle_mouse(const SDL_Event & e)798 static void in_handle_mouse(
799     const SDL_Event& e)
800 {
801     switch (e.type) {
802     case SDL_MOUSEBUTTONDOWN:
803     case SDL_MOUSEBUTTONUP:
804         ::in_handle_mouse_buttons(e.button);
805         break;
806 
807     case SDL_MOUSEMOTION:
808         ::in_handle_mouse_motion(e.motion);
809         break;
810     }
811 }
812 // BBi
813 
814 ///////////////////////////////////////////////////////////////////////////
815 //
816 //      INL_GetMouseDelta() - Gets the amount that the mouse has moved from the
817 //              mouse driver
818 //
819 ///////////////////////////////////////////////////////////////////////////
INL_GetMouseDelta(int * x,int * y)820 static void INL_GetMouseDelta(
821     int* x,
822     int* y)
823 {
824     *x = ::in_mouse_dx;
825     *y = ::in_mouse_dy;
826 }
827 
828 ///////////////////////////////////////////////////////////////////////////
829 //
830 //      INL_GetMouseButtons() - Gets the status of the mouse buttons from the
831 //              mouse driver
832 //
833 ///////////////////////////////////////////////////////////////////////////
INL_GetMouseButtons()834 static int INL_GetMouseButtons()
835 {
836     ::in_handle_events();
837 
838     int result = 0;
839 
840     if (Keyboard[ScanCode::sc_mouse_left]) {
841         result |= 1;
842     }
843 
844     if (Keyboard[ScanCode::sc_mouse_middle]) {
845         result |= 4;
846     }
847 
848     if (Keyboard[ScanCode::sc_mouse_right]) {
849         result |= 2;
850     }
851 
852     if (Keyboard[ScanCode::sc_mouse_x1]) {
853         result |= 8;
854     }
855 
856     if (Keyboard[ScanCode::sc_mouse_x2]) {
857         result |= 16;
858     }
859 
860     return result;
861 }
862 
863 ///////////////////////////////////////////////////////////////////////////
864 //
865 //      IN_GetJoyAbs() - Reads the absolute position of the specified joystick
866 //
867 ///////////////////////////////////////////////////////////////////////////
IN_GetJoyAbs(uint16_t joy,uint16_t * xp,uint16_t * yp)868 void IN_GetJoyAbs(
869     uint16_t joy,
870     uint16_t* xp,
871     uint16_t* yp)
872 {
873 // FIXME
874 #if 0
875     uint8_t xb, yb;
876     uint8_t xs, ys;
877     uint16_t x, y;
878 
879 // Handle Notebook Gamepad's joystick.
880 //
881     if (NGinstalled) {
882         unsigned ax, bx;
883 
884         joy++;
885 
886         _AL = 0x01;
887         _BX = joy;
888         NGjoy(0x01);
889 
890         ax = _AX;
891         bx = _BX;
892         *xp = ax;
893         *yp = bx;
894 
895         return;
896     }
897 
898 // Handle normal PC joystick.
899 //
900     x = y = 0;
901     xs = joy ? 2 : 0; // Find shift value for x axis
902     xb = 1 << xs; // Use shift value to get x bit mask
903     ys = joy ? 3 : 1; // Do the same for y axis
904     yb = 1 << ys;
905 
906 // Read the absolute joystick values
907     asm             pushf // Save some registers
908     asm             push si
909     asm             push di
910     asm             cli // Make sure an interrupt doesn't screw the timings
911 
912 
913     asm             mov dx, 0x201
914     asm             in al, dx
915     asm             out dx, al // Clear the resistors
916 
917     asm             mov ah, [xb] // Get masks into registers
918     asm             mov ch, [yb]
919 
920     asm             xor             si, si // Clear count registers
921     asm             xor             di, di
922     asm             xor             bh, bh // Clear high byte of bx for later
923 
924     asm             push bp // Don't mess up stack frame
925     asm             mov bp, MaxJoyValue
926 
927 loop:
928     asm             in al, dx // Get bits indicating whether all are finished
929 
930     asm             dec bp // Check bounding register
931     asm             jz done // We have a silly value - abort
932 
933     asm             mov bl, al // Duplicate the bits
934     asm             and bl, ah // Mask off useless bits (in [xb])
935     asm             add si, bx // Possibly increment count register
936     asm             mov cl, bl // Save for testing later
937 
938     asm             mov bl, al
939     asm             and bl, ch // [yb]
940     asm             add di, bx
941 
942     asm             add cl, bl
943     asm             jnz loop // If both bits were 0, drop out
944 
945 done:
946     asm     pop bp
947 
948     asm             mov cl, [xs] // Get the number of bits to shift
949     asm             shr si, cl //  and shift the count that many times
950 
951     asm             mov cl, [ys]
952     asm             shr di, cl
953 
954     asm             mov             [x], si // Store the values into the variables
955     asm             mov             [y], di
956 
957     asm             pop di
958     asm             pop si
959     asm             popf // Restore the registers
960 
961     * xp = x;
962     *yp = y;
963 #endif // 0
964 
965     static_cast<void>(joy);
966 
967     *xp = 0;
968     *yp = 0;
969 }
970 
971 ///////////////////////////////////////////////////////////////////////////
972 //
973 //      INL_GetJoyDelta() - Returns the relative movement of the specified
974 //              joystick (from +/-127)
975 //
976 ///////////////////////////////////////////////////////////////////////////
INL_GetJoyDelta(uint16_t joy,int * dx,int * dy)977 void INL_GetJoyDelta(
978     uint16_t joy,
979     int* dx,
980     int* dy)
981 {
982     uint16_t x, y;
983     JoystickDef* def;
984 
985 // FIXME
986 #if 0
987     static uint32_t lasttime;
988 #endif // 0
989 
990     IN_GetJoyAbs(joy, &x, &y);
991     def = JoyDefs + joy;
992 
993     if (x < def->threshMinX) {
994         if (x < def->joyMinX) {
995             x = def->joyMinX;
996         }
997 
998         x = -(x - def->threshMinX);
999         x *= def->joyMultXL;
1000         x >>= JoyScaleShift;
1001         *dx = (x > 127) ? -127 : -x;
1002     } else if (x > def->threshMaxX) {
1003         if (x > def->joyMaxX) {
1004             x = def->joyMaxX;
1005         }
1006 
1007         x = x - def->threshMaxX;
1008         x *= def->joyMultXH;
1009         x >>= JoyScaleShift;
1010         *dx = (x > 127) ? 127 : x;
1011     } else {
1012         *dx = 0;
1013     }
1014 
1015     if (y < def->threshMinY) {
1016         if (y < def->joyMinY) {
1017             y = def->joyMinY;
1018         }
1019 
1020         y = -(y - def->threshMinY);
1021         y *= def->joyMultYL;
1022         y >>= JoyScaleShift;
1023         *dy = (y > 127) ? -127 : -y;
1024     } else if (y > def->threshMaxY) {
1025         if (y > def->joyMaxY) {
1026             y = def->joyMaxY;
1027         }
1028 
1029         y = y - def->threshMaxY;
1030         y *= def->joyMultYH;
1031         y >>= JoyScaleShift;
1032         *dy = (y > 127) ? 127 : y;
1033     } else {
1034         *dy = 0;
1035     }
1036 
1037 // FIXME
1038 #if 0
1039     lasttime = TimeCount;
1040 #endif // 0
1041 }
1042 
1043 ///////////////////////////////////////////////////////////////////////////
1044 //
1045 //      INL_GetJoyButtons() - Returns the button status of the specified
1046 //              joystick
1047 //
1048 ///////////////////////////////////////////////////////////////////////////
INL_GetJoyButtons(uint16_t joy)1049 static uint16_t INL_GetJoyButtons(
1050     uint16_t joy)
1051 {
1052 // FIXME
1053 #if 0
1054     register uint16_t result;
1055 
1056 // Handle Notebook Gamepad's joystick.
1057 //
1058     if (NGinstalled) {
1059         unsigned ax, bx;
1060 
1061         joy++;
1062 
1063         _AL = 0x01;
1064         _BX = joy;
1065         NGjoy(0x00);
1066 
1067         result = _AL;
1068         result >>= joy ? 6 : 4; // Shift into bits 0-1
1069         result &= 3; // Mask off the useless bits
1070         result ^= 3;
1071 
1072         return result;
1073     }
1074 
1075 // Handle normal PC joystick.
1076 //
1077     result = inportb(0x201); // Get all the joystick buttons
1078     result >>= joy ? 6 : 4; // Shift into bits 0-1
1079     result &= 3; // Mask off the useless bits
1080     result ^= 3;
1081     return result;
1082 #endif // 0
1083 
1084     static_cast<void>(joy);
1085     return 0;
1086 }
1087 
1088 ///////////////////////////////////////////////////////////////////////////
1089 //
1090 //      IN_GetJoyButtonsDB() - Returns the de-bounced button status of the
1091 //              specified joystick
1092 //
1093 ///////////////////////////////////////////////////////////////////////////
IN_GetJoyButtonsDB(uint16_t joy)1094 uint16_t IN_GetJoyButtonsDB(
1095     uint16_t joy)
1096 {
1097     uint32_t lasttime;
1098     uint16_t result1, result2;
1099 
1100     do {
1101         result1 = INL_GetJoyButtons(joy);
1102         lasttime = TimeCount;
1103         while (TimeCount == lasttime) {
1104         }
1105         result2 = INL_GetJoyButtons(joy);
1106     } while (result1 != result2);
1107     return result1;
1108 }
1109 
1110 ///////////////////////////////////////////////////////////////////////////
1111 //
1112 //      INL_StartKbd() - Sets up my keyboard stuff for use
1113 //
1114 ///////////////////////////////////////////////////////////////////////////
INL_StartKbd()1115 void INL_StartKbd()
1116 {
1117     IN_ClearKeysDown();
1118 }
1119 
1120 ///////////////////////////////////////////////////////////////////////////
1121 //
1122 //      INL_ShutKbd() - Restores keyboard control to the BIOS
1123 //
1124 ///////////////////////////////////////////////////////////////////////////
INL_ShutKbd()1125 static void INL_ShutKbd()
1126 {
1127 }
1128 
1129 ///////////////////////////////////////////////////////////////////////////
1130 //
1131 //      INL_StartMouse() - Detects and sets up the mouse
1132 //
1133 ///////////////////////////////////////////////////////////////////////////
INL_StartMouse()1134 bool INL_StartMouse()
1135 {
1136     return true;
1137 }
1138 
1139 // BBi
INL_ShutMouse()1140 static void INL_ShutMouse()
1141 {
1142     // ::SDL_ShowCursor(SDL_TRUE);
1143 }
1144 // BBi
1145 
1146 
1147 //
1148 //      INL_SetJoyScale() - Sets up scaling values for the specified joystick
1149 //
INL_SetJoyScale(uint16_t joy)1150 static void INL_SetJoyScale(
1151     uint16_t joy)
1152 {
1153     JoystickDef* def;
1154 
1155     def = &JoyDefs[joy];
1156     def->joyMultXL = JoyScaleMax / (def->threshMinX - def->joyMinX);
1157     def->joyMultXH = JoyScaleMax / (def->joyMaxX - def->threshMaxX);
1158     def->joyMultYL = JoyScaleMax / (def->threshMinY - def->joyMinY);
1159     def->joyMultYH = JoyScaleMax / (def->joyMaxY - def->threshMaxY);
1160 }
1161 
1162 ///////////////////////////////////////////////////////////////////////////
1163 //
1164 //      IN_SetupJoy() - Sets up thresholding values and calls INL_SetJoyScale()
1165 //              to set up scaling values
1166 //
1167 ///////////////////////////////////////////////////////////////////////////
IN_SetupJoy(uint16_t joy,uint16_t minx,uint16_t maxx,uint16_t miny,uint16_t maxy)1168 void IN_SetupJoy(
1169     uint16_t joy,
1170     uint16_t minx,
1171     uint16_t maxx,
1172     uint16_t miny,
1173     uint16_t maxy)
1174 {
1175     uint16_t d, r;
1176     JoystickDef* def;
1177 
1178     def = &JoyDefs[joy];
1179 
1180     def->joyMinX = minx;
1181     def->joyMaxX = maxx;
1182     r = maxx - minx;
1183     d = r / 5;
1184     def->threshMinX = ((r / 2) - d) + minx;
1185     def->threshMaxX = ((r / 2) + d) + minx;
1186 
1187     def->joyMinY = miny;
1188     def->joyMaxY = maxy;
1189     r = maxy - miny;
1190     d = r / 5;
1191     def->threshMinY = ((r / 2) - d) + miny;
1192     def->threshMaxY = ((r / 2) + d) + miny;
1193 
1194     INL_SetJoyScale(joy);
1195 }
1196 
1197 ///////////////////////////////////////////////////////////////////////////
1198 //
1199 //      INL_ShutJoy() - Cleans up the joystick stuff
1200 //
1201 ///////////////////////////////////////////////////////////////////////////
INL_ShutJoy(uint16_t joy)1202 static void INL_ShutJoy(
1203     uint16_t joy)
1204 {
1205     JoysPresent[joy] = false;
1206 }
1207 
1208 ///////////////////////////////////////////////////////////////////////////
1209 //
1210 //      IN_Shutdown() - Shuts down the Input Mgr
1211 //
1212 ///////////////////////////////////////////////////////////////////////////
IN_Shutdown()1213 void IN_Shutdown()
1214 {
1215     uint16_t i;
1216 
1217     if (!IN_Started) {
1218         return;
1219     }
1220 
1221     for (i = 0; i < MaxJoys; i++) {
1222         INL_ShutJoy(i);
1223     }
1224     INL_ShutKbd();
1225 
1226     // BBi
1227     ::INL_ShutMouse();
1228 
1229     IN_Started = false;
1230 }
1231 
1232 ///////////////////////////////////////////////////////////////////////////
1233 //
1234 //      IN_ClearKeysDown() - Clears the keyboard array
1235 //
1236 ///////////////////////////////////////////////////////////////////////////
IN_ClearKeysDown()1237 void IN_ClearKeysDown()
1238 {
1239     LastScan = ScanCode::sc_none;
1240     LastASCII = key_None;
1241     Keyboard.reset();
1242 }
1243 
1244 // BBi
in_handle_window(const SDL_WindowEvent & e)1245 static void in_handle_window(
1246     const SDL_WindowEvent& e)
1247 {
1248     bool reset_state = false;
1249 
1250     switch (e.event) {
1251     case SDL_WINDOWEVENT_FOCUS_GAINED:
1252         reset_state = true;
1253 
1254         ::vl_minimize_fullscreen_window(false);
1255 
1256         if (::in_last_is_mouse_grabbed) {
1257             ::in_last_is_mouse_grabbed = ::in_grab_mouse(true);
1258         }
1259         ::sd_mute(false);
1260         break;
1261 
1262     case SDL_WINDOWEVENT_FOCUS_LOST:
1263         reset_state = true;
1264         ::in_last_is_mouse_grabbed = ::in_is_mouse_grabbed;
1265         static_cast<void>(::in_grab_mouse(false));
1266         ::sd_mute(true);
1267         ::vl_minimize_fullscreen_window(true);
1268         break;
1269     }
1270 
1271     if (reset_state) {
1272         ::in_reset_state();
1273     }
1274 }
1275 
in_handle_events()1276 void in_handle_events()
1277 {
1278     SDL_Event e;
1279 
1280     ::SDL_PumpEvents();
1281 
1282     while (SDL_PollEvent(&e)) {
1283         switch (e.type) {
1284         case SDL_KEYDOWN:
1285         case SDL_KEYUP:
1286             ::in_handle_keyboard(e.key);
1287             break;
1288 
1289         case SDL_MOUSEBUTTONDOWN:
1290         case SDL_MOUSEBUTTONUP:
1291         case SDL_MOUSEMOTION:
1292             ::in_handle_mouse(e);
1293             break;
1294 
1295         case SDL_WINDOWEVENT:
1296             ::in_handle_window(e.window);
1297             break;
1298 
1299         case SDL_QUIT:
1300             ::Quit();
1301             break;
1302         }
1303     }
1304 }
1305 // BBi
1306 
1307 //
1308 // IN_ReadControl() was modified to allow a single player to use any input
1309 // device at any time without having to physically choose a different
1310 // input device.
1311 //
1312 // PROBLEM: This technique will not work for multi-player games.
1313 //
1314 // Basically, this function should use "player" when in "multi-player"
1315 // mode and ignore "player" when in single player mode.
1316 //
1317 // Anyway, it's not a major problem until we start working with
1318 // with multi-player games.
1319 //
1320 //                                                       - Mike
1321 //
1322 
1323 ///////////////////////////////////////////////////////////////////////////
1324 //
1325 //      IN_ReadControl() - Reads the device associated with the specified
1326 //              player and fills in the control info struct
1327 //
1328 ///////////////////////////////////////////////////////////////////////////
IN_ReadControl(int16_t player_index,ControlInfo * control_info)1329 void IN_ReadControl(
1330     int16_t player_index,
1331     ControlInfo* control_info)
1332 {
1333     static_cast<void>(player_index);
1334 
1335     bool realdelta = false;
1336     uint16_t buttons;
1337     int dx;
1338     int dy;
1339     Motion mx, my;
1340     register KeyboardDef* def;
1341 
1342     // BBi
1343     ::in_handle_events();
1344 
1345     dx = dy = 0;
1346     mx = my = motion_None;
1347     buttons = 0;
1348 
1349     {
1350 
1351 // JAM begin
1352         ControlTypeUsed = ctrl_None;
1353 
1354         // Handle keyboard input...
1355         //
1356         if (ControlTypeUsed == ctrl_None) {
1357             def = &KbdDefs;
1358 
1359             if (Keyboard[def->upleft]) {
1360                 mx = motion_Left, my = motion_Up;
1361             } else if (Keyboard[def->upright]) {
1362                 mx = motion_Right, my = motion_Up;
1363             } else if (Keyboard[def->downleft]) {
1364                 mx = motion_Left, my = motion_Down;
1365             } else if (Keyboard[def->downright]) {
1366                 mx = motion_Right, my = motion_Down;
1367             }
1368 
1369             if (Keyboard[def->up]) {
1370                 my = motion_Up;
1371             } else if (Keyboard[def->down]) {
1372                 my = motion_Down;
1373             }
1374 
1375             if (Keyboard[def->left]) {
1376                 mx = motion_Left;
1377             } else if (Keyboard[def->right]) {
1378                 mx = motion_Right;
1379             }
1380 
1381             if (Keyboard[def->button0]) {
1382                 buttons += 1 << 0;
1383             }
1384             if (Keyboard[def->button1]) {
1385                 buttons += 1 << 1;
1386             }
1387             realdelta = false;
1388             if (mx || my || buttons) {
1389                 ControlTypeUsed = ctrl_Keyboard;
1390             }
1391         }
1392 
1393         // Handle mouse input...
1394         //
1395         if (MousePresent && (ControlTypeUsed == ctrl_None)) {
1396             INL_GetMouseDelta(&dx, &dy);
1397             buttons = static_cast<uint16_t>(INL_GetMouseButtons());
1398             realdelta = true;
1399             if (dx || dy || buttons) {
1400                 ControlTypeUsed = ctrl_Mouse;
1401             }
1402         }
1403 
1404         // Handle joystick input...
1405         //
1406         if (JoystickCalibrated && (ControlTypeUsed == ctrl_None)) {
1407             INL_GetJoyDelta(ctrl_Joystick1 - ctrl_Joystick, &dx, &dy);
1408             buttons = INL_GetJoyButtons(ctrl_Joystick1 - ctrl_Joystick);
1409             realdelta = true;
1410             if (dx || dy || buttons) {
1411                 ControlTypeUsed = ctrl_Joystick;
1412             }
1413         }
1414 
1415 // JAM end
1416     }
1417 
1418     if (realdelta) {
1419         mx = (dx < 0) ? motion_Left : ((dx > 0) ? motion_Right : motion_None);
1420         my = (dy < 0) ? motion_Up : ((dy > 0) ? motion_Down : motion_None);
1421     } else {
1422         dx = mx * 127;
1423         dy = my * 127;
1424     }
1425 
1426     control_info->x = dx;
1427     control_info->xaxis = mx;
1428     control_info->y = dy;
1429     control_info->yaxis = my;
1430     control_info->button0 = buttons & (1 << 0);
1431     control_info->button1 = buttons & (1 << 1);
1432     control_info->button2 = buttons & (1 << 2);
1433     control_info->button3 = buttons & (1 << 3);
1434     control_info->dir = DirTable[((my + 1) * 3) + (mx + 1)];
1435 }
1436 
1437 ///////////////////////////////////////////////////////////////////////////
1438 //
1439 //      IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and
1440 //              returns the ASCII value
1441 //
1442 ///////////////////////////////////////////////////////////////////////////
IN_WaitForASCII()1443 char IN_WaitForASCII()
1444 {
1445     char result;
1446 
1447     while ((result = LastASCII) == '\0') {
1448         ::in_handle_events();
1449     }
1450     LastASCII = '\0';
1451     return result;
1452 }
1453 
1454 ///////////////////////////////////////////////////////////////////////////
1455 //
1456 //      IN_Ack() - waits for a button or key press.  If a button is down, upon
1457 // calling, it must be released for it to be recognized
1458 //
1459 ///////////////////////////////////////////////////////////////////////////
1460 
1461 bool btnstate[8];
1462 
IN_StartAck()1463 void IN_StartAck()
1464 {
1465     uint16_t i, buttons;
1466 
1467 //
1468 // get initial state of everything
1469 //
1470     IN_ClearKeysDown();
1471     memset(btnstate, 0, sizeof(btnstate));
1472 
1473     buttons = IN_JoyButtons() << 4;
1474     if (MousePresent) {
1475         buttons |= IN_MouseButtons();
1476     }
1477 
1478     for (i = 0; i < 8; i++, buttons >>= 1) {
1479         if (buttons & 1) {
1480             btnstate[i] = true;
1481         }
1482     }
1483 }
1484 
IN_CheckAck()1485 bool IN_CheckAck()
1486 {
1487     uint16_t i, buttons;
1488 
1489     in_handle_events();
1490 //
1491 // see if something has been pressed
1492 //
1493     if (LastScan != ScanCode::sc_none) {
1494         return true;
1495     }
1496 
1497     buttons = IN_JoyButtons() << 4;
1498     if (MousePresent) {
1499         buttons |= IN_MouseButtons();
1500     }
1501 
1502     for (i = 0; i < 8; i++, buttons >>= 1) {
1503         if (buttons & 1) {
1504             if (!btnstate[i]) {
1505                 return true;
1506             }
1507         } else {
1508             btnstate[i] = false;
1509         }
1510     }
1511 
1512     return false;
1513 }
1514 
IN_Ack()1515 void IN_Ack()
1516 {
1517     IN_StartAck();
1518 
1519     while (!IN_CheckAck()) {
1520     }
1521 }
1522 
1523 ///////////////////////////////////////////////////////////////////////////
1524 //
1525 //      IN_UserInput() - Waits for the specified delay time (in ticks) or the
1526 //              user pressing a key or a mouse button. If the clear flag is set, it
1527 //              then either clears the key or waits for the user to let the mouse
1528 //              button up.
1529 //
1530 ///////////////////////////////////////////////////////////////////////////
IN_UserInput(uint32_t delay)1531 bool IN_UserInput(
1532     uint32_t delay)
1533 {
1534     uint32_t lasttime;
1535 
1536     lasttime = TimeCount;
1537     IN_StartAck();
1538     do {
1539         VL_WaitVBL(1);
1540         if (IN_CheckAck()) {
1541             return true;
1542         }
1543     } while (TimeCount - lasttime < delay);
1544     return false;
1545 }
1546 
IN_MouseButtons()1547 uint8_t IN_MouseButtons()
1548 {
1549     return static_cast<uint8_t>(::INL_GetMouseButtons());
1550 }
1551 
IN_JoyButtons()1552 uint8_t IN_JoyButtons()
1553 {
1554 // FIXME
1555 #if 0
1556     unsigned joybits;
1557 
1558     joybits = inportb(0x201); // Get all the joystick buttons
1559     joybits >>= 4; // only the high bits are useful
1560     joybits ^= 15; // return with 1=pressed
1561 
1562     return joybits;
1563 #else
1564     return 0;
1565 #endif // 0
1566 }
1567 
INL_StartJoy(uint16_t joy)1568 bool INL_StartJoy(
1569     uint16_t joy)
1570 {
1571     uint16_t x;
1572     uint16_t y;
1573 
1574     IN_GetJoyAbs(joy, &x, &y);
1575 
1576     if ((x == 0 || x > MaxJoyValue - 10) ||
1577         (y == 0 || y > MaxJoyValue - 10))
1578     {
1579         return false;
1580     } else {
1581         IN_SetupJoy(joy, 0, x * 2, 0, y * 2);
1582         return true;
1583     }
1584 }
1585 
IN_Startup()1586 void IN_Startup()
1587 {
1588     if (IN_Started) {
1589         return;
1590     }
1591 
1592     INL_StartKbd();
1593     MousePresent = INL_StartMouse();
1594 
1595     for (int i = 0; i < MaxJoys; ++i) {
1596         JoysPresent[i] = INL_StartJoy(static_cast<uint16_t>(i));
1597     }
1598 
1599     ::in_set_default_bindings();
1600 
1601     IN_Started = true;
1602 }
1603 
1604 // BBi
in_get_mouse_deltas(int & dx,int & dy)1605 void in_get_mouse_deltas(
1606     int& dx,
1607     int& dy)
1608 {
1609     ::INL_GetMouseDelta(&dx, &dy);
1610 }
1611 
in_clear_mouse_deltas()1612 void in_clear_mouse_deltas()
1613 {
1614     ::in_mouse_dx = 0;
1615     ::in_mouse_dy = 0;
1616 }
1617 
in_set_default_bindings()1618 void in_set_default_bindings()
1619 {
1620     for (int b = 0; b < k_max_bindings; ++b) {
1621         for (int k = 0; k < k_max_binding_keys; ++k) {
1622             in_bindings[b][k] = ScanCode::sc_none;
1623         }
1624     }
1625 
1626     in_bindings[e_bi_forward][0] = ScanCode::sc_w;
1627     in_bindings[e_bi_backward][0] = ScanCode::sc_s;
1628     in_bindings[e_bi_left][0] = ScanCode::sc_left_arrow;
1629     in_bindings[e_bi_right][0] = ScanCode::sc_right_arrow;
1630     in_bindings[e_bi_strafe][0] = ScanCode::sc_alt;
1631     in_bindings[e_bi_strafe_left][0] = ScanCode::sc_a;
1632     in_bindings[e_bi_strafe_right][0] = ScanCode::sc_d;
1633     in_bindings[e_bi_quick_left][0] = ScanCode::sc_q;
1634     in_bindings[e_bi_quick_right][0] = ScanCode::sc_e;
1635     in_bindings[e_bi_turn_around][0] = ScanCode::sc_r;
1636     in_bindings[e_bi_run][0] = ScanCode::sc_left_shift;
1637 
1638     in_bindings[e_bi_attack][0] = ScanCode::sc_control;
1639     in_bindings[e_bi_attack][1] = ScanCode::sc_mouse_left;
1640     in_bindings[e_bi_weapon_1][0] = ScanCode::sc_1;
1641     in_bindings[e_bi_weapon_2][0] = ScanCode::sc_2;
1642     in_bindings[e_bi_weapon_3][0] = ScanCode::sc_3;
1643     in_bindings[e_bi_weapon_4][0] = ScanCode::sc_4;
1644     in_bindings[e_bi_weapon_5][0] = ScanCode::sc_5;
1645     in_bindings[e_bi_weapon_6][0] = ScanCode::sc_6;
1646     in_bindings[e_bi_weapon_7][0] = ScanCode::sc_back_quote;
1647 
1648     in_bindings[e_bi_use][0] = ScanCode::sc_space;
1649     in_bindings[e_bi_use][1] = ScanCode::sc_mouse_right;
1650 
1651     in_bindings[e_bi_stats][0] = ScanCode::sc_tab;
1652     in_bindings[e_bi_radar_magnify][0] = ScanCode::sc_equals;
1653     in_bindings[e_bi_radar_minify][0] = ScanCode::sc_minus;
1654 
1655     in_bindings[e_bi_help][0] = ScanCode::sc_f1;
1656     in_bindings[e_bi_save][0] = ScanCode::sc_f2;
1657     in_bindings[e_bi_load][0] = ScanCode::sc_f3;
1658     in_bindings[e_bi_sound][0] = ScanCode::sc_f4;
1659     in_bindings[e_bi_controls][0] = ScanCode::sc_f6;
1660     in_bindings[e_bi_end_game][0] = ScanCode::sc_f7;
1661     in_bindings[e_bi_quick_save][0] = ScanCode::sc_f8;
1662     in_bindings[e_bi_quick_load][0] = ScanCode::sc_f9;
1663     in_bindings[e_bi_quick_exit][0] = ScanCode::sc_f10;
1664 
1665     in_bindings[e_bi_attack_info][0] = ScanCode::sc_i;
1666     in_bindings[e_bi_lightning][0] = ScanCode::sc_l;
1667     in_bindings[e_bi_sfx][0] = ScanCode::sc_x;
1668     in_bindings[e_bi_music][0] = ScanCode::sc_m;
1669     in_bindings[e_bi_ceiling][0] = ScanCode::sc_c;
1670     in_bindings[e_bi_flooring][0] = ScanCode::sc_f;
1671     in_bindings[e_bi_heart_beat][0] = ScanCode::sc_h;
1672 
1673     in_bindings[e_bi_pause][0] = ScanCode::sc_p;
1674     in_bindings[e_bi_pause][1] = ScanCode::sc_pause;
1675 
1676     in_bindings[e_bi_grab_mouse][0] = ScanCode::sc_u;
1677 }
1678 
in_is_binding_pressed(BindingId binding_id)1679 bool in_is_binding_pressed(
1680     BindingId binding_id)
1681 {
1682     if (in_use_modern_bindings) {
1683         const Binding& binding = in_bindings[binding_id];
1684 
1685         return (binding[0] != ScanCode::sc_none && Keyboard[binding[0]]) ||
1686                (binding[1] != ScanCode::sc_none && Keyboard[binding[1]]);
1687     } else {
1688         switch (binding_id) {
1689         case e_bi_forward:
1690             return Keyboard[dirscan[di_north]];
1691 
1692         case e_bi_backward:
1693             return Keyboard[dirscan[di_south]];
1694 
1695         case e_bi_left:
1696             return Keyboard[dirscan[di_west]];
1697 
1698         case e_bi_right:
1699             return Keyboard[dirscan[di_east]];
1700 
1701         case e_bi_strafe:
1702             return Keyboard[buttonscan[bt_strafe]];
1703 
1704         case e_bi_quick_left:
1705             return Keyboard[ScanCode::sc_q];
1706 
1707         case e_bi_quick_right:
1708             return Keyboard[ScanCode::sc_e];
1709 
1710         case e_bi_turn_around:
1711             return Keyboard[ScanCode::sc_w] || Keyboard[ScanCode::sc_return];
1712 
1713         case e_bi_run:
1714             return Keyboard[buttonscan[bt_run]];
1715 
1716         case e_bi_attack:
1717             return Keyboard[buttonscan[bt_attack]];
1718 
1719         case e_bi_weapon_1:
1720             return Keyboard[ScanCode::sc_1];
1721 
1722         case e_bi_weapon_2:
1723             return Keyboard[ScanCode::sc_2];
1724 
1725         case e_bi_weapon_3:
1726             return Keyboard[ScanCode::sc_3];
1727 
1728         case e_bi_weapon_4:
1729             return Keyboard[ScanCode::sc_4];
1730 
1731         case e_bi_weapon_5:
1732             return Keyboard[ScanCode::sc_5];
1733 
1734         case e_bi_weapon_6:
1735             return Keyboard[ScanCode::sc_6];
1736 
1737         case e_bi_weapon_7:
1738             if (!::is_ps()) {
1739                 return false;
1740             }
1741 
1742             return Keyboard[ScanCode::sc_back_quote];
1743 
1744         case e_bi_use:
1745             return Keyboard[ScanCode::sc_space];
1746 
1747         case e_bi_stats:
1748             return Keyboard[ScanCode::sc_tab];
1749 
1750         case e_bi_radar_magnify:
1751             if (!::is_ps()) {
1752                 return false;
1753             }
1754 
1755             return Keyboard[ScanCode::sc_equals];
1756 
1757         case e_bi_radar_minify:
1758             if (!::is_ps()) {
1759                 return false;
1760             }
1761 
1762             return Keyboard[ScanCode::sc_minus];
1763 
1764         case e_bi_help:
1765             return Keyboard[ScanCode::sc_f1];
1766 
1767         case e_bi_save:
1768             return Keyboard[ScanCode::sc_f2];
1769 
1770         case e_bi_load:
1771             return Keyboard[ScanCode::sc_f3];
1772 
1773         case e_bi_sound:
1774             return Keyboard[ScanCode::sc_f4];
1775 
1776         case e_bi_controls:
1777             return Keyboard[ScanCode::sc_f6];
1778 
1779         case e_bi_end_game:
1780             return Keyboard[ScanCode::sc_f7];
1781 
1782         case e_bi_quick_save:
1783             return Keyboard[ScanCode::sc_f8];
1784 
1785         case e_bi_quick_load:
1786             return Keyboard[ScanCode::sc_f9];
1787 
1788         case e_bi_quick_exit:
1789             return Keyboard[ScanCode::sc_f10];
1790 
1791         case e_bi_attack_info:
1792             return Keyboard[ScanCode::sc_i];
1793 
1794         case e_bi_lightning:
1795             return Keyboard[ScanCode::sc_l];
1796 
1797         case e_bi_sfx:
1798             return Keyboard[ScanCode::sc_s];
1799 
1800         case e_bi_music:
1801             return Keyboard[ScanCode::sc_m];
1802 
1803         case e_bi_ceiling:
1804             return Keyboard[ScanCode::sc_c];
1805 
1806         case e_bi_flooring:
1807             return Keyboard[ScanCode::sc_f];
1808 
1809         case e_bi_heart_beat:
1810             if (!::is_aog()) {
1811                 return false;
1812             }
1813 
1814             return Keyboard[ScanCode::sc_h];
1815 
1816         case e_bi_pause:
1817             return Keyboard[ScanCode::sc_p] || Keyboard[ScanCode::sc_pause];
1818 
1819         default:
1820             return false;
1821         }
1822     }
1823 }
1824 
in_reset_binding_state(BindingId binding_id)1825 void in_reset_binding_state(
1826     BindingId binding_id)
1827 {
1828     if (in_use_modern_bindings) {
1829         const auto& binding = in_bindings[binding_id];
1830 
1831         if (binding[0] != ScanCode::sc_none) {
1832             Keyboard[binding[0]] = false;
1833         }
1834 
1835         if (binding[1] != ScanCode::sc_none) {
1836             Keyboard[binding[1]] = false;
1837         }
1838     } else {
1839         switch (binding_id) {
1840         case e_bi_forward:
1841             Keyboard[dirscan[di_north]] = false;
1842             break;
1843 
1844         case e_bi_backward:
1845             Keyboard[dirscan[di_south]] = false;
1846             break;
1847 
1848         case e_bi_left:
1849             Keyboard[dirscan[di_west]] = false;
1850             break;
1851 
1852         case e_bi_right:
1853             Keyboard[dirscan[di_east]] = false;
1854             break;
1855 
1856         case e_bi_strafe:
1857             Keyboard[buttonscan[bt_strafe]] = false;
1858             break;
1859 
1860         case e_bi_quick_left:
1861             Keyboard[ScanCode::sc_q] = false;
1862             break;
1863 
1864         case e_bi_quick_right:
1865             Keyboard[ScanCode::sc_e] = false;
1866             break;
1867 
1868         case e_bi_turn_around:
1869             Keyboard[ScanCode::sc_w] = false;
1870             Keyboard[ScanCode::sc_return] = false;
1871             break;
1872 
1873         case e_bi_run:
1874             Keyboard[buttonscan[bt_run]] = false;
1875             break;
1876 
1877         case e_bi_attack:
1878             Keyboard[buttonscan[bt_attack]] = false;
1879             break;
1880 
1881         case e_bi_weapon_1:
1882             Keyboard[ScanCode::sc_1] = false;
1883             break;
1884 
1885         case e_bi_weapon_2:
1886             Keyboard[ScanCode::sc_2] = false;
1887             break;
1888 
1889         case e_bi_weapon_3:
1890             Keyboard[ScanCode::sc_3] = false;
1891             break;
1892 
1893         case e_bi_weapon_4:
1894             Keyboard[ScanCode::sc_4] = false;
1895             break;
1896 
1897         case e_bi_weapon_5:
1898             Keyboard[ScanCode::sc_5] = false;
1899             break;
1900 
1901         case e_bi_weapon_6:
1902             Keyboard[ScanCode::sc_6] = false;
1903             break;
1904 
1905         case e_bi_weapon_7:
1906             if (::is_ps()) {
1907                 Keyboard[ScanCode::sc_back_quote] = false;
1908             }
1909             break;
1910 
1911         case e_bi_use:
1912             Keyboard[ScanCode::sc_space] = false;
1913             break;
1914 
1915         case e_bi_stats:
1916             Keyboard[ScanCode::sc_tab] = false;
1917             break;
1918 
1919         case e_bi_radar_magnify:
1920             if (::is_ps()) {
1921                 Keyboard[ScanCode::sc_equals] = false;
1922             }
1923             break;
1924 
1925         case e_bi_radar_minify:
1926             if (::is_ps()) {
1927                 Keyboard[ScanCode::sc_minus] = false;
1928             }
1929             break;
1930 
1931         case e_bi_help:
1932             Keyboard[ScanCode::sc_f1] = false;
1933             break;
1934 
1935         case e_bi_save:
1936             Keyboard[ScanCode::sc_f2] = false;
1937             break;
1938 
1939         case e_bi_load:
1940             Keyboard[ScanCode::sc_f3] = false;
1941             break;
1942 
1943         case e_bi_sound:
1944             Keyboard[ScanCode::sc_f4] = false;
1945             break;
1946 
1947         case e_bi_controls:
1948             Keyboard[ScanCode::sc_f6] = false;
1949             break;
1950 
1951         case e_bi_end_game:
1952             Keyboard[ScanCode::sc_f7] = false;
1953             break;
1954 
1955         case e_bi_quick_save:
1956             Keyboard[ScanCode::sc_f8] = false;
1957             break;
1958 
1959         case e_bi_quick_load:
1960             Keyboard[ScanCode::sc_f9] = false;
1961             break;
1962 
1963         case e_bi_quick_exit:
1964             Keyboard[ScanCode::sc_f10] = false;
1965             break;
1966 
1967         case e_bi_attack_info:
1968             Keyboard[ScanCode::sc_i] = false;
1969             break;
1970 
1971         case e_bi_lightning:
1972             Keyboard[ScanCode::sc_l] = false;
1973             break;
1974 
1975         case e_bi_sfx:
1976             Keyboard[ScanCode::sc_s] = false;
1977             break;
1978 
1979         case e_bi_music:
1980             Keyboard[ScanCode::sc_m] = false;
1981             break;
1982 
1983         case e_bi_ceiling:
1984             Keyboard[ScanCode::sc_c] = false;
1985             break;
1986 
1987         case e_bi_flooring:
1988             Keyboard[ScanCode::sc_f] = false;
1989             break;
1990 
1991         case e_bi_pause:
1992             Keyboard[ScanCode::sc_p] = false;
1993             Keyboard[ScanCode::sc_pause] = false;
1994             break;
1995 
1996         case e_bi_heart_beat:
1997             if (::is_aog()) {
1998                 Keyboard[ScanCode::sc_h] = false;
1999             }
2000             break;
2001 
2002         default:
2003             break;
2004         }
2005     }
2006 }
2007 
in_reset_state()2008 void in_reset_state()
2009 {
2010     ::LastASCII = '\0';
2011     ::LastScan = ScanCode::sc_none;
2012 
2013     ::Keyboard.reset();
2014 
2015     for (int i = 0; i < NUMBUTTONS; ++i) {
2016         ::buttonstate[i] = false;
2017         ::buttonheld[i] = false;
2018     }
2019 
2020     ::in_clear_mouse_deltas();
2021 }
2022 // BBi
2023