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