; ; 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 : KEYINTR.ASM * ;* * ;* Programmer : Christopher Yates * ;* * ;* Start Date : May 21, 1992 * ;* * ;* Last Update : July 13, 1994 [PWG] * ;* * ;*-------------------------------------------------------------------------* ;* Functions: * ;* KeyNum_Translate -- Translates the given keynum to ??? * ;* Install_Interrupt -- Installs the keyboard interrupt * ;* Stuff_Key_Word -- Stuffs a word of data into keyboard buffer * ;* Stuff_Key_Num -- Stuffs a key num code into the circular buffer * ;* Remove_Interrupt -- Removes the keyboard interrupt and restores the chai* ;* Keystroke_Interrupt -- Handles input that comes from the keyboard * ;* Break_Interrupt -- Handles the break key interrupt * ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ;* * ;* Keyboard driver -- 8086 Assembly portion; * ;* updated by: Phil Gorrow for 32 bit Protected Mode * ;*************************************************************************** ;--------------------------------------------------------------------------- ; Set the assembly directives ;--------------------------------------------------------------------------- IDEAL ; the product runs in ideal mode P386N ; use 386 real mode instructions MODEL TINY ; code must be tiny so it fits LOCALS ?? ; ?? is the symbol for a local WARN ; generate all warnings we can JUMPS ; optimize jumps if possible ;--------------------------------------------------------------------------- ; Include all of the keyboard specific defines ;--------------------------------------------------------------------------- INCLUDE "keyboard.inc" CODESEG SoundOn DW 1 ; toggled by alt S MusicOn DW 1 ; toggled by alt M KeyFlags DW REPEATON+CTRLALTTURBO ; all but repeat for now Break DW 0 KeyMouseMove DB -1,0,1 DB -16,0,16 ScreenEdge DW 320/2,0 ; North DW 319,0 ; North-East DW 319,138/2 ; East DW 319,137 ; South-East DW 320/2,137 ; South DW 0,137 ; South-West DW 0,138/2 ; West DW 0,0 ; North-West DW 320/2,138/2 ; Center Bits DB 01H,02H,04H,08H,10H,20H,40H,80H CondPassKey DW 0220H, 0320H, 060CH, 070DH, 066AH DW 0669H, 0230H, 0330H, 007DH, 017DH DW 025AH, 035AH, 0200H, 0410H, 046EH DW 026EH, 007CH CondPassCond DW CTRLSON, CTRLSON, CTRLALTTURBO, CTRLALTTURBO, CTRLALTTURBO DW CTRLALTTURBO, CTRLCON, CTRLCON, SCROLLLOCKON, SCROLLLOCKON DW PAUSEON, PAUSEON, BREAKON, TASKSWITCHABLE, TASKSWITCHABLE DW TASKSWITCHABLE, BREAKON EscRoutine DD 0 ; vector to execute on esc key press (0=none) ; Extended raw keycodes to be converted to Westwood keycodes. ExtCodes DB 038H,01DH,052H,053H,04BH,047H,04FH,048H,050H,049H DB 051H,04DH,035H,01CH,037H DB 046H ; The matching Westwood keycodes. ExtNums DB 62, 64, 75, 76, 79, 80, 81, 83, 84, 85 DB 86, 89, 95, 108, 124, 0 ; If extended mapping is disabled, then these codes really are... ExtRemap DB 60, 58, 99, 104, 92, 91, 93, 96, 98, 101 DB 103, 102, 55, 43, 124, 0 ExtRemapEnd DB 0 ExtKeyboard DB 0 ; flag for 101/102-key keyboard KeyBuffer DW 128 DUP(0) ; set to empty KeyBufferHead DW 0 ; set to first entry KeyBufferTail DW 0 ; set to head for empty buffer KeyLock DW 0 ; num and caps lock bits KeyNums DB 127,110,002,003,004,005,006,007,008,009,010,011,012,013,015,016 DB 017,018,019,020,021,022,023,024,025,026,027,028,043,058,031,032 DB 033,034,035,036,037,038,039,040,041,001,044,029,046,047,048,049 DB 050,051,052,053,054,055,057,100,060,061,030,112,113,114,115,116 DB 117,118,119,120,121,090,125,091,096,101,105,092,097,102,106,093 DB 098,103,099,104,127,127,127,122,123 KeysCapsLock DB 0,0,0FEH,087H,0FFH,0C0H,01FH,0,0,0,0,0,0,0,0,0 KeysNumLock DB 0,0,0,0,0,0,0,0,0,0,0,038H,0EFH,1,0,0 KeysUpDown DB 16 DUP(0) ; set to all keys up KeyStream DB 16 DUP(0) ; set to all keys up PassCount DW 0 KeyStreamIndex DW 0 LastKeyE0 DB 0 LastKeyE1 DB 0 ; ; Westwood key number values of keys to pass through ; ; CAPS, LEFT_SHIFT, RIGHT_SHIFT, LEFT_CTRL, LEFT_ALT, ; RIGHT_ALT, RIGHT_CTRL, NUM_LOCK, UNKNOWN PassAlways DB 30, 44, 57, 58, 60, 62, 64, 90, 128, 128 PassAlwaysEnd DB 128 ; invalid code to END PassAlways CtrlFlags DB 0 Buffer DW ? Time DW ? ADJUST = 1 ; do not modify DRD XYAdjust DB -ADJUST, -ADJUST ; 91 -> upleft DB -ADJUST, 0 ; 92 -> left DB -ADJUST, ADJUST ; 93 -> downleft DB 0, 0 ; 94 illegal DB 0, 0 ; 95 illegal DB 0, -ADJUST ; 96 -> up DB 0, 0 ; 97 illegal (center) DB 0, ADJUST ; 98 -> down DB 0, 0 ; 99 illegal DB 0, 0 ; 100 illegal DB ADJUST, -ADJUST ; 101 -> upright DB ADJUST, 0 ; 102 -> right DB ADJUST, ADJUST ; 103 -> downright EdgeConv DW 8,2,8,6,4,3,8,5,8,8,8,8,0,1,8,7 MouseUpdate DW 0 MouseX DW 0 LocalMouseX DW 0 MouseY DW 0 LocalMouseY DW 0 Button DW 0 IsExtKey DB 0 ExtIndex DW 0 OldRMI DD 0 ; The origianl RM interrupt seg:off. OldPMIOffset DD 0 ; The origianl PM interrupt offset OldPMISelector DD 0 ; The original PM interrupt segment. CodeOffset DW RM_Keystroke_Interrupt ; Offset of the code in the RM stuff. CallRMIntOffset DW Call_Interrupt_Chain ; Offset of function to call DOS timer interrupt. CallRMIntAddr DD 0 ; PM address of CallRealIntOffset for speed. ;*************************************************************************** ;* KEYNUM_TRANSLATE -- Translates the given keynum to ??? * ;* * ;* INPUT: UWORD the keynum to translate * ;* * ;* OUTPUT: WORD the translated keynum * ;* * ;* PROTO: UWORD KeyNum_Translate(UWORD keynum); * ;* * ;* HISTORY: * ;* 07/11/1994 PWG : Created. * ;*=========================================================================* GLOBAL KeyNum_Translate:FAR PROC KeyNum_Translate C FAR USES cx,di,es,ds ARG keycode:WORD mov ax,cs ; since we are in tiny model mov ds,ax ; set cs = ds mov es,ax ; set es up for scansb mov ax,[keycode] test [KeyFlags],TRACKEXT jne short ??fini mov cx,ExtRemap-ExtNums mov di,OFFSET ExtNums repne scasb jcxz short ??fini ; No match found. mov di,OFFSET ExtRemapEnd dec di sub di,cx mov al,[es:di] ??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(WORD code); * ;* * ;* HISTORY: * ;* 07/11/1994 PWG : Created. * ;*=========================================================================* GLOBAL C Stuff_Key_WORD:FAR PROC Stuff_Key_WORD C FAR USES si,bx,ds ARG code:WORD mov ax,cs ; since we are in tiny model mov ds,ax ; set cs = ds mov ax,[KeyBufferTail] mov si,ax add ax,2 and ax,0FFh ; New KeyBufferTail value. cmp [KeyBufferHead],ax je short ??noroom mov bx,[code] mov [KeyBuffer+si],bx ; Record the keystroke. mov [KeyBufferTail],ax xor ax,ax ret ??noroom: mov ax,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(WORD keynum); * ;* * ;* HISTORY: * ;* 07/11/1994 PWG : Created. * ;*=========================================================================* GLOBAL C Stuff_Key_Num:FAR PROC Stuff_Key_Num C FAR USES ax,bx,cx,dx,di,si,ds ARG keycode:WORD LOCAL tail:WORD ; Original keybuffer tail (safety copy). LOCAL size:WORD ; Size of write. pushf cli ; disable interrupts ; Abort key recognition if in record mode and unable ; to output key due to simultaneous DOS operation. mov ax,cs ; since we are in tiny model mov ds,ax ; set cs = ds ; Record the mouse position to be stuffed into buffer. mov ax,[MouseX] mov [LocalMouseX],ax mov ax,[MouseY] mov [LocalMouseY],ax ??cando: mov ax,[keycode] ; get the code or ax,ax ; Null keycodes are not recorded. jne short ??validkey jmp ??exit ??validkey: test [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 [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 [Button],1 ; Left mouse bit. test ah,KEYRELEASE je ??mousefake and [Button],NOT 1 jmp ??mousefake ??regular: cmp al,KN_DELETE jne short ??regular2 mov al,KN_RMOUSE or [Button],2 ; Right mouse bit. test ah,KEYRELEASE je ??mousefake and [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 sub al,KN_UPLEFT ; get a number between 0 and 12 mov bx,ax shl bx,1 ; double for WORD index add bx,OFFSET XYAdjust mov ax,[bx] ; get x,y add value mov bl,ah cbw xchg ax,bx cbw xchg ax,bx ; AX = mouse x delta, BX = mouse y delta ; 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 dx,1 ; for slow speed test ch,SHIFTPRESS ; is either shift key down? je short ??normspeed ; if not then neither shift is down ??doublespeed: add dx,3 ; for fast speed ??normspeed: add bx,dx ; add speed for y index mov bl,[KeyMouseMove+bx] ; get speed for y delta xchg ax,bx ; swap with ax to extend sign cbw xchg ax,bx xchg bx,dx ; save mouse y delta add bx,ax ; add speed for x index mov al,[KeyMouseMove+bx] ; get speed for x delta cbw xchg bx,dx ; 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 bx,011b ; Y = 1, 0, 3 and ax,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 bx,011b ; Y = 3, 0, 1 and ax,011b ; X = 3, 0, 1 shl bx,1 shl bx,1 or bx,ax ; Lookup index. ; Convert raw index into logical (clockwise) index. shl bx,1 mov bx,[EdgeConv+bx] shl bx,1 shl bx,1 mov ax,[ScreenEdge+bx] ; New absolute X mov bx,[ScreenEdge+bx+2] ; New absolute Y mov [LocalMouseX],ax mov [LocalMouseY],bx ??set_xyz: mov ax,[LocalMouseX] ; get new mouse x,y mov bx,[LocalMouseY] jmp short ??set_xy ; Process a normal faked mouse move. ??ctrloff: ; DRD change add [LocalMouseX],ax ; save it in our local jns short ??not_negative_x xor ax,ax mov [LocalMouseX],ax ; clear our local ??not_negative_x: ; DRD change add [LocalMouseY],bx ; save it in our local jns short ??not_negative_y xor bx,bx mov [LocalMouseY],bx ; clear our local ??not_negative_y: mov ax,[LocalMouseX] ; get new mouse x,y mov bx,[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 [LocalMouseX],ax mov [LocalMouseY],bx mov [MouseX],ax mov [MouseY],bx cmp [MouseUpdate],0 ; wait until mouse interrupt is done jne short ??noshow ; PWG: ARRGGGHHHH! ; call Low_Hide_Mouse ; call Low_Show_Mouse ??noshow: mov ax,KN_MOUSE_MOVE ??mousefake: mov [keycode],ax ; Fake a MOUSE_MOVE event. ??no_pad_move: ; Fetch working pointers to the keyboard ends. mov si,[KeyBufferTail] mov [tail],si ; Safety record. mov di,[KeyBufferHead] ; Record the base keycode (if there is room). push ax call Stuff_Key_WORD add sp,2 or ax,ax jne short ??jmpnoroom ; Also record the mouse coordinates if necessary. mov ax,[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: push [LocalMouseX] call Stuff_Key_WORD add sp,2 or ax,ax jne ??jmpnoroom add [size],2 ; Record mouse coordinate Y. push [LocalMouseY] call Stuff_Key_WORD add sp,2 or ax,ax 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 bx,0101h ; Bit control tools. mov ax,[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 [KeyFlags],PASSBREAKS jne short ??real cmp al,KN_LMOUSE je short ??real cmp al,KN_RMOUSE je short ??real ??notreal: mov [KeyBufferTail],si ; Nullify any KeyBufferTail changes. ??real: ; Update the KeysUpDown bit array. mov di,ax and di,07Fh mov cl,3 shr di,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,[KeysUpDown+di] je short ??notalready test [KeyFlags],REPEATON jne short ??notalready mov [KeyBufferTail],si ; Nullify any KeyBufferTail changes. ??notalready: and [KeysUpDown+di],bh ; Force key bit to zero. or [KeysUpDown+di],bl ; Insert key bit as appropriate. ;??notreal: ; Successful keybuffer stuff could result in a ??norecord: mov ax,1 jmp short ??exit ; Unsuccessful keybuffer stuff. ??noroom: mov ax,[tail] mov [KeyBufferTail],ax xor ax,ax ; Signal an error. ??exit: popf ret ENDP Stuff_Key_Num ;*********************************************************** ;*************************************************************************** ;* KEYSTROKE_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. * ;*=========================================================================* label RM_Keystroke_Interrupt GLOBAL C Keystroke_Interrupt:FAR PROC Keystroke_Interrupt C FAR IF 0 push ax inc ax pop ax iret ELSE push ax push bx push cx push di push ds push dx push es push si cld mov ax,cs ; set ds to cs to avoid cs overide mov ds,ax mov dx,[KeyFlags] ;*** The following fix allows proper caps and num lock tracking on Tandy ; 10-6-89 LJC, DRD and [KeyLock],NOT (NUMLOCK OR CAPSLOCK); assume caps and num inactive mov ax,040H ; BIOS segment mov es,ax ; put in es test [BYTE PTR es:017H],040H ; test Caps lock bit in BIOS je short ??bioscapsoff ; skip activate code or [KeyLock],CAPSLOCK ; Caps Lock active ??bioscapsoff: test [BYTE PTR es:017H],020H ; test Num lock bit in BIOS je short ??biosnumoff ; skip activate code or [KeyLock],NUMLOCK ; Num Lock active ??biosnumoff: mov [ExtKeyboard],TRUE ; assume 101/102-key keyboard test [BYTE PTR es:096H],010H ; test for 101/102-key keyboard jne short ??extkeyboard ; skip deactivate code mov [ExtKeyboard],FALSE ; no 101/102-key keyboard ??extkeyboard: mov ax,cs ; set ds to cs to avoid cs overide mov es,ax cld ; clear direction flag for strings xor ah,ah ; clear ctrl flags to 0 mov bx,0101H ; set key to a make by default in al,KEYDATA ; get a code from the keyboard ; ; New CODE to montior key stream ; mov bx,[KeyStreamIndex] mov [KeyStream+bx],al inc bx and bx,15 mov [KeyStreamIndex],bx mov bx,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 [LastKeyE1],3 ; absorb this and next two codes ??notpcode: cmp [LastKeyE1],0 ; are we in a pause/break code je short ??notpause ; no, just keep going dec [LastKeyE1] ; yes, dec the count test dx,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 [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 [LastKeyE0],FALSE ; was the prev byte an E0? je short ??normal ; if not it is a normal key mov [LastKeyE0],FALSE ; if so clear for next read mov [IsExtKey],TRUE ; it is an extended key mov di,OFFSET ExtCodes ; get offset of extended codes table mov cx,(ExtNums-ExtCodes) ; get number of entrys in ext table repne scasb ; look for a match jcxz ??absorbcode ; Not recognized, so throw it away. mov al,[(ExtNums - ExtCodes) - 1 + di] ; get the match mov [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 di,ax ; use code as an index and di,007Fh ; Mask off any release bit. mov al,[KeyNums+di] ; get the key number of this key ??notext: ; ; Test and set the CTRL bit. ; test [KeysUpDown+8],001H ; is the right ctrl down? jne short ??ctrlon ; if so, ctrl is on test [KeysUpDown+7],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 [ExtKeyboard],TRUE ; if 101/102-key keyboard it is ok je short ??ctrlon test dx,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 [KeysUpDown + 7],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 ax call KeyNum_Translate add sp,2 ;------ Set the shift bit if necessary. test [KeysUpDown+5],010H ; is the left shift down? jne short ??shifton ; if so the shift is on test [KeysUpDown+7],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 di,ax and di,07Fh shr di,1 shr di,1 shr di,1 mov bx,ax and bx,07Fh and bl,0111b mov ch,[Bits+bx] ; get the bit to test test [KeyLock],CAPSLOCK ; is the caps lock on? je short ??capsoff ; if not don't worry about it test ch,[KeysCapsLock+di] ; 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 [KeyLock],NUMLOCK ; is the num lock key on? je short ??numlockoff ; if not don't worry about it test ch,[KeysNumLock+di] ; 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 [CtrlFlags],ah ; save off shift-ctrl-alt flags ; for the mouse and joystick routines ; to use in stuffing key into the ; keyboard buffer. ;------ The CTRL-ALT-DEL key combination always gets passed to the system. cmp ax,0668H ; is it ctrl alt del? je ??passcode cmp ax,064CH ; is it ctrl alt ext del? je ??passcode ; if so don't add it to the buffer ;------ Special Ctrl-C check. cmp ax,0230h je short ??breaker cmp ax,027Eh jne short ??nobreak ??breaker: mov [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 ax call Stuff_Key_Num pop ax ??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 [WORD PTR EscRoutine+2],0 ;if vector is 0 don't jump je short ??noroutine push ax call [EscRoutine] pop ax ??noroutine: ;------ Check to see if the key is to be passed to the system or not. mov di,OFFSET PassAlways ; get offset to table mov cx,(PassAlwaysEnd - PassAlways) ; get number of pass always CDY JLB MOD 7/11 was +1 repne scasb ; look for a match or cx,cx ; see if there was no match jne ??passcode ; CDY JLB 7/11 optimization ??passalways: ; now check for conditional passes mov di,OFFSET CondPassKey ; get offset to cond key table mov cx,(CondPassCond-CondPassKey) ; get number of entries shr cx,1 ; cut in half for words repne scasw ; look for a match jcxz short ??notcondpass ; OPTIMIZATION CDY JLB mov bx,[(CondPassCond - CondPassKey) - 2 + di] 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 dx,FILTERONLY ; is the filter only flag on? je short ??absorbcode ; if not, absorb the code. ;*********************************************************** pushf ; push di ; push es mov ax,0B000h mov es,ax inc [BYTE PTR es:0] ; pop es ; pop di popf ;*********************************************************** ??passcode: pop si pop es pop dx pop ds pop di pop cx pop bx pop ax inc [cs:PassCount] jmp [cs:OldRMI] ??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 ax,040h ; BIOS paragraph is always @ 040h mov es,ax ; put in es as BIOS paragraph mov al,[es:96h] ; get extended keys and al,0FDh ; turn off last key e0 flag mov [es:96h],al ; set extended keys mov al,CLEARISR ; value to clear In Service Register out INTCHIP0,al ; 8259 interrupt chip controller 0 pop si pop es pop dx pop ds pop di pop cx pop bx pop ax iret ENDIF ENDP Keystroke_Interrupt ;*************************************************************************** ;* BREAK_INTERRUPT -- Handles the break key interrupt * ;* * ;* INPUT: none * ;* * ;* OUTPUT: none * ;* * ;* WARNINGS: This is an interrupt routine. * ;* * ;* HISTORY: * ;* 07/13/1994 PWG : Created. * ;*=========================================================================* GLOBAL C Break_Interrupt:FAR PROC Break_Interrupt C FAR iret ENDP Break_Interrupt ;************************************************************************** ;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain* ;* * ;* * ;* INPUT: * ;* * ;* OUTPUT: * ;* * ;* WARNINGS: * ;* * ;* HISTORY: * ;* 07/08/1994 SKB : Created. * ;*=========================================================================* Call_Interrupt_Chain: IF 0 pushf push ax push di push es mov ax,0B000h ; ES:DI = Mono RAM address. mov es,ax mov al,'A' mov ah,2 and di,63 stosw in al,KEYDATA ; get a code from the keyboard mov al,CLEARISR ; value to clear In Service Register out INTCHIP0,al ; 8259 interrupt chip controller 0 pop es pop di pop ax popf ENDIF pushf call Keystroke_Interrupt ;[OldRMI] retf STACK ; Don't really need this ;*********************************************************** END