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