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