replaced by maths.h
[btb/d2x.git] / unused / bios / oldkey.asm
1 ; THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
2 ; SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
3 ; END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
4 ; ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
5 ; IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
6 ; SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
7 ; FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
8 ; CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
9 ; AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
10 ; COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
11 ; $Log: not supported by cvs2svn $
12 ; Revision 1.2  1994/02/17  15:55:59  john
13 ; Initial version
14
15 ; Revision 1.20  1994/01/18  10:58:55  john
16 ; *** empty log message ***
17
18 ; Revision 1.19  1993/12/22  13:28:40  john
19 ; Added back changes Matt made in r1.14
20
21 ; Revision 1.18  1993/12/22  13:18:32  john
22 ; *** empty log message ***
23
24 ; Revision 1.17  1993/12/20  16:48:47  john
25 ; Put cli/sti around clear keybuffer in key_close
26
27 ; Revision 1.16  1993/12/20  15:39:13  john
28 ; Tried to neaten handler code... also, moved some cli's and sti's around
29 ; trying to find bug.  Made the code call key_get_milliseconds instead
30 ; of timer_get_milliseconds, because we don't want the cli and sti
31 ; stuff in the interrupt handler.  
32
33 ; Revision 1.15  1993/12/02  10:54:48  john
34 ; Made the Ctrl,Shift,Alt keys buffer like all the other keys.
35
36 ; Revision 1.14  1993/10/29  11:25:18  matt
37 ; Made key_down_time() not accumulate time if shift,alt,ctrl down
38
39 ; Revision 1.13  1993/10/29  10:47:00  john
40 ; *** empty log message ***
41
42 ; Revision 1.12  1993/10/16  19:24:16  matt
43 ; Added new function key_clear_times() & key_clear_counts()
44
45 ; Revision 1.11  1993/10/15  10:16:49  john
46 ; bunch of stuff, mainly with detecting debugger.
47
48 ; Revision 1.10  1993/10/04  13:25:57  john
49 ; Changed the way extended keys are processed.
50
51 ; Revision 1.9  1993/09/28  11:35:32  john
52 ; added key_peekkey
53
54 ; Revision 1.8  1993/09/23  18:09:23  john
55 ; fixed bug checking for DBG
56
57 ; Revision 1.7  1993/09/23  17:28:01  john
58 ; made debug check look for DBG> instead of CONTROL
59
60 ; Revision 1.6  1993/09/20  17:08:19  john
61 ; Made so that keys pressed in debugger don't get passed through to
62 ; the keyboard handler. I also discovered, but didn't fix a error
63 ; (page fault) caused by jumping back and forth between the debugger
64 ; and the program...
65
66 ; Revision 1.5  1993/09/17  09:58:12  john
67 ; Added checks for already installed, not installed, etc.
68
69 ; Revision 1.4  1993/09/15  17:28:00  john
70 ; Fixed bug in FlushBuffer that used CX before a REP instead of ECX.
71
72 ; Revision 1.3  1993/09/08  14:48:00  john
73 ; made getch() return an int instead of a char that has shift states, etc.
74
75 ; Revision 1.2  1993/07/22  13:12:23  john
76 ; fixed comment
77 ; ,.
78
79 ; Revision 1.1  1993/07/10  13:10:42  matt
80 ; Initial revision
81
82 ;
83 ;
84
85 ;***************************************************************************
86 ;***************************************************************************
87 ;*****                                                                 *****
88 ;*****                                                                 *****
89 ;*****                        K E Y . A S M                            *****
90 ;*****                                                                 *****
91 ;***** Contains routines to get, buffer, and check key presses.        *****
92 ;*****                                                                 *****
93 ;*****                                                                 *****
94 ;***** PROCEDURES                                                      *****
95 ;*****                                                                 *****
96 ;***** key_init()  - Activates the keyboard package.                   *****
97 ;***** key_close() - Deactivates the keyboard package.                 *****
98 ;***** key_check() - Returns 1 if a buffered key is waiting.           *****
99 ;***** key_getch() - Waits for and returns a buffered keypress.        *****
100 ;***** key_flush() - Clears buffers and state array.                   *****
101 ;***** key_time() - Index by scan code. Contains the time key has been *****
102 ;*****             held down. NOT DONE YET.                            *****
103 ;*****                                                                 *****
104 ;*****                                                                 *****
105 ;***** VARIABLES                                                       *****
106 ;*****                                                                 *****
107 ;***** keyd_buffer_type -Set to 0 and key_getch() always returns 0.    *****
108 ;*****                  Set to 1 to so that ASCII codes are returned   *****
109 ;*****                  by key_getch().  Set to 2 and key_getch() returns*****
110 ;*****                  the buffered keyboard scan codes.              *****
111 ;***** keyd_repeat     - Set to 0 to not allow repeated keys in the    *****
112 ;*****                  keyboard buffer.  Set to 1 to allow repeats.   *****
113 ;***** keyd_pressed[] -Index by scan code. Contains 1 if key down else 0*****
114 ;*****                                                                 *****
115 ;*****                                                                 *****
116 ;***** CONSTANTS                                                       *****
117 ;*****                                                                 *****
118 ;***** Setting the DEBUG to 1 at compile time passes SysReq through    *****
119 ;***** to the debugger, and when the debugger is active, it will give  *****
120 ;***** the debugger any keys that are pressed.  Note that this only    *****
121 ;***** works with the Watcom VIDEO debugger at this time.  Setting     *****
122 ;***** DEBUG to 0 takes out all the debugging stuff.                   *****
123 ;*****                                                                 *****
124 ;***************************************************************************
125 ;***************************************************************************
126
127 DEBUG EQU 1
128 .386
129
130 ;************************************************************************
131 ;**************** FLAT MODEL DATA SEGMENT STUFF *************************
132 ;************************************************************************
133
134 _DATA   SEGMENT BYTE PUBLIC USE32 'DATA'
135
136 rcsid   db      "$Id: oldkey.asm,v 1.1.1.2 2001-01-19 03:33:50 bradleyb Exp $"
137
138 PUBLIC  _keyd_pressed     ; Must start with a _ so C can see the variable.
139
140                 _keyd_pressed   db  256 dup (?)
141
142                 keybuffer       dw  256 dup (?)     ; Use 256 so an inc wraps around
143
144                 TimeKeyWentDown dd  256 dup(0)
145                 TimeKeyHeldDown dd  256 dup(0)
146                 NumDowns        dd  256 dup(0)
147                 NumUps          dd  256 dup(0)
148
149                 MyCodeSegment   dw  ?
150
151 PUBLIC _keyd_editor_mode
152
153                 _keyd_editor_mode db 0
154
155 PUBLIC          _keyd_use_bios
156
157                 _keyd_use_bios  db 1
158
159 PUBLIC          _keyd_last_pressed
160                 _keyd_last_pressed  db 0
161 PUBLIC          _keyd_last_released
162                 _keyd_last_released db 0
163
164 PUBLIC          _keyd_dump_key_array
165                 _keyd_dump_key_array    db 0
166                 org_int_sel dw  ?
167                 org_int_off dd  ?
168
169                 interrupted_cs dw  ?
170                 interrupted_eip dd  ?
171
172                 keyhead      db  ?
173                 keytail      db  ?
174 PUBLIC  _keyd_buffer_type
175 PUBLIC  _keyd_repeat
176                 _keyd_buffer_type db  ?   ; 0=No buffer, 1=buffer ASCII, 2=buffer scans
177                 _keyd_repeat      db  ?
178
179                 E0Flag      db  0
180
181                 Installed   db  0
182
183 INCLUDE KEYS.INC
184
185
186 _DATA   ENDS
187
188 DGROUP  GROUP _DATA
189
190
191 ;************************************************************************
192 ;**************** FLAT MODEL CODE SEGMENT STUFF *************************
193 ;************************************************************************
194
195 _TEXT   SEGMENT BYTE PUBLIC USE32 'CODE'
196
197                 ASSUME  ds:_DATA
198                 ASSUME  cs:_TEXT
199
200 key_get_milliseconds:
201                 EXTERNDEF   timer_get_stamp64:NEAR
202
203                 push    ebx
204                 push    edx
205
206                 call    timer_get_stamp64
207
208                 ; Timing in milliseconds
209                 ; Can be used for up to 1000 hours
210                 shld    edx, eax, 21            ; Keep 32+11 bits
211                 shl     eax, 21
212                 mov     ebx, 2502279823         ; 2^21*1193180/1000
213                 div     ebx
214
215                 pop     edx
216                 pop     ebx
217
218                 ret
219
220 ;************************************************************************
221 ;************************************************************************
222 ;*****                                                              *****
223 ;*****                   K E Y _ T O _ A S C I I _                  *****
224 ;*****                                                              *****
225 ;************************************************************************
226 ;************************************************************************
227
228 PUBLIC  key_to_ascii_
229
230 key_to_ascii_:
231
232                 ; EAX = scancode
233                 push    ebx
234
235                 mov     bl, ah
236                 and     bl, 011111110b
237                 cmp     bl, 0
238                 jne     CantDoKey
239
240                 cmp     al, 127
241                 jae     CantDoKey
242
243                 and     ah, 01b        ; take away ctrl and alt codes
244                 shl     al, 1
245                 shr     eax, 1
246                 and     eax, 0ffh
247                 mov     al, byte ptr key1[eax]
248                 pop     ebx
249                 ret
250
251 CantDoKey:
252                 pop     ebx
253                 mov     eax, 255
254                 ret
255
256
257 public key_clear_times_,key_clear_counts_
258
259 ;clear the array of key down times.
260 key_clear_times_:       
261         cli
262         push    eax
263         push    ecx
264         push    edi
265         xor     eax,eax
266         mov     ecx,256
267         lea     edi,TimeKeyHeldDown
268         rep     stosd   ;clear array
269         pop     edi
270         pop     ecx
271         pop     eax
272         sti
273         ret
274
275 ;clear the arrays of key down counts
276 key_clear_counts_:      
277         cli
278         push    eax
279         push    ecx
280         push    edi
281         xor     eax,eax
282         mov     ecx,256
283         lea     edi,NumDowns
284         rep     stosd   ;clear array
285         mov     ecx,256
286         lea     edi,NumUps
287         rep     stosd   ;clear array
288         pop     edi
289         pop     ecx
290         pop     eax
291         sti
292         ret
293
294
295 PUBLIC  key_down_time_
296
297 key_down_time_:
298                 cli
299
300                 push    edx
301                 push    ecx
302                 push    ebx
303
304
305                 mov     ebx, eax
306                 xor     eax, eax
307
308                 cmp     _keyd_pressed[ebx], 0
309                 je      NotPressed
310
311                 
312                 cmp     _keyd_editor_mode, 0
313                 je      read_time
314
315                 call    get_modifiers   ;shift,alt,ctrl?
316                 or      ah,ah
317                 jz      read_time
318                 xor     eax,eax
319                 jmp     NotPressed
320
321 read_time:      mov     ecx, TimeKeyWentDown[ebx*4]
322                 call    key_get_milliseconds
323                 mov     TimeKeyWentDown[ebx*4], eax
324                 sub     eax, ecx        ; EAX = time held since last
325
326 NotPressed:
327                 add     eax, TimeKeyHeldDown[ebx*4]
328                 mov     TimeKeyHeldDown[ebx*4], 0
329
330                 pop     ebx
331                 pop     ecx
332                 pop     edx
333                 sti
334                 ret
335
336 PUBLIC  key_down_count_
337 key_down_count_:
338                 cli
339                 push    ebx
340                 mov     ebx, eax
341                 mov     eax, NumDowns[ebx*4]
342                 mov     NumDowns[ebx*4], 0
343                 pop     ebx
344                 sti
345                 ret
346
347 PUBLIC  key_up_count_
348 key_up_count_:
349                 cli
350                 push    ebx
351                 mov     ebx, eax
352                 mov     eax, NumUps[ebx*4]
353                 mov     NumUps[ebx*4], 0
354                 pop     ebx
355                 sti
356                 ret
357
358
359
360 ;************************************************************************
361 ;************************************************************************
362 ;*****                                                              *****
363 ;*****                   K E Y _ F L U S H                          *****
364 ;*****                                                              *****
365 ;************************************************************************
366 ;************************************************************************
367
368 PUBLIC  key_flush_
369
370 key_flush_:
371                 cli
372
373                 push    eax
374                 push    ecx
375                 push    edi
376
377                 mov     keyhead,0
378                 mov     keytail,255
379                 mov     E0Flag, 0
380
381                 ; Clear the keyboard array
382                 mov     edi, offset _keyd_pressed
383                 mov     ecx, 32
384                 mov     eax,0
385                 rep     stosd
386
387                 pop     edi
388                 pop     ecx
389                 pop     eax
390                 sti
391                 ret
392
393 ;************************************************************************
394 ;************************************************************************
395 ;*****                                                              *****
396 ;*****                   K E Y _ I N I T                            *****
397 ;*****                                                              *****
398 ;************************************************************************
399 ;************************************************************************
400
401 PUBLIC  key_init_
402
403 key_init_:
404                 push    eax
405                 push    ebx
406                 push    ds
407                 push    es
408
409                 ;**************************************************************
410                 ;******************* INITIALIZE key QUEUE **********************
411                 ;**************************************************************
412
413                 mov     _keyd_buffer_type,1
414                 mov     _keyd_repeat,1
415                 mov     E0Flag, 0
416
417                 ; Clear the keyboard array
418                 call    key_flush_
419
420                 cmp     Installed, 0
421                 jne     AlreadyInstalled
422
423                 ;**************************************************************
424                 ;******************* SAVE OLD INT9 HANDLER ********************
425                 ;**************************************************************
426
427                 mov     Installed, 1
428
429                 mov     eax, 03509h             ; DOS Get Vector 09h
430                 int     21h                     ; Call DOS
431                 mov     org_int_sel, es         ; Save old interrupt selector
432                 mov     org_int_off, ebx        ; Save old interrupt offset
433
434
435                 ;**************************************************************
436                 ;***************** INSTALL NEW INT9 HANDLER *******************
437                 ;**************************************************************
438
439                 mov     eax, 02509h             ; DOS Set Vector 09h
440                 mov     edx, offset key_handler  ; Point DS:EDX to new handler
441                 mov     bx, cs
442                 mov     MyCodeSegment, bx
443                 mov     ds, bx
444                 int     21h
445
446
447 AlreadyInstalled:
448
449                 pop     es
450                 pop     ds
451                 pop     ebx
452                 pop     eax
453
454                 ret
455
456
457 ;************************************************************************
458 ;************************************************************************
459 ;*****                                                              *****
460 ;*****                   K E Y _ C L O S E _                          *****
461 ;*****                                                              *****
462 ;************************************************************************
463 ;************************************************************************
464
465 PUBLIC  key_close_
466
467 key_close_:
468                 push    eax
469                 push    ebx
470                 push    edx
471                 push    ds
472
473
474                 cmp     Installed, 0
475                 je      @f
476
477                 ;**************************************************************
478                 ;***************** RESTORE OLD INT9 HANDLER *******************
479                 ;**************************************************************
480
481                 mov     Installed, 0
482
483                 ; Clear the BIOS buffer
484                 cli
485                 mov     ebx, 041ch
486                 mov     al, byte ptr [ebx]
487                 mov     ebx, 041ah
488                 mov     byte ptr [ebx], al
489                 sti
490
491                 mov     eax, 02509h         ; DOS Set Vector 09h
492                 mov     edx, org_int_off
493                 mov     ds, org_int_sel
494                 int     21h
495
496 @@:             pop     ds
497                 pop     edx
498                 pop     ebx
499                 pop     eax
500
501                 ret
502
503 ;************************************************************************
504 ;************************************************************************
505 ;*****                                                              *****
506 ;*****                   K E Y _ C H E C K _                          *****
507 ;*****                                                              *****
508 ;************************************************************************
509 ;************************************************************************
510
511 PUBLIC  key_checkch_       ; Must end with a _ so C can see the function.
512
513 key_checkch_:
514                 cli
515                 push    ebx
516
517                 xor     eax, eax
518                 cmp     Installed, 0
519                 je      NoKey
520
521                 mov     bl, keytail
522                 inc     bl
523                 cmp     bl, keyhead
524                 je      Nokey
525                 mov     eax, 1
526 Nokey:
527                 pop     ebx
528                 sti
529                 ret
530
531 ;************************************************************************
532 ;************************************************************************
533 ;*****                                                              *****
534 ;*****                 K E Y _ D E B U G                              *****
535 ;*****                                                              *****
536 ;************************************************************************
537 ;************************************************************************
538
539 PUBLIC  key_debug_
540 key_debug_:
541                 int 3h
542                 ret
543
544
545 ;************************************************************************
546 ;************************************************************************
547 ;*****                                                              *****
548 ;*****                   K E Y _ G E T C H _                        *****
549 ;*****                                                              *****
550 ;************************************************************************
551 ;************************************************************************
552
553 PUBLIC  key_getch_       ; Must end with a _ so C can see the function.
554
555 key_getch_:
556                 push    ebx
557
558                 xor     eax, eax
559                 xor     ebx, ebx
560                 cmp     Installed, 0
561                 jne     StillNoKey
562                 pop     ebx
563                 ret
564
565 StillNoKey:
566                 cli             ; Critical section
567                 mov     bl, keytail
568                 inc     bl
569                 cmp     bl, keyhead
570                 sti
571                 je      StillNoKey
572
573                 cli             ; Critical section
574                 xor     ebx, ebx
575                 mov     bl, keyhead
576                 mov     ax, word ptr keybuffer[ebx*2]
577                 inc     BYTE PTR keyhead
578                 sti
579
580                 pop     ebx
581                 ret
582
583
584 ;************************************************************************
585 ;************************************************************************
586 ;*****                                                              *****
587 ;*****                   K E Y _ I N K E Y _                        *****
588 ;*****                                                              *****
589 ;************************************************************************
590 ;************************************************************************
591
592 PUBLIC  key_inkey_       ; Must end with a _ so C can see the function.
593
594 key_inkey_:
595                 push    ebx
596
597                 xor     eax, eax
598                 xor     ebx, ebx
599
600                 cmp     Installed, 0
601                 je      NoInkey
602
603                 cli             ; Critical section
604                 mov     bl, keytail
605                 inc     bl
606                 cmp     bl, keyhead
607                 sti
608                 je      NoInkey
609
610                 cli             ; Critical section
611                 mov     bl, keyhead
612                 mov     ax, word ptr keybuffer[ebx*2]
613                 inc     BYTE PTR keyhead
614                 sti
615 NoInkey:
616                 pop     ebx
617                 ret
618
619 PUBLIC  key_peekkey_       ; Must end with a _ so C can see the function.
620
621 key_peekkey_:
622                 push    ebx
623
624                 xor     eax, eax
625                 xor     ebx, ebx
626
627                 cli             ; Critical section
628
629                 cmp     Installed, 0
630                 je      NoPeek
631                 mov     bl, keytail
632                 inc     bl
633                 cmp     bl, keyhead
634                 je      NoPeek
635                 mov     bl, keyhead
636                 mov     ax, word ptr keybuffer[ebx*2]
637                 
638 NoPeek:         sti
639                 pop     ebx
640                 ret
641
642
643
644 ;************************************************************************
645 ;************************************************************************
646 ;*****                                                              *****
647 ;*****                   K E Y _ H A N D L E R                      *****
648 ;*****                                                              *****
649 ;************************************************************************
650 ;************************************************************************
651
652 PUBLIC  key_handler      ; Must end with a _ so C can see the function.
653
654 key_handler:
655
656                 pushfd              ; Save flags in case we have to chain to original
657                 push    eax
658                 push    ebx
659                 push    ecx
660                 push    edx
661                 push    ds
662
663                 mov     ax, DGROUP  ; Point to our data segment, since this is an
664                 mov     ds, ax      ; interrupt and we don't know where we were.
665
666                 mov     eax, (0b0000h+76*2)
667                 mov     byte ptr [eax], '1'
668
669 IFDEF DEBUG
670                 call    CheckForDebugger
671                 jnc     @f
672                 mov eax, 0b0000h+78*2
673                 mov byte ptr [eax], 'D'
674                 jmp      PassToBios      ; If debugger is active, then skip buffer
675
676 @@:             mov eax, 0b0000h+78*2
677                 mov byte ptr [eax], 'I'
678
679                 ; Clear the BIOS buffer
680                 ;**mov     ebx, 041ch
681                 ;**mov     al, byte ptr [ebx]
682                 ;**mov     ebx, 041ah
683                 ;**mov     byte ptr [ebx], al
684 ENDIF
685
686                 xor     eax, eax
687                 xor     ebx, ebx
688
689                 in      al, 060h                ; Get scan code from keyboard
690         
691                 cmp     al, 0E0h
692                 jne     NotE0Code
693
694 E0Code:         mov     E0Flag, 010000000b
695                 jmp     LeaveHandler            ; If garbage key, then don't buffer it
696
697 NotE0Code:      mov     bl, al                  ; Put break bit into bl ; 0 = pressed, 1=released
698                 and     al, 01111111b           ; AL = scancode
699                 or      al, E0Flag              ; AL = extended scancode
700                 mov     E0Flag,0                ; clear E0 flag
701                 cmp     al, 029h
702                 je      pause_execution
703                 shl     bl, 1                   ; put upper bit into carry flag
704                 jc      key_mark_released       ; if upper bit of bl was set, then it was a release code
705
706 ;**************************************************************
707 ;****************** HANDLE A NEWLY PRESSED KEY ****************
708 ;**************************************************************
709 ;Marks the key press in EAX in the scancode array.
710
711 key_mark_pressed:
712                 ;cmp    al, 0eh ; backspace
713                 ;je     pause_execution
714                 
715                 mov     _keyd_last_pressed, al
716                 ; Check if the key is repeating or if it just got pressed.
717                 cmp     byte ptr _keyd_pressed[eax], 1
718                 je      AlreadyDown
719
720 ;------------------------------- Code for a key pressed for the first time ------------------------
721                 mov     byte ptr _keyd_pressed[eax], 1  
722                 ; Set the time
723
724                 push    edx
725                 push    eax
726                 call    key_get_milliseconds
727                 mov     edx, eax
728                 pop     eax
729                 mov     TimeKeyWentDown[eax*4], edx
730                 pop     edx
731
732                 inc     NumDowns[eax*4]
733
734                 jmp     BufferAX
735
736 ;------------------------------- Code for a key that is already pressed ------------------------
737 AlreadyDown:
738                 cmp     _keyd_repeat, 0
739                 je      DoneMarkingPressed
740
741 BufferAX:
742         cmp     _keyd_buffer_type, 0
743         je      SkipBuffer          ; Buffer = 0 means don't buffer anything.
744
745         cmp     al, 0AAh        ; garbage key
746         je      SkipBuffer
747
748         call    get_modifiers   ;returns ah
749         
750         xor     ebx, ebx
751         mov     bl, keytail
752         inc     bl
753         inc     bl
754
755         ; If the buffer is full then don't buffer this key
756         cmp     bl, keyhead
757         je      SkipBuffer
758         dec     bl
759
760         mov     word ptr keybuffer[ebx*2], ax
761         mov     keytail, bl
762
763 SkipBuffer:     
764                 
765 ;---------------------------------- Exit function -----------------------------
766 DoneMarkingPressed:
767         jmp     LeaveHandler
768
769 ;**************************************************************
770 ;******************* HANDLE A RELEASED KEY ********************
771 ;**************************************************************
772 ; Unmarks the key press in EAX from the scancode array.
773 key_mark_released:
774
775                 mov     _keyd_last_released, al
776                 mov     byte ptr _keyd_pressed[eax], 0
777                 inc     NumUps[eax*4]
778
779                 cmp     _keyd_editor_mode, 0
780                 je      NotInEditorMode
781                 push    eax
782                 xor     ah,ah
783                 call    get_modifiers
784                 or      ah,ah   ;check modifiers
785                 pop     eax
786                 jnz     skip_time
787
788 NotInEditorMode:        
789                 push    eax
790
791                 call    timer_get_stamp64
792
793                 ; Timing in milliseconds
794                 ; Can be used for up to 1000 hours
795                 shld    edx, eax, 21            ; Keep 32+11 bits
796                 shl     eax, 21
797                 mov     ebx, 2502279823         ; 2^21*1193180/1000
798                 div     ebx
799
800                 mov     edx, eax
801                 pop     eax
802                 sub     edx, TimeKeyWentDown[eax*4]
803                 add     TimeKeyHeldDown[eax*4], edx
804
805 skip_time:      ;**jmp  LeaveHandler
806
807 ;**************************************************************
808 ;*************** FINISH UP THE KEYBOARD INTERRUPT *************
809 ;**************************************************************
810 LeaveHandler:
811                 mov     eax, (0b0000h+76*2)
812                 mov     byte ptr [eax], '2'
813
814 ;;              cmp     _keyd_dump_key_array, 0
815 ;;              je      DontPassToBios
816                 jmp     PassToBios
817
818                 mov     ecx, 256
819                 mov     ebx, 0
820
821 showdown:       mov     al, _keyd_pressed[ebx]
822                 add     al, '0'
823                 mov     [ebx*2+ 0b0000h], al
824                 inc     ebx
825                 loop    showdown
826
827                 mov     eax, 0b0000h
828                 mov     byte ptr [ eax+(036h*2+1) ], 070h
829                 mov     byte ptr [ eax+(02Ah*2+1) ], 070h
830                 mov     byte ptr [ eax+(038h*2+1) ], 070h
831                 mov     byte ptr [ eax+(0B8h*2+1) ], 070h
832                 mov     byte ptr [ eax+(01Dh*2+1) ], 070h
833                 mov     byte ptr [ eax+(09dh*2+1) ], 070h
834
835                 mov     byte ptr [ eax+(0AAh*2+1) ], 07Fh
836                 mov     byte ptr [ eax+(0E0h*2+1) ], 07Fh
837
838                 jmp     DontPassToBios
839
840
841 ; If in debugger, pass control to dos interrupt.
842
843 PassToBios:     pop     ds          ; Nothing left on stack but flags
844                 pop     edx
845                 pop     ecx
846                 pop     ebx
847                 pop     eax
848
849                 sub     esp, 8              ; Save space for IRETD frame
850                 push    ds                  ; Save registers we use.
851                 push    eax
852                 mov     ax, DGROUP
853                 mov     ds, ax              ; Set DS to our data segment
854                 mov     eax, org_int_off   ; put original handler address
855                 mov     [esp+8], eax        ;   in the IRETD frame
856                 movzx   eax, org_int_sel
857                 mov     [esp+12], eax
858                 pop     eax                 ; Restore registers
859                 pop     ds
860                 iretd                       ; Chain to previous handler
861
862 pause_execution:
863                 in      al, 61h         ; Get current port 61h state
864                 or      al, 10000000b   ; Turn on bit 7 to signal clear keybrd
865                 out     61h, al         ; Send to port
866                 and     al, 01111111b   ; Turn off bit 7 to signal break
867                 out     61h, al         ; Send to port
868                 mov     al, 20h         ; Reset interrupt controller
869                 out     20h, al
870                 sti                     ; Reenable interrupts
871                 pop     ds
872                 pop     edx             ; Restore all of the saved registers.
873                 pop     ecx
874                 pop     ebx
875                 pop     eax
876
877                 sub     esp, 8              ; Save space for IRETD frame
878                 push    ds                  ; Save registers we use.
879                 push    eax
880                 mov     ax, DGROUP
881                 mov     ds, ax              ; Set DS to our data segment
882                 mov     eax, org_int_off   ; put original handler address
883                 mov     [esp+8], eax        ;   in the IRETD frame
884                 movzx   eax, org_int_sel
885                 mov     [esp+12], eax
886                 pop     eax                 ; Restore registers
887                 pop     ds
888
889                 iretd                   ; Interrupt must return with IRETD
890
891 DontPassToBios: 
892
893 ; Resets the keyboard, PIC, restores stack, returns.
894                 in      al, 61h         ; Get current port 61h state
895                 or      al, 10000000b   ; Turn on bit 7 to signal clear keybrd
896                 out     61h, al         ; Send to port
897                 and     al, 01111111b   ; Turn off bit 7 to signal break
898                 out     61h, al         ; Send to port
899                 mov     al, 20h         ; Reset interrupt controller
900                 out     20h, al
901                 sti                     ; Reenable interrupts
902                 pop     ds
903                 pop     edx             ; Restore all of the saved registers.
904                 pop     ecx
905                 pop     ebx
906                 pop     eax
907                 popfd
908                 iretd               ; Interrupt must return with IRETD
909
910 ;returns ah=bitmask of shift,ctrl,alt keys
911 get_modifiers:          push    ecx
912
913                 xor     ah,ah
914
915                 ; Check the shift keys
916                 mov     cl, _keyd_pressed[ 036h ]
917                 or      cl, _keyd_pressed[ 02ah ]
918                 or      ah, cl
919
920                 ; Check the alt key
921                 mov     cl, _keyd_pressed[ 038h ]
922                 or      cl, _keyd_pressed[ 0b8h ]
923                 shl     cl, 1
924                 or      ah, cl
925
926                 ; Check the ctrl key
927                 mov     cl, _keyd_pressed[ 01dh ]
928                 or      cl, _keyd_pressed[ 09dh ]
929                 shl     cl, 2
930                 or      ah, cl
931
932                 pop     ecx
933                 ret
934
935 IFDEF DEBUG
936 CheckForDebugger:
937         ; Returns CF=0 if debugger isn't active
938         ;         CF=1 if debugger is active
939
940                 ;*************************** DEBUG ******************************
941                 ; When we're in the VIDEO debugger, we want to pass control to
942                 ; the original interrupt.  So, to tell if the debugger is active,
943                 ; I check if video page 1 is the active page since that is what
944                 ; page the debugger uses, and if that works, I check the top of
945                 ; the screen to see if the texxt "Control" is there, which should
946                 ; only be there when we're in the debugger.
947
948         
949
950                 push    eax
951                 ;mov     eax, 0462h          ; Address 0462 stores BIOS current page
952                 ;cmp     BYTE PTR [eax], 1
953                 ;jne     NoDebuggerOnColor
954                 ;mov     eax, 0b8000h+4096   ; 4096 = offset to 2nd video mem page
955                 ;cmp     BYTE PTR [eax+2],'C'
956                 ;jne     NoDebuggerOnColor
957                 ;cmp     BYTE PTR [eax+4],'o'
958                 ;jne     NoDebuggerOnColor
959                 ;cmp     BYTE PTR [eax+6],'n'
960                 ;jne     NoDebuggerOnColor
961                 ;cmp     BYTE PTR [eax+8],'t'
962                 ;jne     NoDebuggerOnColor
963                 ;cmp     BYTE PTR [eax+10],'r'
964                 ;jne     NoDebuggerOnColor
965                 ;cmp     BYTE PTR [eax+12],'o'
966                 ;jne     NoDebuggerOnColor
967                 ;cmp     BYTE PTR [eax+14],'l'
968                 ;jne     NoDebuggerOnColor
969                 ;jmp     ActiveDebugger
970                 ;NoDebuggerOnColor:
971                 ; First, see if there is a mono debugger...
972
973                 ;mov     eax, 0b0000h        ; 4096 = offset to mono video mem
974                 ;cmp     BYTE PTR [eax+2],'C'
975                 ;jne     NoActiveDebugger
976                 ;cmp     BYTE PTR [eax+4],'o'
977                 ;jne     NoActiveDebugger
978                 ;cmp     BYTE PTR [eax+6],'n'
979                 ;jne     NoActiveDebugger
980                 ;cmp     BYTE PTR [eax+8],'t'
981                 ;jne     NoActiveDebugger
982                 ;cmp     BYTE PTR [eax+10],'r'
983                 ;jne     NoActiveDebugger
984                 ;cmp     BYTE PTR [eax+12],'o'
985                 ;jne     NoActiveDebugger
986                 ;cmp     BYTE PTR [eax+14],'l'
987                 ;jne     NoActiveDebugger
988
989                 mov     eax, 0b0000h        ; 4096 = offset to mono video mem
990                 add     eax, 24*80*2
991
992
993                 cmp     BYTE PTR [eax+0],'D'
994                 jne     NextTest
995                 cmp     BYTE PTR [eax+2],'B'
996                 jne     NextTest
997                 cmp     BYTE PTR [eax+4],'G'
998                 jne     NextTest
999                 cmp     BYTE PTR [eax+6],'>'
1000                 jne     NextTest
1001
1002                 ;Found DBG>, so consider debugger active:
1003                 jmp     ActiveDebugger
1004
1005 NextTest:
1006                 cmp     BYTE PTR [eax+14],'<'
1007                 jne     NextTest1
1008                 cmp     BYTE PTR [eax+16],'i'
1009                 jne     NextTest1
1010                 cmp     BYTE PTR [eax+18],'>'
1011                 jne     NextTest1
1012                 cmp     BYTE PTR [eax+20],' '
1013                 jne     NextTest1
1014                 cmp     BYTE PTR [eax+22],'-'
1015                 jne     NextTest1
1016
1017                 ; Found <i> - , so consider debugger active:
1018                 jmp     ActiveDebugger
1019
1020 NextTest1:
1021                 cmp     BYTE PTR [eax+0], 200
1022                 jne     NextTest2
1023                 cmp     BYTE PTR [eax+2], 27
1024                 jne     NextTest2
1025                 cmp     BYTE PTR [eax+4], 17
1026                 jne     NextTest2
1027
1028                 ; Found either the help screen or view screen, so consider
1029                 ; debugger active
1030                 jmp     ActiveDebugger
1031
1032 NextTest2:
1033                 ; Now we see if its active by looking for the "Executing..."
1034                 ; text on the bottom of the mono screen
1035                 ;mov     eax, 0b0000h        ; 4096 = offset to mono video mem
1036                 ;add     eax, 24*80*2
1037                 ;cmp     BYTE PTR [eax+0],'E'
1038                 ;je      NoActiveDebugger
1039                 ;cmp     BYTE PTR [eax+2],'x'
1040                 ;je      NoActiveDebugger
1041                 ;cmp     BYTE PTR [eax+4],'e'
1042                 ;je      NoActiveDebugger
1043                 ;cmp     BYTE PTR [eax+6],'c'
1044                 ;je      NoActiveDebugger
1045
1046 NoActiveDebugger:
1047                 pop     eax
1048                 clc
1049                 ret
1050
1051 ActiveDebugger:
1052                 pop     eax
1053                 stc
1054                 ret
1055
1056 ENDIF
1057
1058 _TEXT   ENDS
1059
1060                 END