| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023 |
- ;
- ; 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 : 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
|