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