]> icculus.org git repositories - btb/d2x.git/blob - unused/bios/key.c
fixed location of fps meter in multi
[btb/d2x.git] / unused / bios / key.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 //#define PASS_KEYS_TO_BIOS     1                       //if set, bios gets keys
15
16 #pragma off (unreferenced)
17 static char rcsid[] = "$Id: key.c,v 1.1.1.1 2001-01-19 03:30:14 bradleyb Exp $";
18 #pragma on (unreferenced)
19
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <conio.h>
23 #include <dos.h>
24 #include <i86.h>
25
26 //#define WATCOM_10
27
28 #include "error.h"
29 #include "key.h"
30 #include "timer.h"
31 #include "dpmi.h"
32
33 #define KEY_BUFFER_SIZE 16
34
35 //-------- Variable accessed by outside functions ---------
36 unsigned char                           keyd_buffer_type;               // 0=No buffer, 1=buffer ASCII, 2=buffer scans
37 unsigned char                           keyd_repeat;
38 unsigned char                           keyd_editor_mode;
39 volatile unsigned char  keyd_last_pressed;
40 volatile unsigned char  keyd_last_released;
41 volatile unsigned char  keyd_pressed[256];
42 volatile int                            keyd_time_when_last_pressed;
43
44 typedef struct keyboard {
45         unsigned short          keybuffer[KEY_BUFFER_SIZE];
46         fix                                     time_pressed[KEY_BUFFER_SIZE];
47         fix                                     TimeKeyWentDown[256];
48         fix                                     TimeKeyHeldDown[256];
49         unsigned int            NumDowns[256];
50         unsigned int            NumUps[256];
51         unsigned int            keyhead, keytail;
52         unsigned char           E0Flag;
53         unsigned char           E1Flag;
54         int                                     in_key_handler;
55         void (__interrupt __far *prev_int_9)();
56 } keyboard;
57
58 static volatile keyboard key_data;
59
60 static unsigned char Installed=0;
61
62 unsigned char ascii_table[128] = 
63 { 255, 255, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=',255,255,
64   'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 255, 255,
65   'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', 39, '`',
66   255, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 255,'*',
67   255, ' ', 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255,255,
68   255, 255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
69   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
70   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
71   255,255,255,255,255,255,255,255 };
72
73 unsigned char shifted_ascii_table[128] = 
74 { 255, 255, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+',255,255,
75   'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 255, 255,
76   'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 
77   255, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 255,255,
78   255, ' ', 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255,255,
79   255, 255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
80   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
81   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
82   255,255,255,255,255,255,255,255 };
83
84
85 extern char key_to_ascii(int keycode )
86 {
87         int shifted;
88
89         shifted = keycode & KEY_SHIFTED;
90         keycode &= 0xFF;
91
92         if ( keycode>=127 )
93                 return 255;
94
95         if (shifted)
96                 return shifted_ascii_table[keycode];
97         else
98                 return ascii_table[keycode];
99 }
100
101
102 void key_putkey (unsigned short keycode)
103  {
104   // this function simulates a key stroke entered
105   char temp;
106   
107
108   temp = key_data.keytail+1;
109   if ( temp >= KEY_BUFFER_SIZE ) temp=0;
110   if (temp!=key_data.keyhead)   
111     {
112                 key_data.keybuffer[key_data.keytail] = keycode;
113                 key_data.keytail = temp;
114     }
115  }  
116  
117
118 void key_clear_bios_buffer_all()
119 {
120         // Clear keyboard buffer...
121         *(ushort *)0x41a=*(ushort *)0x41c;
122         // Clear the status bits...
123 //      *(ubyte *)0x417 = 0;
124 //      *(ubyte *)0x418 = 0;
125 }
126
127 void key_clear_bios_buffer()
128 {
129         // Clear keyboard buffer...
130         *(ushort *)0x41a=*(ushort *)0x41c;
131 }
132
133 void key_flush()
134 {
135         int i;
136         fix CurTime;
137
138         _disable();
139
140         // Clear the BIOS buffer
141         key_clear_bios_buffer();
142
143         key_data.keyhead = key_data.keytail = 0;
144
145         //Clear the keyboard buffer
146         for (i=0; i<KEY_BUFFER_SIZE; i++ )      {
147                 key_data.keybuffer[i] = 0;
148                 key_data.time_pressed[i] = 0;
149         }
150         
151         //Clear the keyboard array
152
153         CurTime =timer_get_fixed_secondsX();
154
155         for (i=0; i<256; i++ )  {
156                 keyd_pressed[i] = 0;
157                 key_data.TimeKeyWentDown[i] = CurTime;
158                 key_data.TimeKeyHeldDown[i] = 0;
159                 key_data.NumDowns[i]=0;
160                 key_data.NumUps[i]=0;
161         }
162         _enable();
163 }
164
165 int add_one( int n )
166 {
167         n++;
168         if ( n >= KEY_BUFFER_SIZE ) n=0;
169         return n;
170 }
171
172 // Returns 1 if character waiting... 0 otherwise
173 int key_checkch()
174 {
175         int is_one_waiting = 0;
176
177         _disable();
178
179         key_clear_bios_buffer();
180
181         if (key_data.keytail!=key_data.keyhead)
182                 is_one_waiting = 1;
183         _enable();
184         return is_one_waiting;
185 }
186
187 int key_inkey()
188 {
189         int key = 0;
190
191         _disable();
192
193         key_clear_bios_buffer();
194
195         if (key_data.keytail!=key_data.keyhead) {
196                 key = key_data.keybuffer[key_data.keyhead];
197                 key_data.keyhead = add_one(key_data.keyhead);
198         }
199         _enable();
200         return key;
201 }
202
203 int key_inkey_time(fix * time)
204 {
205         int key = 0;
206
207         _disable();
208
209         key_clear_bios_buffer();
210
211         if (key_data.keytail!=key_data.keyhead) {
212                 key = key_data.keybuffer[key_data.keyhead];
213                 *time = key_data.time_pressed[key_data.keyhead];
214                 key_data.keyhead = add_one(key_data.keyhead);
215         }
216         _enable();
217         return key;
218 }
219
220
221
222 int key_peekkey()
223 {
224         int key = 0;
225
226         _disable();
227
228         key_clear_bios_buffer();
229
230         if (key_data.keytail!=key_data.keyhead) {
231                 key = key_data.keybuffer[key_data.keyhead];
232         }
233         _enable();
234         return key;
235 }
236
237 // If not installed, uses BIOS and returns getch();
238 //      Else returns pending key (or waits for one if none waiting).
239 int key_getch()
240 {
241         int dummy=0;
242         
243         if (!Installed)
244                 return getch();
245
246         while (!key_checkch())
247                 dummy++;
248         return key_inkey();
249 }
250
251 unsigned int key_get_shift_status()
252 {
253         unsigned int shift_status = 0;
254
255         _disable();
256
257         key_clear_bios_buffer();
258
259         if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT] )
260                 shift_status |= KEY_SHIFTED;
261
262         if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT] )
263                 shift_status |= KEY_ALTED;
264
265         if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL] )
266                 shift_status |= KEY_CTRLED;
267
268 #ifndef NDEBUG
269         if (keyd_pressed[KEY_DELETE])
270                 shift_status |=KEY_DEBUGGED;
271 #endif
272
273         _enable();
274
275         return shift_status;
276 }
277
278 // Returns the number of seconds this key has been down since last call.
279 fix key_down_time(int scancode) {
280         fix time_down, time;
281
282         if ((scancode<0)|| (scancode>255)) return 0;
283
284 #ifndef NDEBUG
285         if (keyd_editor_mode && key_get_shift_status() )
286                 return 0;  
287 #endif
288
289         _disable();
290
291         if ( !keyd_pressed[scancode] )  {
292                 time_down = key_data.TimeKeyHeldDown[scancode];
293                 key_data.TimeKeyHeldDown[scancode] = 0;
294         } else  {
295                 time = timer_get_fixed_secondsX();
296                 time_down =  time - key_data.TimeKeyWentDown[scancode];
297                 key_data.TimeKeyWentDown[scancode] = time;
298         }
299         _enable();
300
301         return time_down;
302 }
303
304 // Returns number of times key has went from up to down since last call.
305 unsigned int key_down_count(int scancode)       {
306         int n;
307
308         if ((scancode<0)|| (scancode>255)) return 0;
309
310         _disable();
311         n = key_data.NumDowns[scancode];
312         key_data.NumDowns[scancode] = 0;
313         _enable();
314
315         return n;
316 }
317
318
319 // Returns number of times key has went from down to up since last call.
320 unsigned int key_up_count(int scancode) {
321         int n;
322
323         if ((scancode<0)|| (scancode>255)) return 0;
324
325         _disable();
326         n = key_data.NumUps[scancode];
327         key_data.NumUps[scancode] = 0;
328         _enable();
329
330         return n;
331 }
332
333 // Use intrinsic forms so that we stay in the locked interrup code.
334
335 void Int5();
336 #pragma aux Int5 = "int 5";
337
338 #pragma off (check_stack)
339 void __interrupt __far key_handler()
340 {
341         unsigned char scancode, breakbit, temp;
342         unsigned short keycode;
343
344 #ifndef WATCOM_10
345 #ifndef NDEBUG
346         ubyte * MONO = (ubyte *)(0x0b0000+24*80*2);
347         if (  ((MONO[0]=='D') && (MONO[2]=='B') && (MONO[4]=='G') && (MONO[6]=='>')) ||
348                         ((MONO[14]=='<') && (MONO[16]=='i') && (MONO[18]=='>') && (MONO[20]==' ') && (MONO[22]=='-')) ||
349                         ((MONO[0]==200 ) && (MONO[2]==27) && (MONO[4]==17) )
350                 )
351                 _chain_intr( key_data.prev_int_9 );
352 #endif
353 #endif
354
355         // Read in scancode
356         scancode = inp( 0x60 );
357
358         switch( scancode )      {
359         case 0xE0:
360                 key_data.E0Flag = 0x80;
361                 break;
362         default:
363                 // Parse scancode and break bit
364                 if (key_data.E1Flag > 0 )       {               // Special code for Pause, which is E1 1D 45 E1 9D C5
365                         key_data.E1Flag--;
366                         if ( scancode == 0x1D ) {
367                                 scancode        = KEY_PAUSE;
368                                 breakbit        = 0;
369                         } else if ( scancode == 0x9d ) {
370                                 scancode        = KEY_PAUSE;
371                                 breakbit        = 1;
372                         } else {
373                                 break;          // skip this keycode
374                         }
375                 } else if ( scancode==0xE1 )    {
376                         key_data.E1Flag = 2;
377                         break;
378                 } else {
379                         breakbit        = scancode & 0x80;              // Get make/break bit
380                         scancode &= 0x7f;                                               // Strip make/break bit off of scancode
381                         scancode |= key_data.E0Flag;                                    // Add in extended key code
382                 }
383                 key_data.E0Flag = 0;                                                            // Clear extended key code
384
385                 if (breakbit)   {
386                         // Key going up
387                         keyd_last_released = scancode;
388                         keyd_pressed[scancode] = 0;
389                         key_data.NumUps[scancode]++;
390                         temp = 0;
391                         temp |= keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT];
392                         temp |= keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT];
393                         temp |= keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL];
394 #ifndef NDEBUG
395                         temp |= keyd_pressed[KEY_DELETE];
396                         if ( !(keyd_editor_mode && temp) )
397 #endif          // NOTICE LINK TO ABOVE IF!!!!
398                                 key_data.TimeKeyHeldDown[scancode] += timer_get_fixed_secondsX() - key_data.TimeKeyWentDown[scancode];
399                 } else {
400                         // Key going down
401                         keyd_last_pressed = scancode;
402                         keyd_time_when_last_pressed = timer_get_fixed_secondsX();
403                         if (!keyd_pressed[scancode])    {
404                                 // First time down
405                                 key_data.TimeKeyWentDown[scancode] = timer_get_fixed_secondsX();
406                                 keyd_pressed[scancode] = 1;
407                                 key_data.NumDowns[scancode]++;
408 #ifndef NDEBUG
409                                 if ( (keyd_pressed[KEY_LSHIFT]) && (scancode == KEY_BACKSP) )   {
410                                         keyd_pressed[KEY_LSHIFT] = 0;
411                                         Int5();
412                                 }
413 #endif
414                         } else if (!keyd_repeat) {
415                                 // Don't buffer repeating key if repeat mode is off
416                                 scancode = 0xAA;                
417                         } 
418
419                         if ( scancode!=0xAA ) {
420                                 keycode = scancode;
421
422                                 if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT] )
423                                         keycode |= KEY_SHIFTED;
424
425                                 if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT] )
426                                         keycode |= KEY_ALTED;
427
428                                 if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL] )
429                                         keycode |= KEY_CTRLED;
430
431 #ifndef NDEBUG
432                                 if ( keyd_pressed[KEY_DELETE] )
433                                         keycode |= KEY_DEBUGGED;
434 #endif
435
436                                 temp = key_data.keytail+1;
437                                 if ( temp >= KEY_BUFFER_SIZE ) temp=0;
438
439                                 if (temp!=key_data.keyhead)     {
440                                         key_data.keybuffer[key_data.keytail] = keycode;
441                                         key_data.time_pressed[key_data.keytail] = keyd_time_when_last_pressed;
442                                         key_data.keytail = temp;
443                                 }
444                         }
445                 }
446         }
447
448 #ifndef NDEBUG
449 #ifdef PASS_KEYS_TO_BIOS
450         _chain_intr( key_data.prev_int_9 );
451 #endif
452 #endif
453
454         temp = inp(0x61);               // Get current port 61h state
455         temp |= 0x80;                   // Turn on bit 7 to signal clear keybrd
456         outp( 0x61, temp );     // Send to port
457         temp &= 0x7f;                   // Turn off bit 7 to signal break
458         outp( 0x61, temp );     // Send to port
459         outp( 0x20, 0x20 );     // Reset interrupt controller
460 }
461
462 #pragma on (check_stack)
463
464 void key_handler_end()  {               // Dummy function to help calculate size of keyboard handler function
465 }
466
467 ubyte Status1,Status2;
468
469 void key_init()
470 {
471         // Initialize queue
472
473         Status1= *(ubyte*)0x417;
474         Status2= *(ubyte*)0x418;
475  
476         keyd_time_when_last_pressed = timer_get_fixed_seconds();
477         keyd_buffer_type = 1;
478         keyd_repeat = 1;
479         key_data.in_key_handler = 0;
480         key_data.E0Flag = 0;
481         key_data.E1Flag = 0;
482
483         // Clear the keyboard array
484         key_flush();
485
486         if (Installed) return;
487         Installed = 1;
488
489         //--------------- lock everything for the virtal memory ----------------------------------
490         if (!dpmi_lock_region ((void near *)key_handler, (char *)key_handler_end - (char near *)key_handler))   {
491                 Error( "Can't lock keyboard handler!\n" );
492         }
493         if (!dpmi_lock_region (&key_data, sizeof(keyboard)))    {
494                 Error( "Can't lock keyboard handler's data!\n" );
495         }
496         if (!dpmi_lock_region (&keyd_buffer_type, sizeof(char)))        {
497                 Error( "Can't lock keyboard handler's data!\n" );
498         }
499         if (!dpmi_lock_region (&keyd_repeat, sizeof(char)))     {
500                 Error( "Can't lock keyboard handler's data!\n" );
501         }
502         if (!dpmi_lock_region (&keyd_editor_mode, sizeof(char)))        {
503                 Error( "Can't lock keyboard handler's data!\n" );
504         }
505         if (!dpmi_lock_region (&keyd_last_pressed, sizeof(char)))       {
506                 Error( "Can't lock keyboard handler's data!\n" );
507         }
508         if (!dpmi_lock_region (&keyd_last_released, sizeof(char)))      {
509                 Error( "Can't lock keyboard handler's data!\n" );
510         }
511         if (!dpmi_lock_region (&keyd_pressed, sizeof(char)*256))        {
512                 Error( "Can't lock keyboard handler's data!\n" );
513         }
514         if (!dpmi_lock_region (&keyd_time_when_last_pressed, sizeof(int)))      {
515                 Error( "Can't lock keyboard handler's data!\n" );
516         }
517
518         key_data.prev_int_9 = _dos_getvect( 9 );
519         _dos_setvect( 9, key_handler );
520
521         atexit( key_close );
522 }
523
524 void key_close()
525 {
526         if (!Installed) return;
527         Installed = 0;
528         
529         _dos_setvect( 9, key_data.prev_int_9 );
530
531         _disable();
532         key_clear_bios_buffer_all();
533         _enable();
534   
535         *(ubyte*)0x417=Status1;
536         *(ubyte*)0x418=Status2;
537 }