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