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