]> 4ch.mooo.com Git - 16.git/blob - src/lib/16_in.c
e7ed19edafbe81620eadfbd47dac839280a916a9
[16.git] / src / lib / 16_in.c
1 /* Project 16 Source Code~\r
2  * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
3  *\r
4  * This file is part of Project 16.\r
5  *\r
6  * Project 16 is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 3 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Project 16 is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
18  * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
19  * Fifth Floor, Boston, MA 02110-1301 USA.\r
20  *\r
21  */\r
22 //\r
23 //      ID Engine\r
24 //      ID_IN.c - Input Manager\r
25 //      v1.0d1w\r
26 //      By Jason Blochowiak\r
27 //      Open Watcom port by sparky4\r
28 //\r
29 \r
30 //\r
31 //      This module handles dealing with the various input devices\r
32 //\r
33 //      Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff),\r
34 //                              User Mgr (for command line parms)\r
35 //\r
36 //      Globals:\r
37 //              LastScan - The keyboard scan code of the last key pressed\r
38 //              LastASCII - The ASCII value of the last key pressed\r
39 //      DEBUG - there are more globals\r
40 //\r
41 \r
42 #include "src/lib/16_in.h"\r
43 #pragma hdrstop\r
44 \r
45 static word far* clockw= (word far*) 0x046C; /* 18.2hz clock */\r
46 \r
47 /*\r
48 =============================================================================\r
49 \r
50                                         GLOBAL VARIABLES\r
51 \r
52 =============================================================================\r
53 */\r
54 struct inconfig\r
55 {\r
56         boolean         MousePresent;\r
57         boolean         JoysPresent[MaxJoys];\r
58         boolean         Keyboard[NumCodes];\r
59         boolean         Paused;\r
60         char            LastASCII;\r
61         ScanCode        LastScan;\r
62 \r
63         KeyboardDef     KbdDefs[MaxKbds];\r
64         JoystickDef     JoyDefs[MaxJoys];\r
65 } inpu;\r
66 \r
67 //inpu.KbdDefs = {0x1d,0x38,/*0x47,*/0x48,/*0x49,*/0x4b,0x4d,/*0x4f,*/0x50/*,0x51*/};\r
68 \r
69 /*\r
70 =============================================================================\r
71 \r
72                                         LOCAL VARIABLES\r
73 \r
74 =============================================================================\r
75 */\r
76 \r
77 #ifdef __cplusplus              /* Function must be declared C style */\r
78 extern "C" {\r
79 #endif\r
80 \r
81 static struct instat {\r
82         boolean         IN_Started;\r
83         boolean         CapsLock;\r
84         ScanCode        CurCode,LastCode;\r
85 } inst;\r
86 \r
87 static  byte        far ASCIINames[] =          // Unshifted ASCII for scan codes\r
88                                         {\r
89 //       0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F\r
90         0  ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8  ,9  ,        // 0\r
91         'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0  ,'a','s',        // 1\r
92         'd','f','g','h','j','k','l',';',39 ,'`',0  ,92 ,'z','x','c','v',        // 2\r
93         'b','n','m',',','.','/',0  ,'*',0  ,' ',0  ,0  ,0  ,0  ,0  ,0  ,        // 3\r
94         0  ,0  ,0  ,0  ,0  ,0  ,0  ,'7','8','9','-','4','5','6','+','1',        // 4\r
95         '2','3','0',127,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 5\r
96         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 6\r
97         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0           // 7\r
98                                         },\r
99                                         far ShiftNames[] =              // Shifted ASCII for scan codes\r
100                                         {\r
101 //       0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F\r
102         0  ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8  ,9  ,        // 0\r
103         'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0  ,'A','S',        // 1\r
104         'D','F','G','H','J','K','L',':',34 ,'~',0  ,'|','Z','X','C','V',        // 2\r
105         'B','N','M','<','>','?',0  ,'*',0  ,' ',0  ,0  ,0  ,0  ,0  ,0  ,        // 3\r
106         0  ,0  ,0  ,0  ,0  ,0  ,0  ,'7','8','9','-','4','5','6','+','1',        // 4\r
107         '2','3','0',127,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 5\r
108         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 6\r
109         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0           // 7\r
110                                         },\r
111                                         far SpecialNames[] =    // ASCII for 0xe0 prefixed codes\r
112                                         {\r
113 //       0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F\r
114         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 0\r
115         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,13 ,0  ,0  ,0  ,        // 1\r
116         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 2\r
117         0  ,0  ,0  ,0  ,0  ,'/',0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 3\r
118         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 4\r
119         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 5\r
120         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,        // 6\r
121         0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0           // 7\r
122                                         },\r
123                                         *ScanNames[] =          // Scan code names with single chars\r
124                                         {\r
125         "?","?","1","2","3","4","5","6","7","8","9","0","-","+","?","?",\r
126         "Q","W","E","R","T","Y","U","I","O","P","[","]","|","?","A","S",\r
127         "D","F","G","H","J","K","L",";","\"","?","?","?","Z","X","C","V",\r
128         "B","N","M",",",".","/","?","?","?","?","?","?","?","?","?","?",\r
129         "?","?","?","?","?","?","?","?","\xf","?","-","\x15","5","\x11","+","?",\r
130         "\x13","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",\r
131         "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",\r
132         "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?"\r
133                                         },      // DEBUG - consolidate these\r
134                                         far ExtScanCodes[] =    // Scan codes with >1 char names\r
135                                         {\r
136         1,0xe,0xf,0x1d,0x2a,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,\r
137         0x3f,0x40,0x41,0x42,0x43,0x44,0x57,0x59,0x46,0x1c,0x36,\r
138         0x37,0x38,0x47,0x49,0x4f,0x51,0x52,0x53,0x45,0x48,\r
139         0x50,0x4b,0x4d,0x00\r
140                                         },\r
141                                         *ExtScanNames[] =       // Names corresponding to ExtScanCodes\r
142                                         {\r
143         "Esc","BkSp","Tab","Ctrl","LShft","Space","CapsLk","F1","F2","F3","F4",\r
144         "F5","F6","F7","F8","F9","F10","F11","F12","ScrlLk","Enter","RShft",\r
145         "PrtSc","Alt","Home","PgUp","End","PgDn","Ins","Del","NumLk","Up",\r
146         "Down","Left","Right",""\r
147                                         };\r
148 \r
149 static  Direction       DirTable[] =            // Quick lookup for total direction\r
150                                         {\r
151                                                 /*dir_NorthWest,        */dir_North,/*  dir_NorthEast,*/\r
152                                                 dir_West,               dir_None,       dir_East,\r
153                                                 /*dir_SouthWest,        */dir_South/*,  dir_SouthEast*/\r
154                                         };\r
155 #ifdef __cplusplus\r
156 }\r
157 #endif\r
158 \r
159 static  void                    (*INL_KeyHook)(void);\r
160 static  void interrupt  (*OldKeyVect)(void);\r
161 static  char                    *ParmStringsIN[] = {"nojoys","nomouse",nil};\r
162 \r
163 //      Internal routines\r
164 \r
165 ///////////////////////////////////////////////////////////////////////////\r
166 //\r
167 //      INL_KeyService() - Handles a keyboard interrupt (key up/down)\r
168 //\r
169 ///////////////////////////////////////////////////////////////////////////\r
170 /*static */void interrupt\r
171 INL_KeyService(void)\r
172 {\r
173 static  boolean special;\r
174                 byte    k,c,\r
175                                 temp;\r
176 \r
177         k = inportb(0x60);      // Get the scan code\r
178 \r
179         // Tell the XT keyboard controller to clear the key\r
180         outportb(0x61,(temp = inportb(0x61)) | 0x80);\r
181         outportb(0x61,temp);\r
182 \r
183         if (k == 0xe0)          // Special key prefix\r
184                 special = true;\r
185         else if (k == 0xe1)     // Handle Pause key\r
186                 inpu.Paused = true;\r
187         else\r
188         {\r
189                 if (k & 0x80)   // Break code\r
190                 {\r
191                         k &= 0x7f;\r
192 \r
193 // DEBUG - handle special keys: ctl-alt-delete, print scrn\r
194 \r
195                         inpu.Keyboard[k] = false;\r
196                 }\r
197                 else                    // Make code\r
198                 {\r
199                         inst.LastCode = inst.CurCode;\r
200                         inst.CurCode = inpu.LastScan = k;\r
201                         inpu.Keyboard[k] = true;\r
202 \r
203                         if (special)\r
204                                 c = SpecialNames[k];\r
205                         else\r
206                         {\r
207                                 if (k == sc_CapsLock)\r
208                                 {\r
209                                         inst.CapsLock ^= true;\r
210                                         // DEBUG - make caps lock light work\r
211                                 }\r
212 \r
213                                 if (inpu.Keyboard[sc_LShift] || inpu.Keyboard[sc_RShift])       // If shifted\r
214                                 {\r
215                                         c = ShiftNames[k];\r
216                                         if ((c >= 'A') && (c <= 'Z') && inst.CapsLock)\r
217                                                 c += 'a' - 'A';\r
218                                 }\r
219                                 else\r
220                                 {\r
221                                         c = ASCIINames[k];\r
222                                         if ((c >= 'a') && (c <= 'z') && inst.CapsLock)\r
223                                                 c -= 'a' - 'A';\r
224                                 }\r
225                         }\r
226                         if (c)\r
227                                 inpu.LastASCII = c;\r
228                 }\r
229 \r
230                 special = false;\r
231         }\r
232 \r
233         if (INL_KeyHook && !special)\r
234                 INL_KeyHook();\r
235 #ifdef __DEBUG_InputMgr__\r
236         if(dbg_testkeyin > 0) printf("%c        %u      [0x%x %u]       %u\n", c, c, k, k, inpu.Keyboard[k]);\r
237 #endif\r
238         outportb(0x20,0x20);\r
239 }\r
240 \r
241 void INL_Mouse(int x)\r
242 {\r
243         //union REGS CPURegs;\r
244         //x = CPURegs.x.ax;\r
245         __asm {\r
246                 mov     ax,x\r
247                 int     MouseInt\r
248         }\r
249         //int86(MouseInt,&CPURegs,&CPURegs);\r
250 }\r
251 \r
252 ///////////////////////////////////////////////////////////////////////////\r
253 //\r
254 //      INL_GetMouseDelta() - Gets the amount that the mouse has moved from the\r
255 //              mouse driver\r
256 //\r
257 ///////////////////////////////////////////////////////////////////////////\r
258 static void\r
259 INL_GetMouseDelta(int *x,int *y)\r
260 {\r
261         union REGS CPURegs;\r
262         Mouse(MDelta);\r
263         *x = CPURegs.x.cx;\r
264         *y = CPURegs.x.dx;\r
265 }\r
266 \r
267 ///////////////////////////////////////////////////////////////////////////\r
268 //\r
269 //      INL_GetMouseButtons() - Gets the status of the mouse buttons from the\r
270 //              mouse driver\r
271 //\r
272 ///////////////////////////////////////////////////////////////////////////\r
273 static word\r
274 INL_GetMouseButtons(void)\r
275 {\r
276         union REGS CPURegs;\r
277         word    buttons;\r
278 \r
279         Mouse(MButtons);\r
280         buttons = CPURegs.x.bx;\r
281         return(buttons);\r
282 }\r
283 \r
284 ///////////////////////////////////////////////////////////////////////////\r
285 //\r
286 //      IN_GetJoyAbs() - Reads the absolute position of the specified joystick\r
287 //\r
288 ///////////////////////////////////////////////////////////////////////////\r
289 void\r
290 IN_GetJoyAbs(word joy,word *xp,word *yp)\r
291 {\r
292         byte    xb,yb,\r
293                         xs,ys;\r
294         word    x,y;\r
295 \r
296         x = y = 0;\r
297         xs = joy? 2 : 0;                // Find shift value for x axis\r
298         xb = 1 << xs;                   // Use shift value to get x bit mask\r
299         ys = joy? 3 : 1;                // Do the same for y axis\r
300         yb = 1 << ys;\r
301 \r
302 // Read the absolute joystick values\r
303         __asm {\r
304                 pushf                           // Save some registers\r
305                 push    si\r
306                 push    di\r
307                 cli                                     // Make sure an interrupt doesn't screw the timings\r
308 \r
309 \r
310                 mov             dx,0x201\r
311                 in              al,dx\r
312                 out             dx,al           // Clear the resistors\r
313 \r
314                 mov             ah,[xb]         // Get masks into registers\r
315                 mov             ch,[yb]\r
316 \r
317                 xor             si,si           // Clear count registers\r
318                 xor             di,di\r
319                 xor             bh,bh           // Clear high byte of bx for later\r
320 \r
321                 push    bp                      // Don't mess up stack frame\r
322                 mov             bp,MaxJoyValue\r
323 #ifdef __BORLANDC__\r
324         }\r
325 #endif\r
326 loo:\r
327 #ifdef __BORLANDC__\r
328         __asm {\r
329 #endif\r
330                 in              al,dx           // Get bits indicating whether all are finished\r
331 \r
332                 dec             bp                      // Check bounding register\r
333                 jz              done            // We have a silly value - abort\r
334 \r
335                 mov             bl,al           // Duplicate the bits\r
336                 and             bl,ah           // Mask off useless bits (in [xb])\r
337                 add             si,bx           // Possibly increment count register\r
338                 mov             cl,bl           // Save for testing later\r
339 \r
340                 mov             bl,al\r
341                 and             bl,ch           // [yb]\r
342                 add             di,bx\r
343 \r
344                 add             cl,bl\r
345                 jnz             loo             // If both bits were 0, drop out\r
346 #ifdef __BORLANDC__\r
347         }\r
348 #endif\r
349 done:\r
350 #ifdef __BORLANDC__\r
351         __asm {\r
352 #endif\r
353                 pop             bp\r
354 \r
355                 mov             cl,[xs]         // Get the number of bits to shift\r
356                 shr             si,cl           //  and shift the count that many times\r
357 \r
358                 mov             cl,[ys]\r
359                 shr             di,cl\r
360 \r
361                 mov             [x],si          // Store the values into the variables\r
362                 mov             [y],di\r
363 \r
364                 pop             di\r
365                 pop             si\r
366                 popf                            // Restore the registers\r
367         }\r
368 \r
369         *xp = x;\r
370         *yp = y;\r
371 }\r
372 \r
373 ///////////////////////////////////////////////////////////////////////////\r
374 //\r
375 //      INL_GetJoyDelta() - Returns the relative movement of the specified\r
376 //              joystick (from +/-127)\r
377 //\r
378 ///////////////////////////////////////////////////////////////////////////\r
379 void INL_GetJoyDelta(word joy,int *dx,int *dy/*,boolean adaptive*/)\r
380 {\r
381         word            x,y;\r
382         word TimeCount = *clockw;\r
383         JoystickDef     *def;\r
384 static  word    lasttime;\r
385 \r
386         IN_GetJoyAbs(joy,&x,&y);\r
387         def = inpu.JoyDefs + joy;\r
388 \r
389         if (x < def->threshMinX)\r
390         {\r
391                 if (x < def->joyMinX)\r
392                         x = def->joyMinX;\r
393 \r
394                 x = -(x - def->threshMinX);\r
395                 x *= def->joyMultXL;\r
396                 x >>= JoyScaleShift;\r
397                 *dx = (x > 127)? -127 : -x;\r
398         }\r
399         else if (x > def->threshMaxX)\r
400         {\r
401                 if (x > def->joyMaxX)\r
402                         x = def->joyMaxX;\r
403 \r
404                 x = x - def->threshMaxX;\r
405                 x *= def->joyMultXH;\r
406                 x >>= JoyScaleShift;\r
407                 *dx = (x > 127)? 127 : x;\r
408         }\r
409         else\r
410                 *dx = 0;\r
411 \r
412         if (y < def->threshMinY)\r
413         {\r
414                 if (y < def->joyMinY)\r
415                         y = def->joyMinY;\r
416 \r
417                 y = -(y - def->threshMinY);\r
418                 y *= def->joyMultYL;\r
419                 y >>= JoyScaleShift;\r
420                 *dy = (y > 127)? -127 : -y;\r
421         }\r
422         else if (y > def->threshMaxY)\r
423         {\r
424                 if (y > def->joyMaxY)\r
425                         y = def->joyMaxY;\r
426 \r
427                 y = y - def->threshMaxY;\r
428                 y *= def->joyMultYH;\r
429                 y >>= JoyScaleShift;\r
430                 *dy = (y > 127)? 127 : y;\r
431         }\r
432         else\r
433                 *dy = 0;\r
434 //      if (adaptive)\r
435 //      {\r
436 //              time = (TimeCount - lasttime) / 2;\r
437 //              if (time)\r
438 //              {\r
439 //                      if (time > 8)\r
440 //                              time = 8;\r
441 //                      *dx *= time;\r
442 //                      *dy *= time;\r
443 //              }\r
444 //      }\r
445         lasttime = TimeCount;\r
446 }\r
447 \r
448 ///////////////////////////////////////////////////////////////////////////\r
449 //\r
450 //      INL_GetJoyButtons() - Returns the button status of the specified\r
451 //              joystick\r
452 //\r
453 ///////////////////////////////////////////////////////////////////////////\r
454 static word\r
455 INL_GetJoyButtons(word joy)\r
456 {\r
457 register        word    result;\r
458 \r
459         result = inportb(0x201);        // Get all the joystick buttons\r
460         result >>= joy? 6 : 4;  // Shift into bits 0-1\r
461         result &= 3;                            // Mask off the useless bits\r
462         result ^= 3;\r
463         return(result);\r
464 }\r
465 \r
466 ///////////////////////////////////////////////////////////////////////////\r
467 //\r
468 //      IN_GetJoyButtonsDB() - Returns the de-bounced button status of the\r
469 //              specified joystick\r
470 //\r
471 ///////////////////////////////////////////////////////////////////////////\r
472 word\r
473 IN_GetJoyButtonsDB(word joy)\r
474 {\r
475         word TimeCount = *clockw;\r
476         word    lasttime;\r
477         word            result1,result2;\r
478 \r
479         do\r
480         {\r
481                 result1 = INL_GetJoyButtons(joy);\r
482                 lasttime = TimeCount;\r
483                 while(TimeCount == lasttime)\r
484                         //;\r
485                 result2 = INL_GetJoyButtons(joy);\r
486         } while(result1 != result2);\r
487         return(result1);\r
488 }\r
489 \r
490 ///////////////////////////////////////////////////////////////////////////\r
491 //\r
492 //      INL_StartKbd() - Sets up my keyboard stuff for use\r
493 //\r
494 ///////////////////////////////////////////////////////////////////////////\r
495 static void\r
496 INL_StartKbd(void)\r
497 {\r
498         INL_KeyHook = NULL;     // Clear key hook\r
499 \r
500         IN_ClearKeysDown();\r
501 \r
502         OldKeyVect = getvect(KeyInt);//IN_KbdLED();\r
503         setvect(KeyInt,INL_KeyService);\r
504 }\r
505 \r
506 ///////////////////////////////////////////////////////////////////////////\r
507 //\r
508 //      INL_ShutKbd() - Restores keyboard control to the BIOS\r
509 //\r
510 ///////////////////////////////////////////////////////////////////////////\r
511 static void\r
512 INL_ShutKbd(void)\r
513 {\r
514         pokeb(0x40,0x17,peekb(0x40,0x17) & 0xfaf0);     // Clear ctrl/alt/shift flags\r
515 \r
516         setvect(KeyInt,OldKeyVect);\r
517 }\r
518 \r
519 ///////////////////////////////////////////////////////////////////////////\r
520 //\r
521 //      INL_StartMouse() - Detects and sets up the mouse\r
522 //\r
523 ///////////////////////////////////////////////////////////////////////////\r
524 static boolean\r
525 INL_StartMouse(void)\r
526 {\r
527 #if 0\r
528         if (getvect(MouseInt))\r
529         {\r
530                 Mouse(MReset);\r
531                 if (_AX == 0xffff)\r
532                         return(true);\r
533         }\r
534         return(false);\r
535 #endif\r
536         byte far *vector;\r
537 \r
538 \r
539         if ((vector=MK_FP(peek(0,0x33*4+2),peek(0,0x33*4)))==NULL)\r
540         return false;\r
541 \r
542         if (*vector == 207)\r
543                 return false;\r
544 \r
545         Mouse(MReset);\r
546         return true;\r
547 }\r
548 \r
549 ///////////////////////////////////////////////////////////////////////////\r
550 //\r
551 //      INL_ShutMouse() - Cleans up after the mouse\r
552 //\r
553 ///////////////////////////////////////////////////////////////////////////\r
554 static void\r
555 INL_ShutMouse(void)\r
556 {\r
557 }\r
558 \r
559 //\r
560 //      INL_SetJoyScale() - Sets up scaling values for the specified joystick\r
561 //\r
562 static void\r
563 INL_SetJoyScale(word joy)\r
564 {\r
565         JoystickDef     *def;\r
566 \r
567         def = &(inpu.JoyDefs[joy]);\r
568         def->joyMultXL = JoyScaleMax / (def->threshMinX - def->joyMinX);\r
569         def->joyMultXH = JoyScaleMax / (def->joyMaxX - def->threshMaxX);\r
570         def->joyMultYL = JoyScaleMax / (def->threshMinY - def->joyMinY);\r
571         def->joyMultYH = JoyScaleMax / (def->joyMaxY - def->threshMaxY);\r
572 }\r
573 \r
574 ///////////////////////////////////////////////////////////////////////////\r
575 //\r
576 //      IN_SetupJoy() - Sets up thresholding values and calls INL_SetJoyScale()\r
577 //              to set up scaling values\r
578 //\r
579 ///////////////////////////////////////////////////////////////////////////\r
580 void\r
581 IN_SetupJoy(word joy,word minx,word maxx,word miny,word maxy)\r
582 {\r
583         word            d,r;\r
584         JoystickDef     *def;\r
585 \r
586         def = &(inpu.JoyDefs[joy]);\r
587 \r
588         def->joyMinX = minx;\r
589         def->joyMaxX = maxx;\r
590         r = maxx - minx;\r
591         d = r / 3;\r
592         def->threshMinX = ((r / 2) - d) + minx;\r
593         def->threshMaxX = ((r / 2) + d) + minx;\r
594 \r
595         def->joyMinY = miny;\r
596         def->joyMaxY = maxy;\r
597         r = maxy - miny;\r
598         d = r / 3;\r
599         def->threshMinY = ((r / 2) - d) + miny;\r
600         def->threshMaxY = ((r / 2) + d) + miny;\r
601 \r
602         INL_SetJoyScale(joy);\r
603 }\r
604 \r
605 ///////////////////////////////////////////////////////////////////////////\r
606 //\r
607 //      INL_StartJoy() - Detects & auto-configures the specified joystick\r
608 //                                      The auto-config assumes the joystick is centered\r
609 //\r
610 ///////////////////////////////////////////////////////////////////////////\r
611 static boolean\r
612 INL_StartJoy(word joy)\r
613 {\r
614         word            x,y;\r
615 \r
616         IN_GetJoyAbs(joy,&x,&y);\r
617 \r
618         if\r
619         (\r
620                 ((x == 0) || (x > MaxJoyValue - 10))\r
621         ||      ((y == 0) || (y > MaxJoyValue - 10))\r
622         )\r
623                 return(false);\r
624         else\r
625         {\r
626                 IN_SetupJoy(joy,0,x * 2,0,y * 2);\r
627                 return(true);\r
628         }\r
629 }\r
630 \r
631 ///////////////////////////////////////////////////////////////////////////\r
632 //\r
633 //      INL_ShutJoy() - Cleans up the joystick stuff\r
634 //\r
635 ///////////////////////////////////////////////////////////////////////////\r
636 static void\r
637 INL_ShutJoy(word joy)\r
638 {\r
639         inpu.JoysPresent[joy] = false;\r
640 }\r
641 \r
642 //      Public routines\r
643 \r
644 ///////////////////////////////////////////////////////////////////////////\r
645 //\r
646 //      IN_Startup() - Starts up the Input Mgr\r
647 //\r
648 ///////////////////////////////////////////////////////////////////////////\r
649 void\r
650 IN_Startup()\r
651 {\r
652         boolean checkjoys,checkmouse;\r
653         word    i;\r
654 \r
655         if (inst.IN_Started)\r
656                 return;\r
657 \r
658         checkjoys = true;\r
659         checkmouse = true;\r
660         for (i = 1;i < _argc;i++)\r
661         {\r
662                 switch (US_CheckParm(_argv[i],ParmStringsIN))\r
663                 {\r
664                 case 0:\r
665                         checkjoys = false;\r
666                         break;\r
667                 case 1:\r
668                         checkmouse = false;\r
669                         break;\r
670                 }\r
671         }\r
672 \r
673         INL_StartKbd();\r
674         inpu.MousePresent = checkmouse? INL_StartMouse() : false;\r
675 \r
676         for (i = 0;i < MaxJoys;i++)\r
677                 inpu.JoysPresent[i] = checkjoys? INL_StartJoy(i) : false;\r
678 \r
679         inst.IN_Started = true;\r
680 \r
681 }\r
682 \r
683 ///////////////////////////////////////////////////////////////////////////\r
684 //\r
685 //      IN_Default() - Sets up default conditions for the Input Mgr\r
686 //\r
687 ///////////////////////////////////////////////////////////////////////////\r
688 void\r
689 IN_Default(boolean gotit,player_t *player,ControlType nt)\r
690 {\r
691         int i;\r
692         if\r
693         (\r
694                 (!gotit)\r
695         ||      ((nt == ctrl_Joystick1) && !inpu.JoysPresent[0])\r
696         ||      ((nt == ctrl_Joystick2) && !inpu.JoysPresent[1])\r
697         ||      ((nt == ctrl_Mouse) && !inpu.MousePresent)\r
698         )\r
699                 nt = ctrl_Keyboard1;\r
700         inpu.KbdDefs[0].button0 = 0x1c;\r
701         inpu.KbdDefs[0].button1 = 0x38;\r
702         //in.KbdDefs[0].upleft = 0x47;\r
703         inpu.KbdDefs[0].up = 0x48;\r
704         //in.KbdDefs[0].upright = 0x49;\r
705         inpu.KbdDefs[0].left = 0x4b;\r
706         inpu.KbdDefs[0].right = 0x4d;\r
707         //in.KbdDefs[0].downleft = 0x4f;\r
708         inpu.KbdDefs[0].down = 0x50;\r
709         //in.KbdDefs[0].downright = 0x51;\r
710         IN_SetControlType(player,nt);\r
711         for(i=0; i>MaxPlayers;i++)\r
712                 player[i].enti.d =2;\r
713 }\r
714 \r
715 ///////////////////////////////////////////////////////////////////////////\r
716 //\r
717 //      IN_Shutdown() - Shuts down the Input Mgr\r
718 //\r
719 ///////////////////////////////////////////////////////////////////////////\r
720 void\r
721 IN_Shutdown(void)\r
722 {\r
723         word    i;\r
724 \r
725         if (!inst.IN_Started)\r
726                 return;\r
727 \r
728         INL_ShutMouse();\r
729         for (i = 0;i < MaxJoys;i++)\r
730                 INL_ShutJoy(i);\r
731         INL_ShutKbd();\r
732 \r
733         inst.IN_Started = false;\r
734 }\r
735 \r
736 ///////////////////////////////////////////////////////////////////////////\r
737 //\r
738 //      IN_SetKeyHook() - Sets the routine that gets called by INL_KeyService()\r
739 //                      everytime a real make/break code gets hit\r
740 //\r
741 ///////////////////////////////////////////////////////////////////////////\r
742 void\r
743 IN_SetKeyHook(void (*hook)())\r
744 {\r
745         INL_KeyHook = hook;\r
746 }\r
747 \r
748 ///////////////////////////////////////////////////////////////////////////\r
749 //\r
750 //      IN_ClearKeysDown() - Clears the keyboard array\r
751 //\r
752 ///////////////////////////////////////////////////////////////////////////\r
753 void\r
754 IN_ClearKeysDown(void)\r
755 {\r
756         //int   i;\r
757 \r
758         inpu.LastScan = sc_None;\r
759         inpu.LastASCII = key_None;\r
760         memset (inpu.Keyboard,0,sizeof(inpu.Keyboard));\r
761 }\r
762 \r
763 ///////////////////////////////////////////////////////////////////////////\r
764 //\r
765 //      INL_AdjustCursor() - Internal routine of common code from IN_ReadCursor()\r
766 //\r
767 ///////////////////////////////////////////////////////////////////////////\r
768 static void\r
769 INL_AdjustCursor(CursorInfo *info,word buttons,int dx,int dy)\r
770 {\r
771         if (buttons & (1 << 0))\r
772                 info->button0 = true;\r
773         if (buttons & (1 << 1))\r
774                 info->button1 = true;\r
775 \r
776         info->x += dx;\r
777         info->y += dy;\r
778 }\r
779 \r
780 ///////////////////////////////////////////////////////////////////////////\r
781 //\r
782 //      IN_ReadCursor() - Reads the input devices and fills in the cursor info\r
783 //              struct\r
784 //\r
785 ///////////////////////////////////////////////////////////////////////////\r
786 void\r
787 IN_ReadCursor(CursorInfo *info)\r
788 {\r
789         word    i,\r
790                         buttons;\r
791         int             dx,dy;\r
792 \r
793         info->x = info->y = 0;\r
794         info->button0 = info->button1 = false;\r
795 \r
796         if (inpu.MousePresent)\r
797         {\r
798                 buttons = INL_GetMouseButtons();\r
799                 INL_GetMouseDelta(&dx,&dy);\r
800                 INL_AdjustCursor(info,buttons,dx,dy);\r
801         }\r
802 \r
803         for (i = 0;i < MaxJoys;i++)\r
804         {\r
805                 if (!inpu.JoysPresent[i])\r
806                         continue;\r
807 \r
808                 buttons = INL_GetJoyButtons(i);\r
809                 INL_GetJoyDelta(i,&dx,&dy/*,true*/);\r
810                 dx /= 64;\r
811                 dy /= 64;\r
812                 INL_AdjustCursor(info,buttons,dx,dy);\r
813         }\r
814 }\r
815 \r
816 //if else for gfxtesting and direction\r
817 #define DIRECTIONIFELSE (player->info.dir == 2)\r
818 //#define NDIRECTIONIFELSE      (player->info.dir != 2)\r
819 \r
820 ///////////////////////////////////////////////////////////////////////////\r
821 //\r
822 //      IN_ReadControl() - Reads the device associated with the specified\r
823 //              player and fills in the control info struct\r
824 //\r
825 ///////////////////////////////////////////////////////////////////////////\r
826 void\r
827 IN_ReadControl(player_t *player)\r
828 {\r
829                         boolean         realdelta;\r
830 #if DEMO0\r
831                         byte            dbyte;\r
832 #endif\r
833                         word            buttons;\r
834                         int                     dx,dy;\r
835                         Motion          mx,my;\r
836                         ControlType     type;\r
837                         sword conpee;\r
838                         byte dir=DirTable[2];\r
839 register        KeyboardDef     *def;\r
840 \r
841         dx = dy = 0;\r
842         mx = my = motion_None;\r
843         buttons = 0;\r
844 \r
845 #if DEMO0\r
846         if (DemoMode == demo_Playback)\r
847         {\r
848                 dbyte = DemoBuffer[DemoOffset + 1];\r
849                 my = (dbyte & 3) - 1;\r
850                 mx = ((dbyte >> 2) & 3) - 1;\r
851                 buttons = (dbyte >> 4) & 3;\r
852 \r
853                 if (!(--DemoBuffer[DemoOffset]))\r
854                 {\r
855                         DemoOffset += 2;\r
856                         if (DemoOffset >= DemoSize)\r
857                                 DemoMode = demo_PlayDone;\r
858                 }\r
859 \r
860                 realdelta = false;\r
861         }\r
862         else if (DemoMode == demo_PlayDone)\r
863                 Quit ("Demo playback exceeded");\r
864         else\r
865         {\r
866 #endif\r
867                 switch (type = player->Controls)\r
868                 {\r
869                 case ctrl_Keyboard1:\r
870                 case ctrl_Keyboard2:\r
871                         def = &(inpu.KbdDefs[type - ctrl_Keyboard]);\r
872 \r
873 /*                      if (Keyboard[def->upleft])\r
874                                 mx = motion_Left,my = motion_Up;\r
875                         else if (Keyboard[def->upright])\r
876                                 mx = motion_Right,my = motion_Up;\r
877                         else if (Keyboard[def->downleft])\r
878                                 mx = motion_Left,my = motion_Down;\r
879                         else if (Keyboard[def->downright])\r
880                                 mx = motion_Right,my = motion_Down;*/\r
881 //TODO: make this into a function that the joystick AND keyboard can use wwww\r
882                         if(DIRECTIONIFELSE)//(player->info.dir == 2)\r
883                         {\r
884                         if(!inpu.Keyboard[def->left] && !inpu.Keyboard[def->right]){\r
885                                 if((inpu.Keyboard[def->up] && !inpu.Keyboard[def->down]))\r
886                                         my = motion_Up;\r
887                                 if((inpu.Keyboard[def->down] && !inpu.Keyboard[def->up]))\r
888                                         my = motion_Down;\r
889                         }else if(!inpu.Keyboard[def->up] && !inpu.Keyboard[def->down]){\r
890                                 if((inpu.Keyboard[def->left] && !inpu.Keyboard[def->right]))\r
891                                         mx = motion_Left;\r
892                                 if((inpu.Keyboard[def->right] && !inpu.Keyboard[def->left]))\r
893                                         mx = motion_Right;\r
894                         }else{  //2 keys pressed\r
895                                         switch (player->pdir)\r
896                                         {\r
897                                                 case 0:\r
898                                                 case 4:\r
899                                                         if((inpu.Keyboard[def->left] && !inpu.Keyboard[def->right])){ dir = DirTable[1]; }//mx = motion_Left; }\r
900                                                         else if((inpu.Keyboard[def->right] && !inpu.Keyboard[def->left])){ dir = DirTable[3]; }//mx = motion_Right; }\r
901                                                 break;\r
902                                                 case 1:\r
903                                                 case 3:\r
904                                                         if((inpu.Keyboard[def->up] && !inpu.Keyboard[def->down])){ dir = DirTable[0]; }//my = motion_Up; }\r
905                                                         else if((inpu.Keyboard[def->down] && !inpu.Keyboard[def->up])){ dir = DirTable[4]; }//my = motion_Down; }\r
906                                                 break;\r
907                                                 default:\r
908                                                 break;\r
909                                         }\r
910 #ifdef __DEBUG_InputMgr__\r
911                                         //if(dbg_testcontrolnoisy > 0){ printf("dir=%c ", dirchar(dir)); printf("pdir=%c        ", dirchar(player->pdir)); }\r
912 #endif\r
913                                 }\r
914                         }\r
915                         //input from player\r
916                         if (inpu.Keyboard[def->button0])\r
917                                 buttons += 1 << 0;\r
918                         if (inpu.Keyboard[def->button1])\r
919                                 buttons += 1 << 1;\r
920                         realdelta = false;\r
921                         break;\r
922                 case ctrl_Joystick1:\r
923                 case ctrl_Joystick2:\r
924                         INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy/*,false*/);\r
925                         buttons = INL_GetJoyButtons(type - ctrl_Joystick);\r
926                         realdelta = true;\r
927                         break;\r
928                 case ctrl_Mouse:\r
929                         INL_GetMouseDelta(&dx,&dy);\r
930                         buttons = INL_GetMouseButtons();\r
931                         realdelta = true;\r
932                         break;\r
933                 }\r
934 #ifdef DEMO0\r
935         }\r
936 #endif\r
937 \r
938         if (realdelta)\r
939         {\r
940                 mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);\r
941                 my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);\r
942         }\r
943         else\r
944         {\r
945                 dx = mx;// * 127;\r
946                 dy = my;// * 127;\r
947         }\r
948 \r
949         player->info.x = dx;\r
950         player->info.xaxis = mx;\r
951         player->info.y = dy;\r
952         player->info.yaxis = my;\r
953         player->info.button0 = buttons & (1 << 0);\r
954         player->info.button1 = buttons & (1 << 1);\r
955         player->info.button2 = buttons & (1 << 2);\r
956         player->info.button3 = buttons & (1 << 3);\r
957 //      player->info.dir = DirTable[((my + 1) * 3) + (mx + 1)];\r
958         conpee=(((my + 1) * 2) + (mx + 1))-1;\r
959         player->info.dir = DirTable[conpee];\r
960 \r
961         if(DirTable[conpee]!=2) player->pdir=DirTable[conpee];\r
962         if(player->enti.q==1 &&( dir!=2 || (mx!=motion_None || my!=motion_None)))\r
963         {\r
964                 if(dir==2) player->enti.d = player->info.dir;\r
965                 else player->enti.d = DirTable[dir];\r
966         }\r
967 \r
968 #if DEMO0\r
969         if (DemoMode == demo_Record)\r
970         {\r
971                 // Pack the control info into a byte\r
972                 dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);\r
973 \r
974                 if\r
975                 (\r
976                         (DemoBuffer[DemoOffset + 1] == dbyte)\r
977                 &&      (DemoBuffer[DemoOffset] < 255)\r
978                 )\r
979                         (DemoBuffer[DemoOffset])++;\r
980                 else\r
981                 {\r
982                         if (DemoOffset || DemoBuffer[DemoOffset])\r
983                                 DemoOffset += 2;\r
984 \r
985                         if (DemoOffset >= DemoSize)\r
986                                 Quit ("Demo buffer overflow");\r
987 \r
988                         DemoBuffer[DemoOffset] = 1;\r
989                         DemoBuffer[DemoOffset + 1] = dbyte;\r
990                 }\r
991         }\r
992 #endif\r
993 #ifdef __DEBUG_InputMgr__\r
994 if(dbg_testcontrolnoisy > 0)\r
995 if(player->info.dir!=2/*(inpu.Keyboard[def->up] || inpu.Keyboard[def->down] || inpu.Keyboard[def->left] || inpu.Keyboard[def->right])*/ || player->enti.q>1)\r
996 {\r
997         //printf("b1=%u b2=%u b3=%u b4=%u       ", player->info.button0, player->info.button1, player->info.button2, player->info.button3);\r
998         //printf("q=%d ", player->enti.q);\r
999         //printf("cpee=%c ", dirchar(conpee));\r
1000         printf("pdir=%c d=%c dir=%c ", dirchar(player->pdir), dirchar(player->enti.d), dirchar(player->info.dir));\r
1001         /*if(realdelta) */printf("dx=%d dy=%d   mx=%d   my=%d", player->info.x, player->info.y, player->info.xaxis, player->info.yaxis);\r
1002         //else if(!realdelta) printf("%c%d %c%d %c%d %c%d", dirchar(0), inpu.Keyboard[def->up], dirchar(4), inpu.Keyboard[def->down], dirchar(1), inpu.Keyboard[def->left], dirchar(3), inpu.Keyboard[def->right]);\r
1003         printf("\n");\r
1004 }\r
1005 #endif\r
1006 }\r
1007 \r
1008 ///////////////////////////////////////////////////////////////////////////\r
1009 //\r
1010 //      IN_SetControlType() - Sets the control type to be used by the specified\r
1011 //              player\r
1012 //\r
1013 ///////////////////////////////////////////////////////////////////////////\r
1014 void\r
1015 IN_SetControlType(player_t *player,ControlType type)\r
1016 {\r
1017         // DEBUG - check that requested type is present?\r
1018         player->Controls = type;\r
1019 }\r
1020 \r
1021 #if DEMO0\r
1022 ///////////////////////////////////////////////////////////////////////////\r
1023 //\r
1024 //      IN_StartDemoRecord() - Starts the demo recording, using a buffer the\r
1025 //              size passed. Returns if the buffer allocation was successful\r
1026 //\r
1027 ///////////////////////////////////////////////////////////////////////////\r
1028 boolean\r
1029 IN_StartDemoRecord(word bufsize)\r
1030 {\r
1031         if (!bufsize)\r
1032                 return(false);\r
1033 \r
1034         MM_GetPtr((memptr *)&DemoBuffer,bufsize);\r
1035         DemoMode = demo_Record;\r
1036         DemoSize = bufsize & ~1;\r
1037         DemoOffset = 0;\r
1038         DemoBuffer[0] = DemoBuffer[1] = 0;\r
1039 \r
1040         return(true);\r
1041 }\r
1042 \r
1043 ///////////////////////////////////////////////////////////////////////////\r
1044 //\r
1045 //      IN_StartDemoPlayback() - Plays back the demo pointed to of the given size\r
1046 //\r
1047 ///////////////////////////////////////////////////////////////////////////\r
1048 void\r
1049 IN_StartDemoPlayback(byte /*__segment*/ *buffer,word bufsize)\r
1050 {\r
1051         DemoBuffer = buffer;\r
1052         DemoMode = demo_Playback;\r
1053         DemoSize = bufsize & ~1;\r
1054         DemoOffset = 0;\r
1055 }\r
1056 \r
1057 ///////////////////////////////////////////////////////////////////////////\r
1058 //\r
1059 //      IN_StopDemo() - Turns off demo mode\r
1060 //\r
1061 ///////////////////////////////////////////////////////////////////////////\r
1062 void\r
1063 IN_StopDemo(void)\r
1064 {\r
1065         if ((DemoMode == demo_Record) && DemoOffset)\r
1066                 DemoOffset += 2;\r
1067 \r
1068         DemoMode = demo_Off;\r
1069 }\r
1070 \r
1071 ///////////////////////////////////////////////////////////////////////////\r
1072 //\r
1073 //      IN_FreeDemoBuffer() - Frees the demo buffer, if it's been allocated\r
1074 //\r
1075 ///////////////////////////////////////////////////////////////////////////\r
1076 void\r
1077 IN_FreeDemoBuffer(void)\r
1078 {\r
1079         if (DemoBuffer)\r
1080                 MM_FreePtr((memptr *)&DemoBuffer);\r
1081 }\r
1082 #endif\r
1083 \r
1084 \r
1085 ///////////////////////////////////////////////////////////////////////////\r
1086 //\r
1087 //      IN_GetScanName() - Returns a string containing the name of the\r
1088 //              specified scan code\r
1089 //\r
1090 ///////////////////////////////////////////////////////////////////////////\r
1091 byte *\r
1092 IN_GetScanName(ScanCode scan)\r
1093 {\r
1094         byte            **p;\r
1095         ScanCode        far *s;\r
1096 \r
1097         for (s = ExtScanCodes,p = ExtScanNames;*s;p++,s++)\r
1098                 if (*s == scan)\r
1099                         return(*p);\r
1100 \r
1101         return(ScanNames[scan]);\r
1102 }\r
1103 \r
1104 ///////////////////////////////////////////////////////////////////////////\r
1105 //\r
1106 //      IN_WaitForKey() - Waits for a scan code, then clears LastScan and\r
1107 //              returns the scan code\r
1108 //\r
1109 ///////////////////////////////////////////////////////////////////////////\r
1110 ScanCode\r
1111 IN_WaitForKey(void)\r
1112 {\r
1113         ScanCode        result;\r
1114 \r
1115         while (!(result = inpu.LastScan))\r
1116                 ;\r
1117         inpu.LastScan = 0;\r
1118         return(result);\r
1119 }\r
1120 \r
1121 ///////////////////////////////////////////////////////////////////////////\r
1122 //\r
1123 //      IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and\r
1124 //              returns the ASCII value\r
1125 //\r
1126 ///////////////////////////////////////////////////////////////////////////\r
1127 char\r
1128 IN_WaitForASCII(void)\r
1129 {\r
1130         char            result;\r
1131 \r
1132         while (!(result = inpu.LastASCII))\r
1133                 ;\r
1134         inpu.LastASCII = '\0';\r
1135         return(result);\r
1136 }\r
1137 \r
1138 ///////////////////////////////////////////////////////////////////////////\r
1139 //\r
1140 //      IN_Ack() - waits for a button or key press.  If a button is down, upon\r
1141 // calling, it must be released for it to be recognized\r
1142 //\r
1143 ///////////////////////////////////////////////////////////////////////////\r
1144 \r
1145 boolean btnstate[8];\r
1146 \r
1147 void IN_StartAck(void)\r
1148 {\r
1149         unsigned        i,buttons;\r
1150 \r
1151 //\r
1152 // get initial state of everything\r
1153 //\r
1154         IN_ClearKeysDown();\r
1155         memset (btnstate,0,sizeof(btnstate));\r
1156 \r
1157         buttons = IN_JoyButtons () << 4;\r
1158         if (inpu.MousePresent)\r
1159                 buttons |= IN_MouseButtons ();\r
1160 \r
1161         for (i=0;i<8;i++,buttons>>=1)\r
1162                 if (buttons&1)\r
1163                         btnstate[i] = true;\r
1164 }\r
1165 \r
1166 \r
1167 boolean IN_CheckAck (void)\r
1168 {\r
1169         unsigned        i,buttons;\r
1170 \r
1171 //\r
1172 // see if something has been pressed\r
1173 //\r
1174         if (inpu.LastScan)\r
1175                 return true;\r
1176 \r
1177         buttons = IN_JoyButtons () << 4;\r
1178         if (inpu.MousePresent)\r
1179                 buttons |= IN_MouseButtons ();\r
1180 \r
1181         for (i=0;i<8;i++,buttons>>=1)\r
1182                 if ( buttons&1 )\r
1183                 {\r
1184                         if (!btnstate[i])\r
1185                                 return true;\r
1186                 }\r
1187                 else\r
1188                         btnstate[i]=false;\r
1189 \r
1190         return false;\r
1191 }\r
1192 \r
1193 \r
1194 void IN_Ack (void)\r
1195 {\r
1196         IN_StartAck ();\r
1197 \r
1198         while (!IN_CheckAck ())\r
1199         ;\r
1200 }\r
1201 \r
1202 ///////////////////////////////////////////////////////////////////////////\r
1203 //\r
1204 //      IN_IsUserInput() - Returns true if a key has been pressed or a button\r
1205 //              is down\r
1206 //\r
1207 ///////////////////////////////////////////////////////////////////////////\r
1208 boolean\r
1209 IN_IsUserInput()\r
1210 {\r
1211         boolean result;\r
1212         word    i;\r
1213 \r
1214         result = inpu.LastScan;\r
1215 \r
1216         if (inpu.MousePresent)\r
1217                 if (INL_GetMouseButtons())\r
1218                         result = true;\r
1219 \r
1220         for (i = 0;i < MaxJoys;i++)\r
1221                 if (inpu.JoysPresent[i])\r
1222                         if (INL_GetJoyButtons(i))\r
1223                                 result = true;\r
1224 \r
1225         return(result);\r
1226 }\r
1227 \r
1228 ///////////////////////////////////////////////////////////////////////////\r
1229 //\r
1230 //      IN_UserInput() - Waits for the specified delay time (in ticks) or the\r
1231 //              user pressing a key or a mouse button. If the clear flag is set, it\r
1232 //              then either clears the key or waits for the user to let the mouse\r
1233 //              button up.\r
1234 //\r
1235 ///////////////////////////////////////////////////////////////////////////\r
1236 boolean IN_UserInput(word delay)\r
1237 {\r
1238         word TimeCount = *clockw;\r
1239         word    lasttime;\r
1240 \r
1241         lasttime = TimeCount;\r
1242         IN_StartAck ();\r
1243         do\r
1244         {\r
1245                 if (IN_CheckAck())\r
1246                         return true;\r
1247         } while (TimeCount - lasttime < delay);\r
1248         return(false);\r
1249 }\r
1250 \r
1251 //===========================================================================\r
1252 \r
1253 /*\r
1254 ===================\r
1255 =\r
1256 = IN_MouseButtons\r
1257 =\r
1258 ===================\r
1259 */\r
1260 \r
1261 byte    IN_MouseButtons (void)\r
1262 {\r
1263         union REGS CPURegs;\r
1264         if (inpu.MousePresent)\r
1265         {\r
1266                 Mouse(MButtons);\r
1267                 return CPURegs.x.bx;\r
1268         }\r
1269         else\r
1270                 return 0;\r
1271 }\r
1272 \r
1273 \r
1274 /*\r
1275 ===================\r
1276 =\r
1277 = IN_JoyButtons\r
1278 =\r
1279 ===================\r
1280 */\r
1281 \r
1282 byte    IN_JoyButtons (void)\r
1283 {\r
1284         byte joybits;\r
1285 \r
1286         joybits = inportb(0x201);       // Get all the joystick buttons\r
1287         joybits >>= 4;                          // only the high bits are useful\r
1288         joybits ^= 15;                          // return with 1=pressed\r
1289 \r
1290         return joybits;\r
1291 }\r
1292 \r
1293 boolean IN_KeyDown(byte code)\r
1294 {\r
1295 #ifdef __DEBUG_InputMgr__\r
1296         if(!dbg_nointest)\r
1297 #endif\r
1298         return inpu.Keyboard[code];\r
1299 #ifdef __DEBUG_InputMgr__\r
1300         else\r
1301                 if(dbg_nointest && kbhit())\r
1302                         return 1;\r
1303                 else\r
1304                         return 0;\r
1305 #endif\r
1306 }\r
1307 \r
1308 void IN_ClearKey(byte code)\r
1309 {\r
1310         inpu.Keyboard[code] = false;\r
1311         if(code == inpu.LastScan)\r
1312                 inpu.LastScan = sc_None;\r
1313         }\r
1314 \r
1315 boolean IN_qb(byte kee)\r
1316 {\r
1317 #ifdef __DEBUG_InputMgr__\r
1318         if(dbg_testkeyin) printf("%u\n", inpu.Keyboard[kee]);\r
1319 #endif\r
1320         if(inpu.Keyboard[kee]==true) return 1;\r
1321         else return 0;\r
1322 }\r
1323 \r
1324 ScanCode IN_GetLastScan()\r
1325 {\r
1326         return inpu.LastScan;\r
1327 }\r
1328 \r
1329 ScanCode IN_GetCurCode()\r
1330 {\r
1331         return inst.CurCode;\r
1332 }\r
1333 \r
1334 void IN_KbdLED()\r
1335 {\r
1336         byte far *lock_key;\r
1337 \r
1338         // turn off num-lock via BIOS\r
1339         lock_key = MK_FP(0x040, 0x017); // Pointing to the address of the bios shift state keys\r
1340         *lock_key&=(~(16 | 32 | 64)); // toggle off the locks by changing the values of the 4th, 5th, and 6th bits of the address byte of 0040:0017\r
1341         OldKeyVect();   // call BIOS keyhandler to change keyboard lights\r
1342 }\r