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