; ; Command & Conquer Red Alert(tm) ; Copyright 2025 Electronic Arts Inc. ; ; This program is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 3 of the License, or ; (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program. If not, see . ; ;*************************************************************************** ;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S ** ;*************************************************************************** ;* * ;* Project Name : Library * ;* * ;* File Name : KEYBOARD.ASM * ;* * ;* Programmer : Christopher Yates * ;* * ;* Start Date : May 21, 1992 * ;* * ;* Last Update : July 15, 1994 [PWG] * ;* * ;*-------------------------------------------------------------------------* ;* Functions: * ;* Get_RM_Timer_Address -- Return address of real mode code for copy. * ;* Get_RM_Keyboard_Size -- return size of real mode timer code. * ;* Check_Key -- checks queue for key (make) * ;* Check_Key_Num -- Checks if key in queue, return key num * ;* Get_Key_Num -- Returns the next key num in ax * ;* KN_To_KA -- Translates a key num to an ASCII key * ;* Low_Get_Key -- low level get key returns key num and bits * ;* Convert_Num_To_ASCII -- Assembly routine converts keynum to ASCII key * ;* KeyNum_Translate -- Performs a lowlevel xlate to a keycode * ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ;* ;* Keyboard driver -- 80386 Protected Mode Assembly portion * ;* updated by: Phil Gorrow for 32 bit Protected Mode ;*************************************************************************** ; ; ---------------------------------------------------------------- IDEAL ; the product runs in ideal mode P386 ; use 386 real mode instructions MODEL USE32 FLAT LOCALS ?? ; ?? is the symbol for a local ;WARN ; generate all warnings we can JUMPS ; optimize jumps if possible ;--------------------------------------------------------------------------- ; Make some general equates for easy compatability ;--------------------------------------------------------------------------- PROT_INT_ENABLE EQU 1 ; if false protected int just calls real mode int DPMI_INTR EQU 31h IRQ1INTNUM EQU 09h ; IRQ1 interrupt vector number. BRKINTNUM EQU 23h ; Crtl-C (Break) interrupt vector number DBGINTNUM EQU 3h ; Debug interrupt vector number DOS_SYS_CALL EQU 21h ; to do TNT DOS-XNDR system calls. LOCK_PAGES EQU 5 ; Lock pages subfunction using DX_MEM_MGT UNLOCK_PAGES EQU 6 ; Unlock pages subfunction using DX_MEM_MGT CLEARISR EQU 020H ; value to clear In Service Register INTCHIP0 EQU 020H ; 8259 interrupt chip controller 0 ;--------------------------------------------------------------------------- ; Include all of the keyboard specific defines ;--------------------------------------------------------------------------- INCLUDE "keyboard.inc" INCLUDE "keystruc.inc" INCLUDE "mcgaprim.inc" GLOBAL RealModePtr:DWORD GLOBAL Install_Keyboard_Interrupt:NEAR GLOBAL Get_RM_Keyboard_Address:Near GLOBAL Get_RM_Keyboard_Size:Near GLOBAL Remove_Keyboard_Interrupt:NEAR GLOBAL Check_Key_Num:NEAR GLOBAL Get_Key_Num:NEAR GLOBAL KN_To_KA:NEAR GLOBAL KeyNum_Translate:NEAR GLOBAL Check_Key:NEAR GLOBAL Get_Key:NEAR GLOBAL Keyboard_Attributes_On:NEAR GLOBAL Clear_KeyBuffer:NEAR GLOBAL Key_Down:NEAR GLOBAL Keyboard_Attributes_Off:NEAR GLOBAL Check_Key_Bits:NEAR GLOBAL Get_Key_Bits:NEAR GLOBAL Key_Satisfied:NEAR GLOBAL Stuff_Key_WORD:NEAR GLOBAL Stuff_Key_Num:NEAR GLOBAL MouseQX:DWORD GLOBAL MouseQY:DWORD ;DBG GLOBAL Keyboard_Interrupt:NEAR DATASEG ; For the current time we will just include the real mode stuff ; into the protected mode code and then copy it down. The C side of ; this will handle this method or reading it off of disk in the real ; method. LABEL RealBinStart BYTE include "keyireal.ibn" LABEL RealBinEnd BYTE LABEL LockedDataStart BYTE RMVector DD 0 RealModeSel DD 0 RealModePtr DD 0 ; Pointer to real mode memory. RealModeSize DD 0 ; Pointer to real mode memory. Keyboard_App_Stack_ESP DD 0 ; This the System Stack Offsset Keyboard_App_Stack_SS DD 0 ; This the System Stack Selector Keyboard_StackPointer DD 0DEADDEADh ; We Create a Local Application Keyboard_Stack DD 512 dup (0) Keyboard_StackStart DD 0 ; StackPointer LABEL LockedDataEnd BYTE Ascii DB 0,"`1234567890-=",0,8,9,"qwertyuiop[]\",0,"asdfghjkl;'" DB 0,13,0,45,"zxcvbnm,./",0,0,0,0,0," " Shift DB 0,"~!@#$%^&*()_+",0,8,9,"QWERTYUIOP{}|",0,"ASDFGHJKL:",22H DB 0,13,0,45,"ZXCVBNM<>?",0,0,0,0,0," " Alpha_Lower DB 0 DB "~!@#$%^&*()_+",0,8,9,"qwertyuiop{}|",0,"asdfghjkl:",22H DB 0,13,0,45,"zxcvbnm<>?",0,0,0,0,0," " Alpha_Shift DB 0 DB "`1234567890-=",0,8,9,"QWERTYUIOP[]\",0,"ASDFGHJKL;'" DB 0,13,0,45,"ZXCVBNM,./",0,0,0,0,0," " Edit DB 0AEH,0ADH,000H,000H,0B5H,0B9H,0B1H,000H,0B8H,0B0H,0B7H,0AFH DB 000H,000H,0B3H,000H,0B9H,0B5H,0B1H,000H, "/",0B8H,0B4H,0B0H DB 0AEH, "*",0B7H,0B3H,0AFH,0ADH, "-", "+",000H,00DH,000H NumPad DB 0,"741",0,"/8520*963.-+",0,13,0 GetKeyLock DW 0 ; snap shot of num and caps lock bits InitFlags DW 0 MouseQX DD 0 MouseQY DD 0 CODESEG ;*************************************************************************** ;* GET_RM_TIMER_ADDRESS -- Return address of real mode code for copy. * ;* * ;* INPUT: none * ;* * ;* OUTPUT: VOID * to the address of the real mode timer * ;* * ;* PROTO: VOID *Get_RM_Keyboard_Address(VOID); * ;* * ;* HISTORY: * ;* 07/06/1994 SKB : Created. * ;*=========================================================================* PROC Get_RM_Keyboard_Address C Near mov eax, OFFSET RealBinStart ret ENDP ;*************************************************************************** ;* GET_RM_KEYBOARD_SIZE -- return size of real mode timer code. * ;* * ;* INPUT: none * ;* * ;* OUTPUT: LONG size of the real mode timer code * ;* * ;* PROTO: LONG Get_RM_Keyboard_Size(VOID); ;* * ;* HISTORY: * ;* 07/06/1994 SKB : Created. * ;*=========================================================================* PROC Get_RM_Keyboard_Size C Near mov eax, OFFSET RealBinEnd - OFFSET RealBinStart ret ENDP ;*************************************************************************** ;* INSTALL_KEYBOARD_INTERRUPT -- Installs the keyboard interrupt * ;* * ;* INPUT: int rm_ptr - ptr to the real mode handler * * ;* int rm_size - size of the real mode handler * ;* * ;* OUTPUT: none * ;* * ;* PROTO: VOID Install_Keyboard_Interrupt(int rm_ptr, int rm_size); * ;* * ;* HISTORY: * ;* 07/11/1994 PWG : Created. * ;*=========================================================================* PROC Install_Keyboard_Interrupt C NEAR USES eax,ebx,ecx,edx,esi,edi ARG rm_ptr:DWORD ARG rm_size:DWORD ; Are they attempting to set timer again? cmp [RealModePtr],0 jnz ??error ; Make sure all flags are cleared. cmp [InitFlags],0 jnz ??error ; Before setting the interrupt vectors, the code needs to be locked ; for DPMI compatability. Any code or data accessed must be lockded ; so that no page faults accure during an interrupt. ; First lock the code, then the data. The stack will already be locked. ; The real mode code is also already locked be default. ; To lock a page set up registers : ; AX = 0600h ; BX:CX = starting linear address of memory block ; SI:DI = size of region mov eax,0600h ; function number. mov ecx,OFFSET LockedCodeStart ; ecx must have start of memory. mov edi,OFFSET LockedCodeEnd ; edi will have size of region in bytes. shld ebx,ecx,16 sub edi, ecx shld esi,edi,16 int DPMI_INTR ; do call. jc ??error ; eax = 8 if mem err, eax = 9 if invalid mem region. or [InitFlags],IF_LOCKED_PM_CODE mov eax,0600h ; function number. mov ecx,OFFSET LockedDataStart ; ecx must have start of memory. mov edi,OFFSET LockedDataEnd ; edi will have size of region in bytes. shld ebx,ecx,16 sub edi, ecx shld esi,edi,16 int DPMI_INTR ; do call. jc ??error ; eax = 8 if mem err, eax = 9 if invalid mem region. or [InitFlags],IF_LOCKED_PM_DATA ; now allocate real mode memory and copy the rm binary down to it. mov eax,0100h ; set function number mov ebx,[rm_size] ; get size of RM binary. mov [RealModeSize],ebx add ebx,15 ; round up shr ebx,4 ; convert to pages. int DPMI_INTR ; do call. jc ??error ; check for error. or [InitFlags],IF_ALLOC_RM ; set successful mov [RealModeSel],edx shl eax,4 ; convert segment to offset. mov [RealModePtr],eax ; save offset to global variable. ; now lock the real mode memory that we allocated mov eax,0600h ; function number. mov ecx,[RealModePtr] ; ecx must have start of memory. mov edi,[RealModeSize] ; edi will have size of region in bytes. shld ebx,ecx,16 shld esi,edi,16 int DPMI_INTR ; do call. jc ??error ; eax = 8 if mem err, eax = 9 if invalid mem region. or [InitFlags],IF_LOCKED_RM_CODE ; set up source and destination pointers for the copy. mov eax,[RealModePtr]; ; set up our dest pointer mov esi,[rm_ptr] ; Set up our source pointer. mov edi,eax ; put it into esi for copy. mov ecx,[rm_size] rep movsb ; write RM bin to RM memory. ; restore esi to point to data and initialize some of it. mov esi,[RealModePtr] mov eax,esi shl eax,12 ; make seg in high eax. mov ax,[(KeyboardType PTR esi).CallKeyRMIntOffset] ; create RM addr of call chain. mov [(KeyboardType PTR esi).CallKeyRMIntAddr],eax ; save it for use in PM int. IF NOT PROT_INT_ENABLE ; Chain the Real Keyboard interrupt to any avilable ; Interrupt vector so We make sure that the Real Mode ; Keyboard Interrupt service get called at debuging time ; of the library. mov edi , eax mov bl , 060h mov bh , 6 mov eax , 200h ??find: int DPMI_INTR jc ??error or cx,dx jz ??found inc bl dec bh jnz ??find jmp ??error ??found: movzx ebx , bl mov [ byte ptr RMVector ] , bl mov [ 4 * ebx ] , edi ENDIF ;------------------------------------------------------- ; Initialize all of the keyboard specific information ;------------------------------------------------------- xor eax,eax ; clear the high bits of eax mov al,[417H] ; get keyboard status flags test eax,040H ; caps lock active? je short ??nocap ; not active or [(KeyboardType PTR esi).KeyLock],CAPSLOCK ??nocap: test eax,020H ; num lock active? je short ??nonumlock ; not active or [(KeyboardType PTR esi).KeyLock],NUMLOCK ??nonumlock: test eax,002H ; is left shift key down? je short ??noleftshift ; try the right or [(KeyboardType PTR esi+5).KeysUpDown],010H ??noleftshift: and eax,001H ; get right shift bit shl eax,9 ; put it into the proper position (shl al,1 mov ah,al) mov al,[418H] ; get alt and ctrl bits shl al,2 ; put in proper position shl al,1 and al,00CH ; only alt and ctrl bits or ah,al ; put them ah for Keys+7 later mov al,[496H] ; get extended keys test al,008H ; check for right alt key je short ??noralt or ah,040H ??noralt: mov [(KeyboardType PTR esi+7).KeysUpDown],ah test al,004H ; test for right ctrl je short ??norctrl or [(KeyboardType PTR esi+8).KeysUpDown],001h ??norctrl: test al,002H ; last code E0? je short ??noe0 mov [(KeyboardType PTR esi).LastKeyE0],001h ??noe0: test al,001H ; last code E1? je short ??noe1 mov [(KeyboardType PTR esi).LastKeyE1],002h ??noe1: ;========================================================================== ; Get the protected mode interrupt vector keyboard. ; input ax = 0204 ; bl = number of interrupt to get ; output: cf error ; ES:EBX = address of PM int handler routine. ;========================================================================== mov eax,0204h ; Get proteced mode mov bl,IRQ1INTNUM ; IRQ1 interrupt vector int DPMI_INTR ; do call. jc ??error mov [(KeyboardType PTR esi).KeyOldPMIOffset],edx ; save offset. mov [(KeyboardType PTR esi).KeyOldPMISelector],ecx ; save selector. ;========================================================================== ; Get the real mode interrupt vector keyboard ; input ax = 2503, cl = number of interrupt to get ; output cf error, EBX = address (seg:off) of RM int handler routine. ; cl set above ;========================================================================== mov eax,0200h mov bl,IRQ1INTNUM ; IRQ1 interrupt vector int DPMI_INTR ; do call. jc ??error shl edx,16 shld ecx,edx,16 mov [(KeyboardType PTR esi).KeyOldRMI],ecx ;========================================================================== ; Now it is time to set the Protected mode interrupt Keyboard ; ax = function number (0205 ; bl = number of interrupt to set ; cx:edx = address of PM interrupt handler ;========================================================================== mov eax, 0205h mov bl,IRQ1INTNUM mov cx , cs lea edx, [Keyboard_Interrupt] ; get address of protected code int hand. int DPMI_INTR ; do call. jc ??error or [InitFlags],IF_SET_VECTORS ;========================================================================== ; Now it is time to set the real Interrupt Keyboard ; ax = function number (0201 ; bl = number of interrupt to set ; cx:dx = address of RM interrupt handler ;========================================================================== mov eax, 0201h mov bl,IRQ1INTNUM mov ecx,[RealModePtr] ; get address of real code int hand. shr ecx,4 ; put segment in hi word. mov dx,[(KeyboardType PTR esi).KeyCodeOffset] ; Get address of code int DPMI_INTR ; do call. jc ??error ;========================================================================== ; Get the protected mode interrupt vector - for the break interrupt ; input ax = 0204 ; bl = number of interrupt to get ; output: cf error ; ES:EBX = address of PM int handler routine. ;========================================================================== mov eax,0204h ; Get proteced mode mov bl,BRKINTNUM ; IRQ1 interrupt vector int DPMI_INTR ; do call. jc ??error mov [(KeyboardType PTR esi).BrkOldPMIOffset],edx ; save offset. mov [(KeyboardType PTR esi).BrkOldPMISelector],ecx ; save selector. ;========================================================================== ; Get the real mode interrupt vector - for the break interrupt ; input ax = 0200, bl = number of interrupt to get ; output cf error, EBX = address (seg:off) of RM int handler routine. ; cl set above ;========================================================================== mov eax,0200h mov bl,BRKINTNUM ; IRQ1 interrupt vector int DPMI_INTR ; do call. jc ??error shl edx,16 shld ecx,edx,16 mov [(KeyboardType PTR esi).BrkOldRMI],ecx ;========================================================================== ; Now it is time to set the Protected mode interrupt ; ax = function number (0205 ; bl = number of interrupt to set ; cx:edx = address of PM interrupt handler ;========================================================================== mov eax, 0205h mov bl,BRKINTNUM mov cx , cs lea edx, [Break_Interrupt] ; get address of protected code int hand. int DPMI_INTR ; do call. jc ??error or [InitFlags],IF_SET_VECTORS ;========================================================================== ; Now it is time to set the real Interrupt ; ax = function number (0201 ; bl = number of interrupt to set ; cx:dx = address of RM interrupt handler ;========================================================================== mov eax, 0201h mov bl,BRKINTNUM mov ecx,[RealModePtr] ; get address of real code int hand. shr ecx,4 ; put segment in hi word. mov dx,[(KeyboardType PTR esi).BrkCodeOffset] ; Get address of code int DPMI_INTR ; do call. jc ??error or [InitFlags],IF_SET_VECTORS IF DEBUG ;========================================================================== ; Get the protected mode interrupt vector - for the Debug interrupt ; input ax = 0204 ; bl = number of interrupt to get ; output: cf error ; ES:EBX = address of PM int handler routine. ;========================================================================== mov eax,0204h ; Get proteced mode mov bl,DBGINTNUM ; IRQ1 interrupt vector int DPMI_INTR ; do call. jc ??error mov [(KeyboardType PTR esi).DbgOldPMIOffset],edx ; save offset. mov [(KeyboardType PTR esi).DbgOldPMISelector],ecx ; save selector. ;========================================================================== ; Now it is time to set the Protected mode interrupt ; ax = function number (0205 ; bl = number of interrupt to set ; cx:edx = address of PM interrupt handler ;========================================================================== mov eax, 0205h mov bl,DBGINTNUM mov cx , cs lea edx, [Debug_Interrupt] ; get address of protected code int hand. int DPMI_INTR ; do call. jc ??error or [InitFlags],IF_SET_VECTORS ENDIF ; we have finished with success. mov eax,1 ; signal success. ret ??error: xor eax,eax ; signal an error. ??exit: ret ENDP Install_Keyboard_Interrupt ;*************************************************************************** ;* REMOVE_INTERRUPT -- Removes keyboard interrupt and restores chain * ;* * ;* INPUT: none * ;* * ;* OUTPUT: none * ;* * ;* PROTO: VOID Remove_Interrupt(VOID) * ;* * ;* HISTORY: * ;* 07/13/1994 PWG : Created. * ;*=========================================================================* PROC Remove_Keyboard_Interrupt C NEAR USES ebx,ecx,edx ; verifie that the keyboard was previosly install ; this is here in case of a page fault crash mov esi,[RealModePtr] test esi,esi jz ??error test [InitFlags],IF_SET_VECTORS jz ??vectors_not_set ; disengage Keyboard Interrupt handle ;========================================================================== ; Now it is time to set the real Interrupt ; ax = function number (0201 ; bl = number of interrupt to set ; cx:dx = address of RM interrupt handler ;========================================================================== mov eax, 0201h mov bl,IRQ1INTNUM mov edx,[(KeyboardType esi).KeyOldRMI] ; get address of real code int hand. shld ecx , edx , 16 int DPMI_INTR ; do call. jc ??error ;========================================================================== ; Now it is time to set the Protected mode interrupt ; ax = function number (0205 ; bl = number of interrupt to set ; cx:edx = address of PM interrupt handler ;========================================================================== mov eax, 0205h mov bl,IRQ1INTNUM mov ecx,[(KeyboardType esi).KeyOldPMISelector] ; Get PM segment to put int ds later. mov edx,[(KeyboardType esi).KeyOldPMIOffset] ; Get PM offset int DPMI_INTR ; do call. jc ??error ; disengage Control Break Interrupt handle ;========================================================================== ; Now it is time to set the real Interrupt ; ax = function number (0201 ; bl = number of interrupt to set ; cx:dx = address of RM interrupt handler ;========================================================================== mov eax, 0201h mov bl,BRKINTNUM mov edx,[(KeyboardType esi).BrkOldRMI] ; get address of real code int hand. shld ecx , edx , 16 int DPMI_INTR ; do call. jc ??error ;========================================================================== ; Now it is time to set the Protected mode interrupt ; ax = function number (0205 ; bl = number of interrupt to set ; cx:edx = address of PM interrupt handler ;========================================================================== mov eax, 0205h mov bl,BRKINTNUM mov ecx,[(KeyboardType esi).BrkOldPMISelector] ; Get PM segment to put int ds later. mov edx,[(KeyboardType esi).BrkOldPMIOffset] ; Get PM offset int DPMI_INTR ; do call. jc ??error IF DEBUG ; disengage Keyboard Interrupt handle ;========================================================================== ; Now it is time to set the Protected mode interrupt ; ax = function number (0205 ; bl = number of interrupt to set ; cx:edx = address of PM interrupt handler ;========================================================================== mov eax, 0205h mov bl,DBGINTNUM mov ecx,[(KeyboardType esi).DbgOldPMISelector] ; Get PM segment to put int ds later. mov edx,[(KeyboardType esi).DbgOldPMIOffset] ; Get PM offset int DPMI_INTR ; do call. jc ??error ENDIF IF NOT PROT_INT_ENABLE ; Clean up the Users interrupt table mov eax , 201h mov bl , [ byte ptr RMVector ] xor ecx , ecx xor edx , edx int DPMI_INTR jc ??error ENDIF ??vectors_not_set: ; now free up the real mode memory. test [InitFlags],IF_LOCKED_RM_CODE jz ??rm_not_locked mov eax , 0601h mov ecx,[RealModePtr] ; ecx must have start of memory. mov edi,[RealModeSize] ; edx will have size of region in bytes. shld ebx , ecx , 16 shld esi , edi , 16 int DPMI_INTR ; do call. jc ??error ; eax = 8 if mem err, eax = 9 if invalid mem region. ??rm_not_locked: test [InitFlags],IF_ALLOC_RM jz ??mem_not_allocated mov eax , 0101h mov edx,[ RealModeSel ] ; get physical address of real mode buffer. int DPMI_INTR ; do call. jc ??error ??mem_not_allocated: ; Now we can unlock all stuff needed for the interrupt. ; Unlock Code test [InitFlags],IF_LOCKED_PM_CODE jz ??code_not_locked mov eax , 0601h mov ecx,OFFSET LockedCodeStart ; ecx must have start of memory. mov edi,OFFSET LockedCodeEnd ; edx will have size of region in bytes. sub edi,ecx ; - figure size. shld ebx , ecx , 16 shld esi , edi , 16 int DPMI_INTR ; do call. jc ??error ; eax = 8 if mem err, eax = 9 if invalid mem region. ??code_not_locked: ; Unlock data test [InitFlags],IF_LOCKED_PM_DATA jz ??data_not_locked mov ax,0601h ; set es to descriptor of data. mov ecx,OFFSET LockedDataStart ; ecx must have start of memory. mov edi,OFFSET LockedDataEnd ; edx will have size of region in bytes. sub edi,ecx ; - figure size. shld ebx , ecx , 16 shld esi , edi , 16 int DPMI_INTR ; do call. jc ??error ; eax = 8 if mem err, eax = 9 if invalid mem region. ??data_not_locked: ; we have finished with success. mov [RealModePtr],0 ; To say we can do it again sometime. mov [InitFlags],0 ; To say we can do it again sometime. mov eax,1 ; signal success. ret ??error: xor eax,eax ; signal an error. ret ENDP Remove_Keyboard_Interrupt ;*************************************************************************** ;* CHECK_KEY_NUM -- Checks if key in queue, return key num * ;* * ;* INPUT: none * ;* * ;* OUTPUT: Keynum of the key that was pressed, FALSE otherwise * ;* ;* PROTO: INT Check_Key_Num(VOID); ;* * ;* HISTORY: * ;* 07/14/1994 PWG : Created. * ;*=========================================================================* PROC Check_Key_Num C NEAR USES ebx,esi pushf ; save off the flags cli ; disable interrupts mov esi,[RealModePtr] ; Point to start of RM data. mov eax,[(KeyboardType PTR esi).KeyBufferHead] xor eax,[(KeyboardType PTR esi).KeyBufferTail] or eax,eax ; check to see if head == tail jz short ??fini ; if so we are done mov eax,[(KeyboardType PTR esi).KeyBufferHead] ; get the head mov ax,[(KeyboardType PTR esi+eax).KeyBuffer] ; get key num ??fini: sti popf ret ENDP Check_Key_Num ;*************************************************************************** ;* GET_KEY_NUM -- Returns the next key num in ax * ;* * ;* INPUT: none * ;* * ;* OUTPUT: WORD key flags are in the high byte of return word, key * ;* num is in the low byte. ;* * ;* PROTO: WORD Get_Key_Num(VOID); ;* * ;* HISTORY: * ;* 07/14/1994 PWG : Created. * ;*=========================================================================* PROC Get_Key_Num C NEAR USES esi,edi mov esi,[RealModePtr] ; Point to start of RM data. ??wait: cli ; disable interrupts mov eax,[(KeyboardType PTR esi).KeyBufferHead] ; get the head cmp eax,[(KeyboardType PTR esi).KeyBufferTail] ; get the head jne short ??getkey sti ; enable interrupts jmp ??wait ??getkey: call Low_Get_Key sti ; enable interrupts ret ENDP Get_Key_Num ;*************************************************************************** ;* KN_TO_KA -- Translates a key num to an ASCII key * ;* * ;* INPUT: WORD the keynum to translate * ;* * ;* OUTPUT: WORD the ASCII key that is returned * ;* * ;* PROTO: INT KN_To_KA(INT keynum); * ;* * ;* HISTORY: * ;* 07/15/1994 PWG : Created. * ;*=========================================================================* PROC KN_To_KA C NEAR ARG keynum:DWORD mov eax,[keynum] call near ptr Convert_Num_To_ASCII ret ENDP KN_To_KA ;*************************************************************************** ;* LOW_GET_KEY -- low level get key returns key num and bits * ;* * ;* INPUT: AX - index into the buffer * ;* * ;* OUTPUT: AX - key num with bits * ;* * ;* PROTO: none - assembly callable routine only. * ;* * ;* HISTORY: * ;* 07/14/1994 PWG : Created. * ;*=========================================================================* PROC Low_Get_Key C NEAR USES ebx,esi,edi mov edi,eax ; save off value in ax ; We should set up both DS & ES because we are a low level function ; and don't know who might have called us or what the registers ; currently are. ; No reason to set DS & ES. ; This is not a hardware interrupt and if the funtion is being called ; from within a hardware interrupt then DS and ES will be preset to ; DGROUP _DATA mov esi,[RealModePtr] ; Point to start of RM data. mov ax,[(KeyboardType PTR esi+edi).KeyBuffer] ; get the head add edi,2 and edi,0FFH ; 128 word circular buffer cmp al,KN_LMOUSE jb short ??cont cmp al,KN_RMOUSE ja short ??chkjoy push eax ; save off the keynum we got mov ax,[(KeyboardType PTR esi+edi).KeyBuffer] ; get the head add edi,2 and edi,0FFH ; 128 word circular buffer mov [MouseQX],eax mov ax,[(KeyboardType PTR esi+edi).KeyBuffer] ; get the head add edi,2 and edi,0FFH ; 128 word circular buffer mov [MouseQY],eax pop eax ; restore keynum for return jmp short ??cont ??chkjoy: cmp al,KN_JBUTTON2 ; mouse button before joystick button ja short ??cont push eax ; save off the keynum we got mov ax,[(KeyboardType PTR esi+edi).KeyBuffer] ; get the head add edi,2 and edi,0FFH ; 128 word circular buffer mov ax,[(KeyboardType PTR esi+edi).KeyBuffer] ; get the head add edi,2 and edi,0FFH ; 128 word circular buffer pop eax ; restore keynum for return ??cont: mov [(KeyboardType PTR esi).KeyBufferHead],edi ; set the head ??out: ret ENDP Low_Get_Key ;*************************************************************************** ;* CONVERT_NUM_TO_ASCII -- Assembly routine converts keynum to ASCII key * ;* * ;* INPUT: EAX where: * ;* AH - holds the key num bits * ;* AL - holds the key num value * ;* * ;* OUTPUT: EAX where: * ;* AH - hold the key bits * ;* AL - holds the ASCII key value * ;* * ;* PROTO: none - assembly callable routine only. * ;* * ;* WARNINGS: GetKeyLock must be set prior to calling this function * ;* * ;* HISTORY: * ;* 07/15/1994 PWG : Created. * ;*=========================================================================* PROC Convert_Num_To_ASCII C NEAR USES ebx,ecx,esi,edi ;*=================================================================== ;* Force all breaks to be thrown out. ;*=================================================================== test eax,08000h ; If it is a button number jne short ??button ; don't process it test ah,KEYRELEASE ; If it is not key release je short ??ok ; then go process it ??button: xor eax,eax ; no ascii value for a button ret ??ok: ;*=================================================================== ;* ES points to the DOSMEM selector, esi is the offset of the ;* protected mode structure. ;*=================================================================== mov esi,[RealModePtr] ; Point to start of RM data. ;*=================================================================== ;* Start dealing with the keys. ;*=================================================================== cmp al,110 ; is it esc je ??esc ; if so then deal with it ;??chkext: cmp al,62 ; is it extended? jae short ??extended ; its extended so return ext code mov ebx,eax ; get an index and ebx,03FH ; only 0-63 allowed test ah,1 ; if not, test for shift jnz short ??shifted ; if shifted get shift value ;*=================================================================== ;* Here when we have an unshifted ascii key ;*=================================================================== mov al,[Ascii+ebx] ; get the ascii code for this number jmp short ??ctrlkey ;*=================================================================== ;* CAPS key is on, forcing all alphabetic characters to lower case (all ;* others are shifted) ;*=================================================================== ??alpha_lowered: mov al,[Alpha_Lower+ebx] ; get the s_ascii code for number jmp short ??ctrlkey ;*=================================================================== ;* CAPS key is on, forcing all alphabetic characters to lower case (all ;* others are shifted) ;*=================================================================== ??alpha_shifted: mov al,[Alpha_Shift+ebx] ; get the s_ascii code for number jmp short ??ctrlkey ;*=================================================================== ;* Shift'ed character ;*=================================================================== ??shifted: mov al,[Shift+ebx] ; get ascii shift code for number ??ctrlkey: test ah,2 ; is it ctrl? jz short ??jexit ; izf not skip ctrl check mov edi,ebx ; get index and edi,7 ; only bits 0-7 mov cl,[(KeyboardType PTR esi+edi).Bits] shr ebx,3 ; div by 8 for byte offset test [(KeyboardType PTR esi+ebx).KeysCapsLock],cl je short ??jexit and al,01FH ; force to ctrl value ??jexit: jmp short ??exit ??extended: cmp al,75 ; if less than insert jb short ??special cmp al,110 ; if >= esc jae short ??funckey ??editkeys: xor ebx,ebx mov bl,al sub ebx,75 ; get value from 0-34 test [(KeyboardType PTR esi).KeyFlags],NONUMLOCK jne short ??no_numpad test [GetKeyLock],NUMLOCK ; look at the snap shot of bits jne short ??numpad test ah,SHIFTPRESS jne short ??numpad ??no_numpad: mov al,[Edit+ebx] ; get the ascii code for this number jmp short ??exit ??numpad: sub ebx,15 ; adjust to numpad entries mov al,[NumPad+ebx] ; get the ascii code for this number jmp short ??exit ??funckey: cmp al,112 ; if less than function keys jb short ??extout cmp al,121 ; if greater than function keys 1-10 ja short ??extout mov bl,al sub bl,112 ; get value 0-9 mov bh,0C5H ; function key 1 no shift-ctrl-alt test ah,7 ; any shift-ctrl-alt je short ??funcadj mov bh,098H ; function key 1 alt test ah,ALTPRESS ; (highest prescendence) jne short ??funcadj mov bh,0A2H ; function key 1 ctrl (next highest) test ah,CTRLPRESS jne short ??funcadj mov bh,0ACH ; function key 1 shift (lowest) ??funcadj: sub bh,bl ; adjust function key to a mov al,bh ; shift/no shift etc jmp short ??exit ??special: cmp al,65 ; if less than specials jb short ??extout add al,133 ; make value between 198-207 or jmp short ??exit ; 0C6H-0CFH ??extout: or al,080H jmp short ??exit ??esc: mov al,01BH ??exit: ret ENDP Convert_Num_To_ASCII ;*************************************************************************** ;* CHECK_KEY -- checks for ASCII keys sitting in the keybuffer * ;* * ;* INPUT: none * ;* * ;* OUTPUT: INT the ASCII sequence for the key that was pressed * ;* * ;* PROTO: INT Check_Key(VOID); * ;* * ;* HISTORY: * ;* 07/15/1994 PWG : Created. * ;*=========================================================================* PROC Check_Key C NEAR USES ebx,edi,esi pushf cld mov ebx,[RealModePtr] ; Point to start of RM data. ??clrloop: cli ; disable interrupts mov eax,[(KeyboardType PTR ebx).KeyBufferHead] cmp eax,[(KeyboardType PTR ebx).KeyBufferTail] je short ??clrexit mov esi,eax mov ax,[(KeyboardType PTR ebx+eax).KeyBuffer] ; get key num mov edi,ebx add edi,OFFSET (KeyboardType PTR 0).PassAlways mov ecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always repne scasb ; look for a match or ecx,ecx ; see if there was a match jne short ??getinvalid test ah,KEYRELEASE ; is this a break? jne short ??getinvalid cmp al,122 ; is code a valid ascii key?? jb short ??convkey ??getinvalid: cmp al,KN_LMOUSE ; check if it is a mouse or joystick jb short ??contget cmp al,KN_JBUTTON2 ja short ??contget add si,4 ; get rid of the x and y values ??contget: add esi,2 ; get rid of invalid ascii key and esi,0FFH ; 128 word circular buffer mov [(KeyboardType PTR ebx).KeyBufferHead],esi sti ; enable interrupts jmp ??clrloop ??clrexit: xor eax,eax ??convkey: mov cx,[(KeyboardType PTR ebx).KeyLock] mov [GetKeyLock],cx ; save status for convert to ASCII sti ; enable interrupts or eax,eax je short ??exit ; exit if no key ; AX has key num code with bits call near ptr Convert_Num_To_ASCII ; AX has ASCII code with bits xor ah,ah ; clear key bits ??exit: popf ret ENDP Check_Key ;*************************************************************************** ;* GET_KEY -- Gets the next available ASCII keystroke. * ;* * ;* INPUT: none * ;* * ;* OUTPUT: AH - hold the key bits * ;* AL - holds the ASCII key value * ;* * ;* PROTO: INT Get_Key(VOID); * ;* * ;* HISTORY: * ;* 07/15/1994 PWG : Created. * ;*=========================================================================* PROC Get_Key C NEAR USES ebx,ecx,edi cld ; clear the direction flag for speed ; Check_Key had to be copied because of enable and disable of ints ; with mod to get the key mov ebx,[RealModePtr] ; Point to start of RM data. ??chkkey: cli ; disable interrupts mov eax,[(KeyboardType PTR ebx).KeyBufferHead] cmp eax,[(KeyboardType PTR ebx).KeyBufferTail] jne short ??getkey sti ; enable interrupts jmp ??chkkey ??getkey: ; AX has index into keybuffer call near ptr Low_Get_Key ; AX has key num code with bits mov cx,[(KeyboardType PTR ebx).KeyLock] mov [GetKeyLock],cx ; save status for convert to ASCII sti ; enable interrupts mov edi,ebx add edi,OFFSET (KeyboardType PTR 0).PassAlways mov ecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always repne scasb ; look for a match or ecx,ecx ; see if there was a match jne ??chkkey test ah,KEYRELEASE ; is this a break? jne ??chkkey cmp al,122 ; is code a valid ascii key?? jae ??chkkey ; AX has key num code with bits call near ptr Convert_Num_To_ASCII xor ah,ah ret ENDP Get_Key ;*************************************************************************** ;* KEYBOARD_ATTRIBUTES_ON -- Sets the specified keyflags on * ;* * ;* INPUT: INT the keyflags that need to be turned on * ;* * ;* OUTPUT: INT the current keyflags that are on * ;* * ;* PROTO: INT Keyboard_Attributes_On(INT key_flags); * ;* * ;* HISTORY: * ;* 07/19/1994 PWG : Created. * ;*=========================================================================* PROC Keyboard_Attributes_On C NEAR USES esi,edi ARG bits:DWORD mov esi,[RealModePtr] ; Point to start of RM data. mov eax,[bits] or [(KeyboardType PTR esi).KeyFlags],eax ; Only do this if in playback or record mode. test eax,PASSBREAKS je short ??fini xor eax,eax mov edi,esi add edi,OFFSET (KeyboardType PTR 0).KeysUpDown mov [edi],eax mov [edi+4],eax mov [edi+8],eax mov [edi+12],eax ??fini: mov eax,[(KeyboardType PTR esi).KeyFlags] ret ENDP Keyboard_Attributes_On ;*************************************************************************** ;* KEYBOARD_ATTRIBUTES_OFF -- Sets the specified keyflags off * ;* * ;* INPUT: INT the keyflags that need to be turned off * ;* * ;* OUTPUT: INT the current keyflags that are off * ;* * ;* PROTO: INT Keyboard_Attributes_Off(INT key_flags); * ;* * ;* HISTORY: * ;* 07/19/1994 PWG : Created. * ;*=========================================================================* PROC Keyboard_Attributes_Off C NEAR USES esi ARG bits:DWORD mov esi,[RealModePtr] ; Point to start of RM data. mov eax,[bits] not eax and [(KeyboardType PTR esi).KeyFlags],eax xor eax,eax mov eax,[(KeyboardType PTR esi).KeyFlags] ret ENDP Keyboard_Attributes_Off ;*************************************************************************** ;* CLEAR_KEYBUFFER -- Clears keystrokes out of the key buffer * ;* * ;* INPUT: none * ;* * ;* OUTPUT: none * ;* * ;* PROTO: VOID Clear_KeyBuffer(VOID); * ;* * ;* HISTORY: * ;* 07/19/1994 PWG : Created. * ;*=========================================================================* PROC Clear_KeyBuffer C NEAR USES eax,esi mov esi,[RealModePtr] ; Point to start of RM data. cli mov eax,[(KeyboardType PTR esi).KeyBufferHead] mov [(KeyboardType PTR esi).KeyBufferTail],eax sti ret ENDP Clear_KeyBuffer ;*************************************************************************** ;* KEY_DOWN -- tests the status of a keyboard key * ;* * ;* INPUT: INT the key num to check * ;* * ;* OUTPUT: INT zero if the key is up, none zero if the key is down * ;* * ;* PROTO: INT Key_Down(INT key); * ;* * ;* HISTORY: * ;* 07/19/1994 PWG : Created. * ;*=========================================================================* PROC Key_Down C NEAR USES ebx,ecx,edi,esi ARG key:DWORD push [key] call KeyNum_Translate add esp,4 xor ah,ah ; Always ignore the control bits. mov esi,[RealModePtr] ; Point to start of RM data. mov edi,eax shr edi,3 mov cl,al and cl,0111b mov al,01b shl al,cl and al,[(KeyboardType PTR esi+edi).KeysUpDown] ret ENDP Key_Down ;*************************************************************************** ;* CHECK_KEY_BITS -- checks ascii key in key buff with shift,ctrl,alt bits * ;* * ;* INPUT: none * ;* * ;* OUTPUT: INT 0 = no key in buffer, !0 = a key with the bits set * ;* * ;* PROTO: INT Check_Key_Bits(VOID); * ;* * ;* HISTORY: * ;* 07/20/1994 PWG : Created. * ;*=========================================================================* PROC Check_Key_Bits C NEAR USES ebx,ecx,edi,esi pushf ; save off the direction flag cld ; we will go forward mov ebx,[RealModePtr] ; Point to start of RM data. ??clrloop: cli ; disable interrupts mov eax,[(KeyboardType PTR ebx).KeyBufferHead] cmp eax,[(KeyboardType PTR ebx).KeyBufferTail] je short ??clrexit ??playback: mov esi,eax mov ax,[(KeyboardType PTR ebx+eax).KeyBuffer] ; get key num mov edi,ebx add edi,OFFSET (KeyboardType PTR 0).PassAlways mov ecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always repne scasb ; look for a match or ecx,ecx ; see if there was a match jne short ??getinvalid ;------ If there is a NULL in the keyboard buffer, we must NOT treat it ; as a valid ASCII value because the calling code will falsely ; assume that the NULL return value indicates an empty buffer. or al,al je short ??getinvalid cmp al,122 ; is code a valid ascii key?? jb short ??convkey ??getinvalid: add esi,2 ; get rid of invalid ascii key and esi,0FFH ; 128 word circular buffer mov [(KeyboardType PTR ebx).KeyBufferHead],esi sti ; enable interrupts jmp ??clrloop ??clrexit: xor ax,ax ??convkey: mov cx,[(KeyboardType PTR ebx).KeyLock] mov [GetKeyLock],cx ; save status for convert to ASCII sti ; enable interrupts or eax,eax je short ??exit ; exit if no key ; AX has key num code with bits mov ch,ah and ch,KEYRELEASE ; keep only KEYRELEASE bit and ah,NOTKEYRELEASE ; keep everything but KEYRELEASE bit call near ptr Convert_Num_To_ASCII ; AX has ASCII code with bits or ah,ch ; replace KEYRELEASE bit ??exit: popf ret ENDP Check_Key_Bits ;*************************************************************************** ;* GET_KEY_BITS -- Gets ascii key in key buff with shift,ctrl,alt bits * ;* * ;* INPUT: none * ;* * ;* OUTPUT: INT 0 = no key in buffer, !0 = a key with the bits set * ;* * ;* PROTO: INT Check_Key_Bits(VOID); * ;* * ;* HISTORY: * ;* 07/20/1994 PWG : Created. * ;*=========================================================================* PROC Get_Key_Bits C NEAR USES ebx,ecx,edi cld ; Check_Key_Bits was copied because of enable and disable of interrupts ; with mod to get the key mov ebx,[RealModePtr] ; Point to start of RM data. ??chkkey: cli ; disable interrupts mov eax,[(KeyboardType PTR ebx).KeyBufferHead] cmp eax,[(KeyboardType PTR ebx).KeyBufferTail] jne short ??getkey sti ; enable interrupts jmp ??chkkey ??getkey: ; AX has index into keybuffer call near ptr Low_Get_Key ; AX has key num code with bits mov cx,[(KeyboardType PTR ebx).KeyLock] mov [GetKeyLock],cx ; save status for convert to ASCII sti ; enable interrupts mov edi,ebx add edi,OFFSET (KeyboardType PTR 0).PassAlways mov ecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd-OFFSET (KeyboardType PTR 0).PassAlways)+1 ; get number of pass always repne scasb ; look for a match or ecx,ecx ; see if there was a match jne ??chkkey cmp al,122 ; is code a valid ascii key?? jae ??chkkey ; AX has key num code with bits mov ch,ah and ch,KEYRELEASE ; keep only KEYRELEASE bit and ah,NOTKEYRELEASE ; keep everything but KEYRELEASE bit call near ptr Convert_Num_To_ASCII ; AX has ASCII code with bits or ah,ch ; replace KEYRELEASE bit ret ENDP Get_Key_Bits ;*************************************************************************** ;* KEY_SATISFIED -- checks to see if the given key is satisfied * ;* * ;* INPUT: INT the key flags/number to check * ;* * ;* OUTPUT: INT 0 if the key is not satisfied, !0 if the key is satisfied * ;* * ;* PROTO: VOID Key_Satisfied(INT key); * ;* * ;* HISTORY: * ;* 07/20/1994 PWG : Created. * ;*=========================================================================* PROC Key_Satisfied C NEAR USES ebx,ecx,esi,edi ARG key:DWORD mov eax,[key] mov ebx,eax ; save key code push eax call Key_Down ; see it its even down add esp,4 cmp eax,0 je ??out ; if not it can't be satisfied mov esi,[RealModePtr] ; Point to start of RM data. mov eax,ebx ; if so, restore code xor ah,ah ; clear out flags area mov edi,eax ; set as an index shr edi,3 ; div by 8 for bytes mov ch,1h ; set a bit for mask mov cl,al ; get the code number and cl,7 ; get the actual bit this code is shl ch,cl ; move bit into mask position ; now test the ctrl,alt and shift bits test [(KeyboardType PTR esi+7).KeysUpDown],04h ; is the left ctrl down? jne short ??ctrlon ; if so, ctrl is on test [(KeyboardType PTR esi+8).KeysUpDown],01h ; is the right ctrl down? je short ??ctrloff ; if not, neither are down, no ctrl ??ctrlon: or ah,02h ; or on the ctrl bit in flags ??ctrloff: test [(KeyboardType PTR esi+7).KeysUpDown],50h ; is either alt key down? je short ??altoff or ah,04h ; or on the alt bit in flags ??altoff: test [(KeyboardType PTR esi+5).KeysUpDown],10h ; is the left shift down? jne short ??shifton ; if so the sift is on test [(KeyboardType PTR esi+7).KeysUpDown],02h ; is the right shift down? je short ??shiftoff ; if not then neither shift is down ??shifton: or ah,01h ; or on the shift bit in flags ??shiftoff: test [(KeyboardType PTR esi).KeyLock],CAPSLOCK ; is the caps lock on? je short ??capsoff ; if not don't worry about it test ch,[(KeyboardType PTR esi+edi).KeysCapsLock] ; get code for keycaps je short ??capsoff ; its not effected xor ah,1h ; toggle the shift flag ??capsoff: test [(KeyboardType PTR esi).KeyLock],NUMLOCK ; is the num lock key on? je short ??numlockoff ; if not don't worry about it test ch,[(KeyboardType PTR esi+edi).KeysNumLock] ; get code for numlock je short ??numlockoff ; if not effected skip toggle xor ah,1h ; toggle the shift flag if effected ??numlockoff: mov al,0ffh ; set to match by default cmp ah,bh ; if flags match return !0 je short ??out ; just exit xor eax,eax ; otherwise, clear all bits FALSE ??out: or eax,eax ret ENDP Key_Satisfied ;*************************************************************************** ;* Interrupt routines start here - Interrupts must be within the Locked ;* code area for DPMI compatability. ;*************************************************************************** LABEL LockedCodeStart BYTE ;*************************************************************************** ;* KEYNUM_TRANSLATE -- Performs a lowlevel xlate to a keycode * ;* * ;* INPUT: WORD the code that needs to be translated * ;* * ;* OUTPUT: WORD the translated code * ;* * ;* PROTO: INT KeyNum_Translate(INT keynum); * ;* * ;* HISTORY: * ;* 07/15/1994 PWG : Created. * ;*=========================================================================* PROC KeyNum_Translate C NEAR USES ebx,ecx,esi,edi ARG keycode:DWORD ;*=================================================================== ;* ES points to the DOSMEM selector, esi is the offset of the ;* protected mode structure. ;*=================================================================== mov esi,[RealModePtr] ; Point to start of RM data. mov eax,[keycode] test [(KeyboardType PTR esi).KeyFlags],TRACKEXT jne short ??fini mov ecx,OFFSET ((KeyboardType PTR 0).ExtRemap)- OFFSET((KeyboardType PTR 0).ExtNums) mov edi,OFFSET (KeyboardType PTR 0).ExtNums add edi,esi repne scasb jcxz short ??fini ; No match found. mov edi,esi add edi,OFFSET (KeyboardType PTR 0).ExtRemapEnd dec edi sub edi,ecx mov al,[edi] ??fini: ret ENDP KeyNum_Translate ;*************************************************************************** ;* STUFF_KEY_WORD -- Stuffs a word of data into keyboard buffer * ;* * ;* INPUT: WORD the code to stick into the circular buffer * ;* * ;* OUTPUT: WORD !=0 is sucessful, ==0 is not enough room * ;* * ;* PROTO: VOID Stuff_Key_WORD(INT code); * ;* * ;* HISTORY: * ;* 07/11/1994 PWG : Created. * ;*=========================================================================* PROC Stuff_Key_WORD C NEAR USES ebx,esi,edi ARG code:WORD mov esi,[RealModePtr] ; Point to start of RM data. mov eax,[(KeyboardType PTR esi).KeyBufferTail] mov edi,eax add eax,2 and eax,0FFh ; New KeyBufferTail value. cmp [(KeyboardType PTR esi).KeyBufferHead],eax je short ??noroom mov bx,[code] mov [(KeyboardType PTR esi+edi).KeyBuffer],bx ; Record the keystroke. mov [(KeyboardType PTR esi).KeyBufferTail],eax xor eax,eax ret ??noroom: mov eax,1 ret ENDP Stuff_Key_WORD ;*************************************************************************** ;* STUFF_KEY_NUM -- Stuffs a key num code into the circular buffer * ;* * ;* INPUT: WORD the keycode to stuff * ;* * ;* OUTPUT: WORD !=0 is sucessful, ==0 is not enough room * ;* * ;* PROTO: VOID Stuff_Key_Num(INT keynum); * ;* * ;* HISTORY: * ;* 07/11/1994 PWG : Created. * ;*=========================================================================* PROC Stuff_Key_Num C NEAR USES ebx,ecx,edx,edi,esi ARG keycode:DWORD LOCAL tail:DWORD ; Original keybuffer tail (safety copy). LOCAL size:WORD ; Size of write. ; for the moment we do not check for the interrupt flag ; mov eax,2534h ; function to get the interrupt status ; int 21 ; eax = interrupt status ; push eax ; save the result on the stack pushf ; store off the flags cli ; disable interrupts ; We need to set the data segment because we might be being called ; from within an interrupt ; Soo, if that is the case then DS & ES point to DGROUP _DATA mov esi,[RealModePtr] ; Point to start of RM data. ; Record the mouse position to be stuffed into buffer. mov eax,[(KeyboardType PTR esi).MouseX] mov [(KeyboardType PTR esi).LocalMouseX],ax mov eax,[(KeyboardType PTR esi).MouseY] mov [(KeyboardType PTR esi).LocalMouseY],ax ??cando: mov eax,[keycode] ; get the code or eax,eax ; Null keycodes are not recorded. jne short ??validkey jmp ??exit ??validkey: test [(KeyboardType PTR esi).KeyFlags],KEYMOUSE ; is the numeric keypad moving the mouse? je ??no_pad_move ; ALT-cursor keys are undefined. Pass them on to the program. test ah,ALTPRESS ; is either alt key down? jne ??no_pad_move test [(KeyboardType PTR esi).KeyFlags],SIMLBUTTON ; are we simulating left mouse presses je short ??chkinsert cmp al,KN_RETURN je short ??forceleft cmp al,KN_SPACE je short ??forceleft cmp al,KN_KEYPAD_RETURN je short ??forceleft ??chkinsert: cmp al,KN_INSERT jne short ??regular ??forceleft: mov al,KN_LMOUSE or [(KeyboardType PTR esi).Button],1 ; Left mouse bit. test ah,KEYRELEASE je ??mousefake and [(KeyboardType PTR esi).Button],NOT 1 jmp ??mousefake ??regular: cmp al,KN_DELETE jne short ??regular2 mov al,KN_RMOUSE or [(KeyboardType PTR esi).Button],2 ; Right mouse bit. test ah,KEYRELEASE je ??mousefake and [(KeyboardType PTR esi).Button],NOT 2 jmp ??mousefake ??regular2: ; DRD correction to ignore key releases for key mouse movement test ah,KEYRELEASE jne ??no_pad_move cmp al,KN_CENTER je short ??pad_move cmp al,KN_UPLEFT ; less than upleft? jb ??no_pad_move ; yes, then it isn't a keypad key cmp al,KN_DOWNRIGHT ; greater than downright? ja ??no_pad_move ; yes, then it isn't a keypad key cmp al,KN_DOWNLEFT ; is it UPLEFT, LEFT, or DOWNLEFT? jbe short ??pad_move cmp al,KN_UPRIGHT ; is it UPRIGHT, RIGHT, or DOWNRIGHT? jae short ??pad_move cmp al,KN_UP ; up? je short ??pad_move cmp al,KN_DOWN ; down? jne ??no_pad_move ??pad_move: ; DRD correction to use ch for ah mov ch,ah ; save shift-ctrl-alt-rlse status xor ah,ah ; get rid of any bits xor ebx,ebx sub al,KN_UPLEFT ; get a number between 0 and 12 mov bx,ax shl ebx,1 ; double for WORD index mov ax,[WORD PTR ((KeyboardType PTR esi+ebx).XYAdjust)] movsx ebx,ah movsx eax,al ; DRD correction to use ch ; The CTRL key moves the mouse to the edge of the screen. test ch,CTRLPRESS ; is either ctrl key down? jne short ??ctrlon ; if so, ctrl is on ; DRD correction to use ch ; use fast speed of the mouse move if the shift key is held down. mov edx,1 ; for slow speed test ch,SHIFTPRESS ; is either shift key down? je short ??normspeed ; if not then neither shift is down ??doublespeed: add edx,3 ; for fast speed ??normspeed: add ebx,edx ; add speed for y index mov bl,[(KeyboardType PTR esi+ebx).KeyMouseMove] ; get speed for y delta movsx ebx,bl xchg ebx,edx ; save mouse y delta add ebx,eax ; add speed for x index mov al,[(KeyboardType PTR esi+ebx).KeyMouseMove] ; get speed for x delta movsx eax,al xchg ebx,edx ; restore mouse y delta jmp short ??ctrloff ??ctrlon: ; Table lookup method for determining hotkey positions for CTRL ; cursor combination. This algorithm is hard coded for an ADJUST ; value of 3. If this value changed, then this section will also ; have to be modified. and ebx,011b ; Y = 1, 0, 3 and eax,011b ; X = 1, 0, 3 ; Table lookup method for determining hotkey positions for CTRL ; cursor combination. This algorithm is hard coded. ; -1, 0, 1 and ebx,011b ; Y = 3, 0, 1 and eax,011b ; X = 3, 0, 1 shl ebx,2 or ebx,eax ; Lookup index. ; Convert raw index into logical (clockwise) index. shl ebx,1 movzx ebx,[(KeyboardType PTR esi+ebx).EdgeConv] shl ebx,2 mov ax,[(KeyboardType PTR esi+ebx).ScreenEdge] ; New absolute X mov bx,[(KeyboardType PTR esi+ebx+2).ScreenEdge] ; New absolute Y mov [(KeyboardType PTR esi).LocalMouseX],ax mov [(KeyboardType PTR esi).LocalMouseY],bx ??set_xyz: mov ax,[(KeyboardType PTR esi).LocalMouseX] ; get new mouse x,y mov bx,[(KeyboardType PTR esi).LocalMouseY] jmp short ??set_xy ; Process a normal faked mouse move. ??ctrloff: ; DRD change add [(KeyboardType PTR esi).LocalMouseX],ax ; save it in our local jns short ??not_negative_x xor eax,eax mov [(KeyboardType PTR esi).LocalMouseX],ax ; clear our local ??not_negative_x: ; DRD change add [(KeyboardType PTR esi).LocalMouseY],bx ; save it in our local jns short ??not_negative_y xor ebx,ebx mov [(KeyboardType PTR esi).LocalMouseY],bx ; clear our local ??not_negative_y: mov ax,[(KeyboardType PTR esi).LocalMouseX] ; get new mouse x,y mov bx,[(KeyboardType PTR esi).LocalMouseY] cmp ax,MAX_X_PIXEL ; bigger than jle short ??check_y mov ax,MAX_X_PIXEL ??check_y: cmp bx,MAX_Y_PIXEL ; bigger than jle short ??set_xy mov bx,MAX_Y_PIXEL ??set_xy: mov [(KeyboardType PTR esi).LocalMouseX],ax mov [(KeyboardType PTR esi).LocalMouseY],bx mov [WORD PTR (KeyboardType PTR esi).MouseX],ax mov [WORD PTR (KeyboardType PTR esi).MouseY],bx cmp [(KeyboardType PTR esi).MouseUpdate],0 ; wait until mouse interrupt is done jne short ??noshow ; PWG: ARRGGGHHHH! ; call Low_Hide_Mouse ; call Low_Show_Mouse ??noshow: mov eax,KN_MOUSE_MOVE ??mousefake: mov [keycode],eax ; Fake a MOUSE_MOVE event. ??no_pad_move: ; Fetch working pointers to the keyboard ends. mov edi,[(KeyboardType PTR esi).KeyBufferTail] mov [tail],edi ; Safety record. ; Record the base keycode (if there is room). cwde push eax call Stuff_Key_WORD add esp,4 or eax,eax jne short ??jmpnoroom ; Also record the mouse coordinates if necessary. mov eax,[keycode] ; get key code cmp al,KN_MOUSE_MOVE ; mouse move? je short ??recordmouse ; yes? then record the mouse cooordinates cmp al,KN_LMOUSE je short ??recordmouse cmp al,KN_RMOUSE je short ??recordmouse jmp short ??ok ??jmpnoroom: jmp ??noroom ; Record mouse coordinate X. ??recordmouse: movzx eax,[(KeyboardType esi).LocalMouseX] push eax call Stuff_Key_WORD add esp,4 or eax,eax jne ??jmpnoroom add [size],2 ; Record mouse coordinate Y. movzx eax,[(KeyboardType esi).LocalMouseY] push eax call Stuff_Key_WORD add esp,4 or eax,eax jne ??jmpnoroom add [size],2 ??ok: ; If PASSBREAKS is not active and this is a keyboard ; break AND it is not a mouse event, then don't put ; it into the buffer. mov ebx,0101h ; Bit control tools. mov eax,[keycode] cmp al,KN_MOUSE_MOVE je short ??notreal cmp al,127 je short ??notreal test ah,KEYRELEASE je short ??real xor bl,bl test [(KeyboardType PTR esi).KeyFlags],PASSBREAKS jne short ??real cmp al,KN_LMOUSE je short ??real cmp al,KN_RMOUSE je short ??real ??notreal: mov [(KeyboardType esi).KeyBufferTail],edi ; Nullify any KeyBufferTail changes. ??real: ; Update the KeysUpDown bit array. mov edi,eax and edi,07Fh mov cl,3 shr edi,cl ; DI = Byte offset into bit table. mov cl,al and cl,0111b ; CL = Bit offset into bit table byte. shl bx,cl not bh ; If this is a reapeat key and the key is already being held ; down, then don't stuff it into the keyboard buffer. test bl,[(KeyboardType esi+edi).KeysUpDown] je short ??notalready test [(KeyboardType PTR esi).KeyFlags],REPEATON jne short ??notalready mov edx,[tail] mov [(KeyboardType esi).KeyBufferTail],edx ; Nullify any KeyBufferTail changes. ??notalready: and [(KeyboardType esi+edi).KeysUpDown],bh ; Force key bit to zero. or [(KeyboardType esi+edi).KeysUpDown],bl ; Insert key bit as appropriate. ;??notreal: ; Successful keybuffer stuff could result in a ??norecord: mov eax,1 jmp short ??exit ; Unsuccessful keybuffer stuff. ??noroom: mov eax,[tail] mov [(KeyboardType PTR esi).KeyBufferTail],eax xor eax,eax ; Signal an error. ??exit: sti popf ; popf ; pop ebx ; or ebx,ebx ; jz ??final_exit ; sti ??final_exit: ret ENDP Stuff_Key_Num ;*************************************************************************** ;* BREAK_INTERRUPT -- Handles break interrupt for protected mode * ;* * ;* INPUT: none * ;* * ;* OUTPUT: none * ;* * ;* WARNINGS: This is an interrupt routine. * ;* * ;* HISTORY: * ;* 07/28/1994 PWG : Created. * ;*=========================================================================* PROC Break_Interrupt C NEAR iret ENDP Break_Interrupt IF DEBUG ;*************************************************************************** ;* DEBUG_INTERRUPT -- Handles debug (INT 3) interrupt for protected mode * ;* * ;* INPUT: none * ;* * ;* OUTPUT: none * ;* * ;* WARNINGS: This is an interrupt routine. * ;* * ;* HISTORY: * ;* 07/28/1994 PWG : Created. * ;*=========================================================================* PROC Debug_Interrupt C NEAR ;*================================================================== ;* Setup fake Interrupt entry sequence so that we can execute our ;* code and then IRET painlessly into the debuggers interrupt ;* handler. ;*================================================================== pushfd ; Step 1 sub esp,8 ; Step 2 push ebp ; Step 3 mov ebp,esp ; Set up a stack frame to know where to poke address. ;*================================================================== ;* Preserve all of the registers that we intend to use. ;*=======================================Dbg======================== pushad push ds es gs fs cld mov ax , _DATA mov ds , ax mov es , ax inc [BYTE PTR 0B0000h] ;*================================================================== ;* Setup the pointers to the real mode data and the protected mode ;* data and selectors. ;*================================================================== mov esi,[RealModePtr] ; Point to start of RM data. ;*================================================================== ;* Do the deed. ;*================================================================== mov [(KeyboardType PTR esi).KeyIntDisabled],1 ;*================================================================== ;* Now get the address of the real debug handler and poke it into ;* the stack so we can IRET to it. ;*================================================================== mov eax,[(KeyboardType PTR esi).DbgOldPMIOffset] ; Get orig offset. mov ebx,[(KeyboardType PTR esi).DbgOldPMISelector] ; Get orig selector. mov [ss:ebp+4],eax ; Poke offset. mov [ss:ebp+8],ebx ; Poke selector. ;*================================================================== ;* Restore the stack so it looks like we just did an IRET entry ;*================================================================== pop fs gs es ds popad pop ebp ;*================================================================== ;* This iret should go directly to the real debugger handler ;* painlessly and effectively. ;*================================================================== iretd ENDP Debug_Interrupt ENDIF IF PROT_INT_ENABLE ;*************************************************************************** ;* KEYBOARD_INTERRUPT -- Handles input that comes from the keyboard * ;* * ;* This routine intercepts the key codes on their way to the * ;* BIOS. With the adjustment of the Flags described above * ;* you can get a wide variety of effects. * ;* * ;* INPUT: none * ;* * ;* OUTPUT: none * ;* * ;* WARNINGS: This is an interrupt function * ;* * ;* HISTORY: * ;* 07/13/1994 PWG : Created. * ;*=========================================================================* PROC Keyboard_Interrupt C NEAR pushad push ds es gs fs cld ; this is the part of the interrupt that set the segment registers mov ax , _DATA mov es , ax mov ds , ax ; At this point we do not know if the SS selector is a ; System Stack or the Application Stack pointer. ; Soo to be in the safe side we create our own local ; Stack Pointer Selector Relative to DS ; Note Do not try this trick in a reentrant interrupt mov cx, ss ; get SS mov [Keyboard_App_Stack_ESP], esp ; Protect ESP mov [Keyboard_App_Stack_SS], ecx ; Protect SS lea edx, [Keyboard_StackStart ] ; Compute Local Stack size and edx, -4 ; cli ; Disable All interrupts mov ss, ax ; Set new SS Selector mov esp, edx ; Set new Stack Offset sti ; Enable Interrupts mov esi,[RealModePtr] ; Point to start of RM data. mov edx,[(KeyboardType PTR esi).KeyFlags] ;*** The following fix allows proper caps and num lock tracking on Tandy ; 10-6-89 LJC, DRD and [(KeyboardType PTR esi).KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive test [BYTE PTR 417H],040H ; test Caps lock bit in BIOS je short ??bioscapsoff ; skip activate code or [(KeyboardType PTR esi).KeyLock],CAPSLOCK ; Caps Lock active ??bioscapsoff: test [BYTE PTR 417H],020H ; test Num lock bit in BIOS je short ??biosnumoff ; skip activate code or [(KeyboardType PTR esi).KeyLock],NUMLOCK ; Num Lock active ??biosnumoff: mov [(KeyboardType PTR esi).ExtKeyboard],TRUE ; assume 101/102-key keyboard test [BYTE PTR 496H],010H ; test for 101/102-key keyboard jne short ??extkeyboard ; skip deactivate code mov [(KeyboardType PTR esi).ExtKeyboard],FALSE ; no 101/102-key keyboard ??extkeyboard: xor ah,ah ; clear ctrl flags to 0 mov ebx,0101H ; set key to a make by default in al,KEYDATA ; get a code from the keyboard ; ; New CODE to montior key stream ; xor ebx,ebx mov bx,[(KeyboardType PTR esi).KeyStreamIndex] mov [(KeyboardType PTR esi+ebx).KeyStream],al inc ebx and ebx,15 mov [(KeyboardType PTR esi).KeyStreamIndex],bx mov ebx,0101H ; set key to a make by default ; ; END OF SEQUENCE ; ; ; Handle the PAUSE key being pressed. If it is pressed, then ; signal that the next two input codes are to be thrown out. ; cmp al,0E1H ; see if this is a pause/break jne short ??notpcode ; not a pause/break start code mov [(KeyboardType PTR esi).LastKeyE1],3 ; absorb this and next two codes ??notpcode: cmp [(KeyboardType PTR esi).LastKeyE1],0 ; are we in a pause/break code je short ??notpause ; no, just keep going dec [(KeyboardType PTR esi).LastKeyE1] ; yes, dec the count test edx,PAUSEON ; should it pass these codes jne ??passcode ; pass the code jmp ??absorbcode ; don't pass code ??notpause: ; ; Record any extended key codes that arrive. They will be ; taken into account with the next code. ; cmp al,0E0H ; is it an extended code jne short ??notextcode ; if not skip to handle key mov [(KeyboardType PTR esi).LastKeyE0],TRUE ; set the extended code to 1 ??jmppasscode: jmp ??passcode ; always pass E0s ??notextcode: ; ; Check and acknowledge if the key is a make or a break. ; test al,080H ; test for high bit je short ??make ; if off its a make xor bl,bl ; set make/break to break and al,07FH ; clear high bit or ah,KEYRELEASE ; CDY NEW -- ABSENT IN OLD CODE ??make: ; ; Translate the raw keycode into the Westwood keycode. ; cmp [(KeyboardType PTR esi).LastKeyE0],FALSE ; was the prev byte an E0? je short ??normal ; if not it is a normal key mov [(KeyboardType PTR esi).LastKeyE0],FALSE ; if so clear for next read mov [(KeyboardType PTR esi).IsExtKey],TRUE ; it is an extended key mov edi,OFFSET (KeyboardType PTR 0).ExtCodes add edi,esi mov ecx,(OFFSET (KeyboardType PTR 0).ExtNums-OFFSET (KeyboardType PTR 0).ExtCodes) ; get number of entrys in ext table repne scasb ; look for a match jcxz ??absorbcode ; Not recognized, so throw it away. mov al,[(OFFSET (KeyboardType PTR 0).ExtNums - OFFSET (KeyboardType PTR 0).ExtCodes) - 1 + edi] ; get the match mov [(KeyboardType PTR esi).IsExtKey],FALSE ; it is not an extended key jmp short ??notext ??normal: cmp al,07Ah jne short ??normok mov al,128 jmp short ??notext ??normok: mov edi,eax ; use code as an index and edi,007Fh ; Mask off any release bit. mov al,[(KeyboardType PTR esi+edi).KeyNums] ; get the key number of this key ??notext: ; ; Test and set the CTRL bit. ; test [(KeyboardType PTR esi+8).KeysUpDown],001H ; is the right ctrl down? jne short ??ctrlon ; if so, ctrl is on test [(KeyboardType PTR esi+7).KeysUpDown],004H ; is the left ctrl down? je short ??ctrloff ; if not, neither are down, no ctrl ; DRD ; check for CTRL-NUMLOCK for pause on some keyboards cmp al,KN_NUMLOCK ; check for CTRL-NUMLOCK jne short ??ctrlon cmp [(KeyboardType PTR esi).ExtKeyboard],TRUE ; if 101/102-key keyboard it is ok je short ??ctrlon test edx,PAUSEON ; should it pass these codes jne short ??ctrlon ; pass the code jmp ??absorbcode ; don't pass code ??ctrlon: or ah,CTRLPRESS ; or on the ctrl bit in flags ??ctrloff: ; ; Test and set the ALT bit. ; test [(KeyboardType PTR esi+7).KeysUpDown],050H ; is either alt key down? je short ??altoff or ah,ALTPRESS ; or on the alt bit in flags ??altoff: ;------ Set the shift bit if necessary. test [(KeyboardType PTR esi+5).KeysUpDown],010H ; is the left shift down? jne short ??shifton ; if so the shift is on test [(KeyboardType PTR esi+7).KeysUpDown],002H ; is the right shift down? je short ??shiftoff ; if not then neither shift is down ??shifton: or ah,SHIFTPRESS ; or on the shift bit in flags ??shiftoff: ; ;------ Toggle the shift state if the caps lock key is on (if necessary). ; mov edi,eax and edi,07Fh shr edi,3 mov ebx,eax and ebx,07Fh and bl,0111b mov ch,[(KeyboardType PTR esi+ebx).Bits] ; get the bit to test test [(KeyboardType PTR esi).KeyLock],CAPSLOCK ; is the caps lock on? je short ??capsoff ; if not don't worry about it test ch,[(KeyboardType PTR esi+edi).KeysCapsLock] ; get code for keycaps je short ??capsoff ; its not effected xor ah,SHIFTPRESS ; toggle the shift flag ??capsoff: ; ;------ Toggle the shift state if the num-lock key is on (if necessary). ; test [(KeyboardType PTR esi).KeyLock],NUMLOCK ; is the num lock key on? je short ??numlockoff ; if not don't worry about it test ch,[(KeyboardType PTR esi+edi).KeysNumLock] ; get code for numlock je short ??numlockoff ; if not effected skip toggle xor ah,SHIFTPRESS ; toggle the shift flag if effected ??numlockoff: ;------ Remember the current control/shift/alt bit settings for later use. ;??noshiftever: mov [(KeyboardType PTR esi).CtrlFlags],ah ; save off shift-ctrl-alt flags ; for the mouse and joystick routines ; to use in stuffing key into the ; keyboard buffer. ; ; Remap the keyboard keys if this is requested. (Do not set DGROUP ; as it is unecessary) push eax call KeyNum_Translate add esp,4 mov ecx,eax xor eax,eax mov ax,cx test edx,DEBUGINT jz ??not_toggle cmp [(KeyboardType PTR esi).KeyIntDisabled],1 jne ??not_currently_disabled inc [BYTE PTR 0B0002h] cmp eax,115 ; is it the F4 key je ??disable cmp eax,118 ; is it less then F7 key jb ??justpass cmp eax,120 ; is it greater than F9 key ja ??justpass ??disable: mov [(KeyboardType PTR esi).KeyIntDisabled],0 ??justpass: jmp ??passcode ??not_currently_disabled: cmp eax,125 jne ??not_toggle inc [BYTE PTR 0B0000h] mov [(KeyboardType PTR esi).KeyIntDisabled],1 jmp ??absorbcode ??not_toggle: ;------ The CTRL-ALT-DEL key combination always gets passed to the system. cmp eax,0668H ; is it ctrl alt del? je ??passcode cmp eax,064CH ; is it ctrl alt ext del? je ??passcode ; if so don't add it to the buffer ;------ Special Ctrl-C check. cmp eax,0230h je short ??breaker cmp eax,027Eh jne short ??nobreak ??breaker: mov [(KeyboardType PTR esi).Break],1 ??nobreak: ;------ Check for Music and Sound control keys. ; cmp ax,0420H ; is this an alt s ; jne short ??checkmusic ; toggle the Sound variable ; push ax ; mov ax,[SoundOn] ; xor ax,01H ; push ax ; add sp,2 ; pop ax ;??checkmusic: ; cmp ax,0434H ; is this an alt m ; jne short ??esc ; toggle the Music variable ; push ax ; mov ax,[MusicOn] ; xor ax,01H ; push ax ; add sp,2 ; pop ax ;??esc: push eax call Stuff_Key_Num pop eax ??skipstuff: ;------ Do the special ESC routine if necessary. cmp al,110 ; is this the esc key? jne short ??noroutine ; if not goto the pass always cmp [(KeyboardType PTR esi).EscRoutine],0 ;if vector is 0 don't jump je short ??noroutine push eax call [(KeyboardType PTR esi).EscRoutine] pop eax ??noroutine: ;------ Check to see if the key is to be passed to the system or not. mov edi,OFFSET (KeyboardType PTR 0).PassAlways ; get offset to table add edi,esi mov ecx,(OFFSET (KeyboardType PTR 0).PassAlwaysEnd - OFFSET (KeyboardType PTR 0).PassAlways) ; get number of pass always CDY JLB MOD 7/11 was repne scasb ; look for a match or ecx,ecx ; see if there was no match jne ??passcode ; CDY JLB 7/11 optimization ??passalways: ; now check for conditional passes mov edi,OFFSET (KeyboardType PTR 0).CondPassKey ; get offset to cond key table add edi,esi mov ecx,(OFFSET (KeyboardType PTR 0).CondPassCond-OFFSET (KeyboardType PTR 0).CondPassKey) ; get number of entries shr ecx,1 ; cut in half for words repne scasw ; look for a match jcxz short ??notcondpass ; OPTIMIZATION CDY JLB mov bx,[(OFFSET (KeyboardType PTR 0).CondPassCond - OFFSET (KeyboardType PTR 0).CondPassKey) - 2 + edi] and bx,dx ; are the conditions met? je short ??notcondpass ; NO... check normally. jmp short ??passcode ; YES... pass back to system. ; ;------ Last check before passing keycode back to the system. ; ??notcondpass: test edx,FILTERONLY ; is the filter only flag on? je short ??absorbcode ; if not, absorb the code. ??passcode: inc [(KeyboardType PTR esi).PassCount] mov [(KeyboardType PTR esi).PMIssuedKeyInt],1 ; Make it TRUE ; Now it is time to set up for the call to the System Keyboard ; interrupt handler. ; 1 -Restore System Stack Pointer Selector before exit Interrupt ; 2- We Create a Returning Point from Interrupt by Push A ; Interupt Stack Frame into the Stack Pointer ; 3- We make a Far jump to the interuupt handler cmp [Keyboard_StackPointer],0DEADDEADh je ??pass_stack_good push ecx push edi push eax mov edi,0A0000h mov ecx,64000 mov eax,1 rep stosb pop eax pop edi pop ecx ??pass_stack_good: cli ; disable Interrupts mov edx, [Keyboard_App_Stack_SS] mov ss, dx ; Set System Stack Selector mov esp, [Keyboard_App_Stack_ESP] ; Set System Stack offset sti ; Enable Interrupts lea edx, [??Call_Back_Keyboard] ; Get Return address offset pushfd ; push flags push cs ; push Code Selector push edx ; push Offset ; Now we need to simulate an interrup call by using ired ; because we still want to come back here from the ; Old Keyboard interrupt handle. pushfd push [(KeyboardType PTR esi).KeyOldPMISelector] ; push orig selector. push [(KeyboardType PTR esi).KeyOldPMIOffset] ; push orig offset. iretd ??absorbcode: in al,KEYCTRL ; get the control port mov ah,al or al,080H ; reset bit for keyboard out KEYCTRL,al xchg ah,al ; get orig control data out KEYCTRL,al ; restore control data mov al,[496h] ; get extended keys and al,0FDh ; turn off last key e0 flag mov [496h],al ; set extended keys mov al,CLEARISR ; value to clear In Service Register out INTCHIP0,al ; 8259 interrupt chip controller 0 cmp [Keyboard_StackPointer],0DEADDEADh je ??call_stack_good push ecx push edi push eax mov edi,0A0000h mov ecx,64000 mov eax,1 rep stosb pop eax pop edi pop ecx ??call_stack_good: ; Restore System Stack Pointer Selector before exit Interrupt mov edx, [Keyboard_App_Stack_SS] cli ; disable Interrupts mov ss, dx ; Set System Stack Selector mov esp, [Keyboard_App_Stack_ESP] ; Set System Stack offset sti ; Enable Interrupts ??Call_Back_Keyboard: pop fs gs es ds popad iret ENDP Keyboard_Interrupt ELSE ;*************************************************************************** ;* KEYBOARD_INTERRUPT -- Stub for the keyboard interrupt call real mode * ;* * ;* INPUT: none * ;* * ;* OUTPUT: none * ;* * ;* WARNINGS: This is an interrupt routine. * ;* * ;* HISTORY: * ;* 07/06/1994 SKB : Created. * ;*=========================================================================* DATASEG STRUC RealModeCallStruc _EDI DD 0 _ESI DD 0 _EBP DD 0 DD 0 _EBX DD 0 _EDX DD 0 _ECX DD 0 _EAX DD 0 FLAGS DW 0 _ES DW 0 _DS DW 0 _FS DW 0 _GS DW 0 _IP DW 0 _CS DW 0 _SP DW 0 _SS DW 0 dd 0 dd 0 nothing dd 0 ENDS RMDS RealModeCallStruc <> CODESEG PROC Keyboard_Interrupt Near ; This option of the keyboard interrupt handle will not be ; available at this moment because the light version of Rational System DOS ; Extender do not allow a DPMI real mode call which is ; DMPI INT 31h funtion 0301h pushad push fs gs es ds mov ax , _DATA mov es , ax mov ds , ax lea edi , [ RMDS ] lea ecx , [ RMDS . nothing ] sub ecx , edi xor eax , eax shr ecx , 2 rep stosd mov eax , 0300h mov bl , [ byte ptr RMVector ] xor bh , bh xor cx , cx lea edi , [RMDS] int DPMI_INTR ; this is here only for testing to make sure ; that a real mode interrupt is bieng issued. mov ax , _DATA mov es , ax mov ds , ax mov [ byte ptr 0b0000h + 10 * 80 + 40 ] , 040h jc ??error mov [ byte ptr 0b0000h + 10 * 80 + 42 ] , 041h ??error: pop ds es gs fs popad iretd ENDP ENDIF LABEL LockedCodeEnd BYTE ;*************************************************************************** ;* End of File. * ;*************************************************************************** END