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