CnC_Red_Alert/WIN32LIB/KEYBOARD/OLD/KEYBOARD.ASM

2521 lines
84 KiB
NASM

;
; 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 <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** 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.
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
??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
; This routine will do what it needs to,
; then it will decide if the old vector should be called.
; if so, it calls it and never returns to this function.
; if not, we do our own return.
; the method for doing this is found in:
; "Phar Lap TNT DOS-Extender Reference Manual, First Addition, p. 142"
; It says:
; 1 - Execute a PUSHFD to save the current flags.
; 2 - Dec the stack ptr by 8 bytes to save room for the addr of orig handler
; 3 - Push register I use.
; 4 - Do any processing.
; 5 - Put the address of the original handler in the reserved slot.
; 6 - Pop saved register values
; 7 - Execute an IRETD to transfer control to original 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.
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
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:
;
; Remap the keyboard keys if this is requested. (Do not set DGROUP
; as it is unecessary)
push eax
call KeyNum_Translate
add esp,4
;------ 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.
mov ecx,eax
xor eax,eax
mov ax,cx
IF DEBUG
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
ENDIF
??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]
; Step 5.
; Now it is time to set up for the call by returning by poking
; the old interupt handle address in.
mov [(KeyboardType PTR esi).PMIssuedKeyInt],1 ; Make it TRUE
mov eax,[(KeyboardType PTR esi).KeyOldPMIOffset] ; Get orig offset.
mov ebx,[(KeyboardType PTR esi).KeyOldPMISelector] ; Get orig selector.
mov [ss:ebp+4],eax ; Poke offset.
mov [ss:ebp+8],ebx ; Poke selector.
; Step 6.
pop fs gs es ds
popad
pop ebp
; Step 7.
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
pop fs gs es ds
popad
pop ebp
add esp,8
popfd
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