; ============================================================================= ; ; Litos8 keyboard driver ; ; ============================================================================= ; ----------------------------------------------------------------------------- ; Exported user functions (42): ; SetLang - set language ; GetLang - get current language ; TestChar - test if some character is ready ; GetChar - get character without waiting ; GetCharWait - get character with waiting ; TestKey - test if some key is ready ; GetKey - get key without waiting ; GetKeyWait - get key with waiting ; KeyIsModi - check if key is modifier ; TestKeyModi - test if some key is ready (incl. modifiers Ctrl,Alt...) ; GetKeyModi - get key without waiting (including modifiers Ctrl, Alt...) ; GetKeyModiWait - get key with waiting (including modifiers Ctrl,Alt...) ; KeyGetModi - get keyboard modifiers ; KeySetModi - set keyboard modifiers (and LEDs) ; KeyFlush - flush keyboard buffer ; IsScrollLock - check Scroll Lock state ; IsNumLock - check Num Lock state ; IsCapsLock - check Caps Lock state ; IsInsert - check Insert state ; IsPause - check Pause state ; KeySetRate - set keyboard rate ; ReturnKey - return key into keyboard buffer ring (as first key) ; SetKey - write key into keyboard buffer ring (as last key) ; GetKeyMap - get bitmap of pressed keys ; KeyPressed - test if key is pressed ; CtrlPressed - test if left or right Ctrl is pressed ; LCtrlPressed - test if left Ctrl is pressed ; RCtrlPressed - test if right Ctrl is pressed ; AltPressed - test if left or right Alt is pressed ; LAltPressed - test if left Alt is pressed ; RAltPressed - test if right Alt is pressed ; ShiftPressed - test if left or right Shift is pressed ; LShiftPressed - test if left Shift is pressed ; RShiftPressed - test if right Shift is pressed ; ScanFromKey - get base scan code from key code ; ExtFromKey - get extended scan code from key code ; ModiFromKey - get modifiers from key code ; ScanModiFromKey - get extended scan code with modifiers from key code ; CharFromKey - get character code from key code ; SetTimer2Gate - set Timer 2 gate ; GetTimer2Out - get Timer 2 output ; SetSpeakerGate - set speaker gate ; ----------------------------------------------------------------------------- KEY_IRQ EQU 1 ; IRQ for keyboard KEYDATA EQU 60h ; data port, read scan code of key, ; bit 7: release key ; If PB7=1: read switches ; write commands to keyboard: ; 0edh: set LEDs, follows: ; B0: Scroll Lock is ON ; B1: Num Lock is ON ; B2: Caps Lock is ON ; 0eeh: send echo 0eeh back ; 0f3h: set key rate, follows: ; B0..4: rate ; 0->30 ... 1fh->2.0 ; B5,B6: delay ; 0->250ms ... 3->1sec ; B7: must be 0 ; 0f4H: enable keyboard ; 0f5h: disable keyboard ; 0f6h: set default params, ; continue tests ; 0feh: repeat last data ; 0ffh: keyboard reset KEYCTRLB EQU 61h ; control port B, read and write: ; B0: timer 2 gate 1=ON, 0=OFF ; B1: speaker gate 1=ON, 0=OFF ; B2: 0=read spare key (port C) ; 1=read r/w memory size ; B3: LED 1=ON, 0=OFF ; B4: mem.par.check 1=OFF,0=ON ; B5: I/O check 1=OFF,0=ON ; B6: keyb.clock 1=enab,0=dis ; B7: 1=clear keyb, read SW1 KEYCTRL EQU 64h ; control port, write: ; 20h: send controller's command ; byte to 60h ; 60h: next byte written to port ; 60h sets contr. command ; 0adh: disable keyboard ; 0aeh: enable keyboard ; status port, read: ; B0: 0=can read data from 60h ; B1: 0=can write to port 64h ; ------------- macro - check if key is pressed (sets NZ = key is pressed) ; Clears CF (-> NC). %macro KEYISPRESSED 1 test byte [KeyMap + (%1 >> 3)],(1 << (%1 & 7)) %endmacro CODEINIT_SECTION ; ----------------------------------------------------------------------------- ; INIT: Initialize keyboard driver (display should be initialized first) ; ----------------------------------------------------------------------------- ; INPUT: AL = required language (LANG_EN, LANG_CZ) ; ----------------------------------------------------------------------------- ; ------------- set keyboard modifiers (and update keyboard layout) KeyInit: mov byte [KeyLayoutSel],255 ; invalid keyboard layout mov byte [Language],255 ; invalid language mov byte [KeyModi],KEY_MODI_NUM ; Num Lock is ON call SetLang ; set language ; ------------- set keyboard rate (to maximum) xor ax,ax ; AX <- 0 call KeySetRate ; set keyboard rate ; ------------- install INT 09h interrupt handler mov ax,Int09 ; AX <- handler address mov cl,9 ; CL <- number of Int 09h call SysSetInt ; set interrupt handler ret CODE_SECTION ; ----------------------------------------------------------------------------- ; Reinitialize keyboard driver ; ----------------------------------------------------------------------------- KeyReinit: push ax ; push AX push cx ; push CX mov ax,Int09 ; AX <- handler address mov cl,9 ; CL <- number of Int 09h call SysSetInt ; set interrupt handler pop cx ; pop CX pop ax ; pop AX ret ; ----------------------------------------------------------------------------- ; Set Timer 2 gate ; ----------------------------------------------------------------------------- ; INPUT: AL = Timer 2 gate 1=enable, 0=disable ; NOTES: It temporaly disables interrupts. ; It takes aprox. 3 us. ; ----------------------------------------------------------------------------- ; ------------- push registers SetTimer2Gate: pushf ; push flags push ax ; push AX cli ; disable interrupts ; ------------- set Timer 2 gate mov ah,al ; AH <- required flag in al,KEYCTRLB ; AL <- get keyboard controller B and al,~B0 ; disable old flag or al,ah ; AL <- set new flag out KEYCTRLB,al ; set speaker gate ; ------------- pop registers pop ax ; pop AX popf ; pop flags ret ; ----------------------------------------------------------------------------- ; Get Timer 2 output ; ----------------------------------------------------------------------------- ; OUTPUT: AL = Timer 2 output (0 and CY, 1 and NC) ; CY = output is 0 (AL = 0) ; NOTES: Output from Timer 2 must be enabled using SetTimer2Gate. ; It takes aprox. 1.5 us. ; ----------------------------------------------------------------------------- GetTimer2Out: in al,KEYCTRLB ; AL <- get keyboard controller B rol al,1 ; B5 -> B6 rol al,1 ; B5 -> B7 rol al,1 ; B5 -> B0 and al,B0 ; AL <- Timer 2 output cmp al,1 ; set CY if AL = 0 ret ; ----------------------------------------------------------------------------- ; Set speaker gate ; ----------------------------------------------------------------------------- ; INPUT: AL = speaker gate 1=enable, 0=disable ; NOTES: It temporaly disables interrupts. ; It takes aprox. 3 us. ; ----------------------------------------------------------------------------- ; ------------- push registers SetSpeakerGate: pushf ; push flags push ax ; push AX cli ; disable interrupts ; ------------- set speaker gate shl al,1 ; AL <- flag to B1 position mov ah,al ; AH <- required flag in al,KEYCTRLB ; AL <- get keyboard controller B and al,~B1 ; disable old flag or al,ah ; AL <- set new flag out KEYCTRLB,al ; set speaker gate ; ------------- pop registers pop ax ; pop AX popf ; pop flags ret ; ----------------------------------------------------------------------------- ; Set language ; ----------------------------------------------------------------------------- ; INPUT: AL = new language (LANG_EN, LANG_CS) ; NOTES: It temporaly disables interrupts. ; ----------------------------------------------------------------------------- ; ------------- push registers SetLang: pushf ; push flags push ax ; push AX cli ; disable interrupts ; ------------- check if language is changed cmp al,[Language] ; language changed? je short SetLang9 ; language not changed mov [Language],al ; store new language ; ------------- set Scroll Lock mov ah,[KeyModi] ; AH <- current modifiers and ah,~B0 ; AH <- clear Scroll Lock flag and al,B0 ; AL <- new Scroll Lock flag or al,ah ; AL <- new modifiers mov [KeyModi],al ; set new modifiers call UpdateKeyModi ; update modifiers ; ------------- update fonts call UpdateTextFont ; update fonts ; ------------- pop registers SetLang9: pop ax ; pop Ax popf ; pop flags (maybe enable interrupts) ret ; ----------------------------------------------------------------------------- ; Get current language ; ----------------------------------------------------------------------------- ; OUTPUT: AL = current language (LANG_EN, LANG_CS) ; ----------------------------------------------------------------------------- GetLang: mov al,[Language] ; AL <- current language ret ; ----------------------------------------------------------------------------- ; Set keyboard modifiers (and LEDs) ; ----------------------------------------------------------------------------- ; INPUT: AL = keyboard modifiers (KEY_MODI_SCROLL, ...) ; NOTES: It temporaly disables interrupts. ; ----------------------------------------------------------------------------- KeySetModi: mov [KeyModi],al ; set keyboard modifiers call UpdateKeyModi ; update modifiers push ax ; push AX and al,B0 ; AL <- Scroll Lock flag call SetLang ; set language pop ax ; pop AX ret ; ----------------------------------------------------------------------------- ; Update LEDs of modifiers ; ----------------------------------------------------------------------------- ; NOTES: It temporaly disables interrupts. ; ----------------------------------------------------------------------------- ; ------------- check, if LEDs need to be changed UpdateKeyModi: push ax ; push AX mov al,[KeyModi] ; AL <- keyboard modifiers and al,B0+B1+B2 ; mask LEDs cmp al,[KeyLED] ; change? je short UpdateKeyModi4 ; no change needed ; ------------- disable interupts pushf ; push flags cli ; disable interrupts ; ------------- send LED command to keyboard mov al,0edh ; AL <- command call KeySendData ; send command mov al,[KeyModi] ; AL <- keyboard modifiers and al,B0+B1+B2 ; mask LEDs mov [KeyLED],al ; save new state call KeySendData ; send LED state mov al,0f4h ; AL <- command to re-enable keyboard call KeySendData ; send enable command ; ------------- pop registers popf ; pop flags (maybe enable interrupts) UpdateKeyModi4: pop ax ; pop AX ; ------------- update keyboard layout ; === UpdateKeyLayout must follow ! ; ----------------------------------------------------------------------------- ; Update current keyboard layout (after changing Scroll Lock) ; ----------------------------------------------------------------------------- ; ------------- push registers UpdateKeyLayout:push ax ; push AX push bx ; push BX ; ------------- prepare required layout mov al,[KeyModi] ; Al <- current modifiers and al,B0 ; AL <- Scroll Lock state cmp al,[KeyLayoutSel] ; check current layout set je short UpdateKeyLay8 ; layout is set OK mov [KeyLayoutSel],al ; store new current layout ; ------------- prepare descriptor -> BX mov ah,KEYLAYOUT_size ; AH <- size of keyboard layout mul ah ; AX <- offset of descriptor xchg ax,bx ; BX <- offset of descriptor lea bx,[KeyLayoutTabs+bx] ; BX <- descriptor ; ------------- opdate current structure mov ax,[bx+KEYLAYOUT_LOWER] ; AX <- lower table mov [KeyMapLower],ax ; set lower table mov ax,[bx+KEYLAYOUT_UPPER] ; AX <- upper table mov [KeyMapUpper],ax ; set upper table mov ax,[bx+KEYLAYOUT_CTRL] ; AX <- control table mov [KeyMapCtrl],ax ; set control table mov ax,[bx+KEYLAYOUT_LOWUP] ; AX <- lower/upper table mov [KeyMapLowUp],ax ; set lower/upper table mov al,[bx+KEYLAYOUT_DCH1] ; AL <- dead character 1 mov [KeyMapDCh1],al ; set dead character 1 mov al,[bx+KEYLAYOUT_DCH2] ; AL <- dead character 2 mov [KeyMapDCh2],al ; set dead character 2 mov ax,[bx+KEYLAYOUT_DEAD1] ; AX <- dead table 1 mov [KeyMapDead1],ax ; set dead table 1 mov ax,[bx+KEYLAYOUT_DEAD2] ; AX <- dead table 2 mov [KeyMapDead2],ax ; set dead table 2 mov ax,[bx+KEYLAYOUT_SPEC] ; AX <- special RAlt table mov [KeyMapSpec],ax ; set special RAlt table mov byte [KeyDeadChar],0 ; destroy dead character mov byte [KeyAltChar],0 ; no Alt char. code ; ------------- pop registers UpdateKeyLay8: pop bx ; pop BX pop ax ; pop AX ret ; ----------------------------------------------------------------------------- ; Get bitmap of pressed keys ; ----------------------------------------------------------------------------- ; OUTPUT: BX = pointer to 256-bit system key map, 1=key is pressed ; NOTES: Use extended scan code as index into key bitmap. ; ----------------------------------------------------------------------------- GetKeyMap: mov bx,KeyMap ; BX <- pointer to key map ret ; ----------------------------------------------------------------------------- ; Get keyboard modifiers ; ----------------------------------------------------------------------------- ; OUTPUT: AL = keyboard modifiers (KEY_MODI_SCROLL, ...) ; ----------------------------------------------------------------------------- KeyGetModi: mov al,[KeyModi] ; AL <- keyboard modifiers ret ; ----------------------------------------------------------------------------- ; Check Scroll Lock state ; ----------------------------------------------------------------------------- ; OUTPUT: AL = Scroll Lock state (0=OFF and CY, 1=ON and NC) ; CY = Scroll Lock is OFF (AL = 0) ; ----------------------------------------------------------------------------- IsScrollLock: mov al,[KeyModi] ; AL <- keyboard modifiers and al,B0 ; AL <- Scroll Lock state cmp al,1 ; set CY flag ret ; ----------------------------------------------------------------------------- ; Check Num Lock state ; ----------------------------------------------------------------------------- ; OUTPUT: AL = Num Lock state (0=OFF and CY, 1=ON and NC) ; CY = Num Lock is OFF (AL = 0) ; ----------------------------------------------------------------------------- IsNumLock: mov al,[KeyModi] ; AL <- keyboard modifiers shr al,1 ; AL <- rotate flag to B0 position and al,B0 ; AL <- Num Lock state cmp al,1 ; set CY flag ret ; ----------------------------------------------------------------------------- ; Check Caps Lock state ; ----------------------------------------------------------------------------- ; OUTPUT: AL = Caps Lock state (0=OFF and CY, 1=ON and NC) ; CY = Caps Lock is OFF (AL = 0) ; ----------------------------------------------------------------------------- IsCapsLock: mov al,[KeyModi] ; AL <- keyboard modifiers shr al,1 shr al,1 ; AL <- rotate flag to B0 position and al,B0 ; AL <- Caps Lock state cmp al,1 ; set CY flag ret ; ----------------------------------------------------------------------------- ; Check Insert state ; ----------------------------------------------------------------------------- ; OUTPUT: AL = Insert state (0=OFF and CY, 1=ON and NC) ; CY = Insert is OFF (AL = 0) ; ----------------------------------------------------------------------------- IsInsert: mov al,[KeyModi] ; AL <- keyboard modifiers shr al,1 shr al,1 shr al,1 ; AL <- rotate flag to B0 position and al,B0 ; AL <- Insert state cmp al,1 ; set CY flag ret ; ----------------------------------------------------------------------------- ; Check Pause state ; ----------------------------------------------------------------------------- ; OUTPUT: AL = Pause state (0=OFF and CY, 1=ON and NC) ; CY = Pause is OFF (AL = 0) ; ----------------------------------------------------------------------------- IsPause: mov al,[KeyModi] ; AL <- keyboard modifiers shr al,1 shr al,1 shr al,1 shr al,1 ; AL <- rotate flag to B0 position and al,B0 ; AL <- Pause state cmp al,1 ; set CY flag ret ; ----------------------------------------------------------------------------- ; Set keyboard rate ; ----------------------------------------------------------------------------- ; INPUT: AL = rate coefficient (0..31, 0->30 key/sec ... 31->2 key/sec) ; AH = initial delay (0..3, 0->250 ms ... 3->1000 ms) ; NOTES: It temporaly disables interrupts. ; ----------------------------------------------------------------------------- ; 0f3h: set key rate, follows: ; B0..4: rate ; 0->30 ... 1fh->2.0 ; B5,B6: delay ; 0->250ms ... 3->1sec ; B7: must be 0 ; ------------- push registers and disable interupts KeySetRate: pushf ; push flags push ax ; push AX cli ; disable interrupts ; ------------- prepare rate data ror ah,1 ror ah,1 ror ah,1 ; AH <- rotate delay to position B5,B6 or ah,al ; AH <- add rate ; ------------- send RATE command to keyboard mov al,0f3h ; AL <- command call KeySendData ; send command mov al,ah ; AL <- rate data call KeySendData ; send rate data mov al,0f4h ; AL <- command to re-enable keyboard call KeySendData ; send enable command ; ------------- pop registers pop ax ; pop AX popf ; pop flags (maybe enable interrupts) ret ; ----------------------------------------------------------------------------- ; Test if left Ctrl is pressed ; ----------------------------------------------------------------------------- ; OUTPUT: AL = key status, 1=pressed (NC), 0=released (CY) ; CY = key is not pressed (AL = 0) ; ----------------------------------------------------------------------------- LCtrlPressed: KEYISPRESSED KEY_LCTRL ; check if left Ctrl is pressed LCtrlPressed2: jz short LCtrlPressed6 ; key is not pressed LCtrlPressed4: mov al,1 ; AL <- pressed flag ret LCtrlPressed6: mov al,0 ; AL <- 0, released flag stc ; set released flag ret ; ----------------------------------------------------------------------------- ; Test if left or right Ctrl is pressed ; ----------------------------------------------------------------------------- ; OUTPUT: AL = key status, 1=pressed (NC), 0=released (CY) ; CY = key is not pressed (AL = 0) ; ----------------------------------------------------------------------------- CtrlPressed: KEYISPRESSED KEY_LCTRL ; check if left Ctrl is pressed jnz short LCtrlPressed4 ; left Ctrl is pressed ; === RCtrlPressed must follow ! ; ----------------------------------------------------------------------------- ; Test if right Ctrl is pressed ; ----------------------------------------------------------------------------- ; OUTPUT: AL = key status, 1=pressed (NC), 0=released (CY) ; CY = key is not pressed (AL = 0) ; ----------------------------------------------------------------------------- RCtrlPressed: KEYISPRESSED KEY_RCTRL ; check if right Ctrl is pressed jmp short LCtrlPressed2 ; ----------------------------------------------------------------------------- ; Test if left Alt is pressed ; ----------------------------------------------------------------------------- ; OUTPUT: AL = key status, 1=pressed (NC), 0=released (CY) ; CY = key is not pressed (AL = 0) ; ----------------------------------------------------------------------------- LAltPressed: KEYISPRESSED KEY_LALT ; check if left Alt is pressed jmp short LCtrlPressed2 ; ----------------------------------------------------------------------------- ; Test if left or right Alt is pressed ; ----------------------------------------------------------------------------- ; OUTPUT: AL = key status, 1=pressed (NC), 0=released (CY) ; CY = key is not pressed (AL = 0) ; ----------------------------------------------------------------------------- AltPressed: KEYISPRESSED KEY_LALT ; check if left Alt is pressed jnz short LCtrlPressed4 ; left Alt is pressed ; === RAltPressed must follow ! ; ----------------------------------------------------------------------------- ; Test if right Alt is pressed ; ----------------------------------------------------------------------------- ; OUTPUT: AL = key status, 1=pressed (NC), 0=released (CY) ; CY = key is not pressed (AL = 0) ; ----------------------------------------------------------------------------- RAltPressed: KEYISPRESSED KEY_RALT ; check if right Alt is pressed jmp short LCtrlPressed2 ; ----------------------------------------------------------------------------- ; Test if left Shift is pressed ; ----------------------------------------------------------------------------- ; OUTPUT: AL = key status, 1=pressed (NC), 0=released (CY) ; CY = key is not pressed (AL = 0) ; ----------------------------------------------------------------------------- LShiftPressed: KEYISPRESSED KEY_LSHIFT ; check if left Shift is pressed jmp short LCtrlPressed2 ; ----------------------------------------------------------------------------- ; Test if left or right Shift is pressed ; ----------------------------------------------------------------------------- ; OUTPUT: AL = key status, 1=pressed (NC), 0=released (CY) ; CY = key is not pressed (AL = 0) ; ----------------------------------------------------------------------------- ShiftPressed: KEYISPRESSED KEY_LSHIFT ; check if left Shift is pressed jnz short LCtrlPressed4 ; left Shift is pressed ; === RShiftPressed must follow ! ; ----------------------------------------------------------------------------- ; Test if right Shift is pressed ; ----------------------------------------------------------------------------- ; OUTPUT: AL = key status, 1=pressed (NC), 0=released (CY) ; CY = key is not pressed (AL = 0) ; ----------------------------------------------------------------------------- RShiftPressed: KEYISPRESSED KEY_RSHIFT ; check if right Shift is pressed jmp short LCtrlPressed2 ; ----------------------------------------------------------------------------- ; Test if key is pressed ; ----------------------------------------------------------------------------- ; INPUT: AL = key extended scan code ; OUTPUT: AL = key status, 1=pressed (NC), 0=released (CY) ; CY = key is not pressed (AL = 0) ; ----------------------------------------------------------------------------- ; ------------- push registers KeyPressed: push bx ; push BX push cx ; push CX ; ------------- prepare offset in table -> BX xor bx,bx ; BX <- 0 mov bl,al ; BL <- key code mov cl,3 ; CL <- number of rotations shr bx,cl ; BX /= 8 ; ------------- get key state -> AL mov cl,al ; CL <- key code and cl,7 ; CL <- lowest 3 bits mov al,[bx+KeyMap] ; AL <- get key state shr al,cl ; AL <- shift bit on position 0 and al,B0 ; mask bit cmp al,1 ; set CY of not pressed ; ------------- pop registers pop cx ; pop CX pop bx ; pop BX ret ; ----------------------------------------------------------------------------- ; Get base scan code from key code ; ----------------------------------------------------------------------------- ; INPUT: AX = key code ; OUTPUT: AL = base scan code (0..7Fh) ; ----------------------------------------------------------------------------- ScanFromKey: mov al,ah ; AL <- key HIGH and al,7fh ; AL <- mask scan code ret ; ----------------------------------------------------------------------------- ; Get extened scan code from key code ; ----------------------------------------------------------------------------- ; INPUT: AX = key code ; OUTPUT: AL = extended scan code (0..0FFh) ; ----------------------------------------------------------------------------- ExtFromKey: or ax,ax ; control key ? jns short ScanFromKey ; base ASCII character shl al,1 ; CY <- extended flag mov al,ah ; AL <- code HIGH rcl al,1 ; AL,B0 <- extended flag ror al,1 ; AL <- extended scan code ret ; ----------------------------------------------------------------------------- ; Get modifiers from key code ; ----------------------------------------------------------------------------- ; INPUT: AX = key code ; OUTPUT: AL = modifiers (0..7), B0=Shift, B1=Ctrl, B2=Alt ; ----------------------------------------------------------------------------- ModiFromKey: or ax,ax ; control key? jns short ModiFromKey2 ; not control key and al,KEYFLAG_MODI ; AL <- modifiers B4,B5,B6 shr al,1 shr al,1 shr al,1 shr al,1 ; AL <- modifiers B0,B1,B2 ret ModiFromKey2: mov al,0 ; AL <- 0, no (unkown) modifiers ret ; ----------------------------------------------------------------------------- ; Get extended scan code with modifiers from key code ; ----------------------------------------------------------------------------- ; INPUT: AX = key code ; OUTPUT: AL = extended scan code (0..0FFh) ; AH = modifiers (0..7), B0=Shift, B1=Ctrl, B2=Alt ; ----------------------------------------------------------------------------- ScanModiFromKey:or ax,ax ; control key? jns short ScanModiFrmKey2 ; not control key shl al,1 ; CY <- extended flag rcl ah,1 ; AH,B0 <- extended flag ror ah,1 ; AH <- extended scan code rol al,1 rol al,1 rol al,1 ; AL <- modifiers to B0,B1,B2 and al,7 ; AL <- mask modifiers xchg al,ah ; AH <- modifiers, AL <- scan code ret ScanModiFrmKey2:mov al,ah ; AL <- key HIGH and ax,7fh ; AX <- scan code ret ; ----------------------------------------------------------------------------- ; Get character from key code ; ----------------------------------------------------------------------------- ; INPUT: AX = key code ; OUTPUT: AL = character (0..0ffh) ; ----------------------------------------------------------------------------- CharFromKey: or ax,ax ; control key? jns short CharFromKey2 ; not control key push bx ; push BX mov bx,KeyCharTab ; BX <- character table and al,KEYFLAG_MASK ; AL <- mask table character xlat ; AL <- character from table pop bx ; pop BX CharFromKey2: ret ; ----------------------------------------------------------------------------- ; Check if key is modifier ; ----------------------------------------------------------------------------- ; INPUT: AX = key code ; OUTPUT: NC = key is modifier (Cltr,ALt,Shift,x Lock) ; ----------------------------------------------------------------------------- ; ------------- push registers KeyIsModi: push ax ; push AX mov al,ah ; AL <- scan code and al,7fh ; mask base scan code ; ------------- check modifier cmp al,KEY_CTRL ; Left or Right Ctrl je short KeyIsModi4 cmp al,KEY_ALT ; Left or Right Alt je short KeyIsModi4 cmp al,KEY_LSHIFT ; Left Shift je short KeyIsModi4 cmp al,KEY_RSHIFT ; Right Shift je short KeyIsModi4 cmp al,KEY_CAPSLOCK ; Caps Lock je short KeyIsModi4 cmp al,KEY_NUMLOCK ; Num Lock je short KeyIsModi4 cmp al,KEY_SCROLL ; Scroll Lock je short KeyIsModi4 stc ; set error flag ; ------------- pop registers KeyIsModi4: pop ax ; pop AX ret ; ----------------------------------------------------------------------------- ; Test if some key is ready ; ----------------------------------------------------------------------------- ; OUTPUT: AX = key code, 0=no key (CY) ; CY = no key (AX = 0) ; NOTES: Key is not removed from keyboard buffer. ; It temporaly disables interrupts. ; ----------------------------------------------------------------------------- ; Entry point to function is TestKey ! TestKey0: call GetKeyModi ; destroy modifier in buffer TestKey: call TestKeyModi ; test key with modifiers jc short TestKey4 ; no key call KeyIsModi ; check if key is modifier jnc short TestKey0 ; destroy modifier clc ; clear error flag TestKey4: ret ; ----------------------------------------------------------------------------- ; Get key without waiting (without modifiers Ctrl, Alt...) ; ----------------------------------------------------------------------------- ; OUTPUT: AX = key code, 0=no key (CY) ; CY = no key (AX = 0) ; NOTES: It temporaly disables interrupts. ; ----------------------------------------------------------------------------- GetKey: call GetKeyModi ; get key with modifiers jc short GetKey4 ; no key call KeyIsModi ; check if key is modifier jnc short GetKey ; destroy modifier clc ; clear error flag GetKey4: ret ; ----------------------------------------------------------------------------- ; Get key with waiting (without modifiers Ctrl, Alt...) ; ----------------------------------------------------------------------------- ; OUTPUT: AX = key code ; NOTES: It temporaly disables interrupts. ; ----------------------------------------------------------------------------- GetKeyWait: call GetKey ; get key jc short GetKeyWait ; wait for a key ret ; ----------------------------------------------------------------------------- ; Test if some character is ready ; ----------------------------------------------------------------------------- ; OUTPUT: AL = character, 0=no character (CY) ; CY = no character (AL = 0) ; NOTES: Character is not removed from keyboard buffer. ; It temporaly disables interrupts. ; ----------------------------------------------------------------------------- ; ------------- push registers TestChar: push cx ; push CX xchg ax,cx ; CH <- push AH ; ------------- input character -> AL TestChar2: call TestKeyModi ; test key with modifiers jc short TestChar4 ; no key call CharFromKey ; get character from key or al,al ; is it valid character? jnz short TestChar4 ; it is valid character call GetKeyModi ; destroy key from buffer jmp short TestChar2 ; next key ; ------------- pop registers TestChar4: mov ah,ch ; AH <- pop AH pop cx ; pop CX ret ; ----------------------------------------------------------------------------- ; Get character without waiting ; ----------------------------------------------------------------------------- ; OUTPUT: AL = character, 0=no character (CY) ; CY = no character (AL = 0) ; NOTES: It temporaly disables interrupts. ; ----------------------------------------------------------------------------- ; ------------- push registers GetChar: push cx ; push CX xchg ax,cx ; CH <- push AH ; ------------- input character -> AL GetChar2: call GetKeyModi ; get key with modifiers jc short GetChar4 ; no key call CharFromKey ; get character from key or al,al ; is it valid character? jz short GetChar2 ; invalid character ; ------------- pop registers GetChar4: mov ah,ch ; AH <- pop AH pop cx ; pop CX ret ; ----------------------------------------------------------------------------- ; Get character with waiting ; ----------------------------------------------------------------------------- ; OUTPUT: AL = character (1..0ffh) ; NOTES: It temporaly disables interrupts. ; ----------------------------------------------------------------------------- GetCharWait: call GetChar ; get character jc short GetCharWait ; wait for a character ret ; ----------------------------------------------------------------------------- ; Test if some key is ready (including modifiers Ctrl, Alt...) ; ----------------------------------------------------------------------------- ; OUTPUT: AX = key code, 0=no key (CY) ; CY = no key (AX = 0) ; NOTES: Key is not removed from keyboard buffer. ; It temporaly disables interrupts. ; ----------------------------------------------------------------------------- ; ------------- push registers TestKeyModi: pushf ; push flags push bx ; push BX cli ; disable interrupts ; ------------- check if there are any key in the buffer xor ax,ax ; AX <- 0, preset invalid key mov bl,[KeyReadInx] ; BX <- read index from buffer cmp bl,[KeyWriteInx] ; check buffer je short GetKeyModi8 ; no data in buffer ; ------------- read key from the buffer mov bh,0 ; BH <- 0 shl bx,1 ; BX <- offset in bufer mov ax,[KeyBuff+bx] ; read key from buffer ; ------------- pop registers TestKeyModi8: pop bx ; pop BX popf ; pop flags (maybe enable interrupts) cmp ax,1 ; set CY if no key ret ; ----------------------------------------------------------------------------- ; Get key without waiting (including modifiers Ctrl, Alt...) ; ----------------------------------------------------------------------------- ; OUTPUT: AX = key code, 0=no key (CY) ; CY = no key (AX = 0) ; NOTES: It temporaly disables interrupts. ; ----------------------------------------------------------------------------- ; ------------- push registers GetKeyModi: pushf ; push flags push bx ; push BX cli ; disable interrupts ; ------------- check if there are any key in the buffer xor ax,ax ; AX <- 0, preset invalid key mov bl,[KeyReadInx] ; BX <- read index from buffer cmp bl,[KeyWriteInx] ; check buffer je short GetKeyModi8 ; no data in buffer ; ------------- read key from the buffer mov bh,0 ; BH <- 0 shl bx,1 ; BX <- offset in bufer mov ax,[KeyBuff+bx] ; read key from buffer ; ------------- increase read index shr bx,1 ; BX <- offset in buffer inc bx ; increase offset in buffer and bl,KEYBUFMASK ; BL <- mask offset mov [KeyReadInx],bl ; set new read index ; ------------- pop registers GetKeyModi8: pop bx ; pop BX popf ; pop flags (maybe enable interrupts) cmp ax,1 ; set CY if no key ret ; ----------------------------------------------------------------------------- ; Flush keyboard buffer ; ----------------------------------------------------------------------------- ; NOTES: It temporaly disables interrupts. ; ----------------------------------------------------------------------------- ; ------------- push registers KeyFlush: pushf ; push flags push ax ; push AX cli ; disable interrupts ; ------------- destroy keys in buffer mov al,[KeyWriteInx] ; AL <- read index mov [KeyReadInx],al ; destroy keys in buffer ; ------------- pop registers pop ax ; pop AX popf ; pop flags (maybe enable interrupts) ret ; ----------------------------------------------------------------------------- ; Get key with waiting (including modifiers Ctrl, Alt...) ; ----------------------------------------------------------------------------- ; OUTPUT: AX = key code ; NOTES: It temporaly disables interrupts. ; ----------------------------------------------------------------------------- GetKeyModiWait: call GetKeyModi ; get key with modifiers jc short GetKeyModiWait ; wait for a key ret ; ----------------------------------------------------------------------------- ; Return key into keyboard ring buffer (as first key) ; ----------------------------------------------------------------------------- ; INPUT: AX = key code (should not be 0) ; NOTES: It temporaly disables interrupts. ; ----------------------------------------------------------------------------- ; ------------- push registers ReturnKey: pushf ; push flags push bx ; push BX cli ; disable interrupts ; ------------- shift read index down mov bh,0 ; BH <- 0 mov bl,[KeyReadInx] ; BL <- read index from buffer dec bx ; decrease read index and bl,KEYBUFMASK ; BL <- mask offset ; ------------- check buffer overrun cmp bl,[KeyWriteInx] ; check write index jne short ReturnKey4 ; no overrun dec byte [KeyReadInx] ; shift write index and byte [KeyReadInx],KEYBUFMASK ; mask write index ReturnKey4: mov [KeyReadInx],bl ; set new read index ; ------------- write key into buffer shl bx,1 ; BX <- offset in bufer mov [KeyBuff+bx],ax ; write key into buffer ; ------------- pop registers pop bx ; pop BX popf ; pop flags (maybe enable interrupts) ret ; ----------------------------------------------------------------------------- ; Write key into keyboard ring buffer (as last key) ; ----------------------------------------------------------------------------- ; INPUT: AX = key code (should not be 0) ; NOTES: It temporaly disables interrupts. ; ----------------------------------------------------------------------------- ; ------------- push registers SetKey: pushf ; push flags push bx ; push BX cli ; disable interrupts ; ------------- write key into ring buffer mov bh,0 ; BH <- 0 mov bl,[KeyWriteInx] ; BL <- write index into buffer shl bx,1 ; BX <- offset in bufer mov [KeyBuff+bx],ax ; write key into buffer ; ------------- shift write index shr bx,1 ; BX <- offset in buffer inc bx ; increase offset in buffer and bl,KEYBUFMASK ; BL <- mask offset ; ------------- check buffer overrun cmp bl,[KeyReadInx] ; check read index jne short SetKey4 ; no overrun inc byte [KeyReadInx] ; shift read index and byte [KeyReadInx],KEYBUFMASK ; mask read index SetKey4: mov [KeyWriteInx],bl ; set new write index ; ------------- pop registers pop bx ; pop BX popf ; pop flags (maybe enable interrupts) ret ; ----------------------------------------------------------------------------- ; Wait for releasing send buffer ; ----------------------------------------------------------------------------- ; NOTES: Interrupt must be disabled. ; ----------------------------------------------------------------------------- ; ------------- push registers KeySendWait: push ax ; push AX push cx ; push CX ; ------------- wait for byte to accept mov cx,10000 ; CX <- timeout KeySendWait2: in al,KEYCTRL ; AL <- read controller status test al,B1 ; output buffer redy? loopnz KeySendWait2 ; wait to release send buffer ; ------------- pop registers pop cx ; pop CX pop ax ; pop AX ret ; ----------------------------------------------------------------------------- ; Send command to keyboard controller ; ----------------------------------------------------------------------------- ; INPUT: AL = byte to send ; NOTES: Interrupt must be disabled. ; ----------------------------------------------------------------------------- KeySendCmd: call KeySendWait ; wait for releasing send buffer out KEYCTRL,al ; send byte to keyboard ret ; ----------------------------------------------------------------------------- ; Send data to keyboard ; ----------------------------------------------------------------------------- ; INPUT: AL = byte to send ; NOTES: Interrupt must be disabled. ; ----------------------------------------------------------------------------- KeySendData: call KeySendWait ; wait for releasing send buffer out KEYDATA,al ; send data to keyboard ret ; ----------------------------------------------------------------------------- ; Interrupt Int 09h handler ; ----------------------------------------------------------------------------- ; ------------- push registers Int09: push ax ; push AX push bx ; push BX push cx ; push CX push si ; push SI push ds ; push DS push es ; push ES ; ------------- initialize segment registers push cs ; push CS pop ds ; DS <- CS push cs ; push CS pop es ; ES <- CS ; ------------- maximum number of keys received at once -> CX mov cx,10 ; CX <- max. number of keys mov si,KeyModi ; SI <- keyboard modifiers ; ------------- check if controller has any data Int092: in al,KEYCTRL ; AL <- read keyboard controller status test al,B0 ; any data byte pending? jnz short Int0923 ; valid data jmp Int099 ; no data byte ready ; ------------- read keyboard data -> AL Int0923: mov ah,al ; AH <- save controller status in al,KEYDATA ; AL <- scan code ; ------------- data error test ah,B6+B7 ; data error? jnz short Int09Next4 ; data error, get next data ; ------------- ignore no key, echo, acknowledge and error control codes or al,al ; no key? jz short Int09Next4 ; no key cmp al,0eeh ; control code? jae short Int09Next4 ; ignore control codes ; ------------- shift random generator with AX code call RandShift ; shift random generator ; ------------- extended code E1 cmp al,0e1h ; extended prefix E1? jne short Int093 ; no E1 mov byte [KeyPrefix],1 ; set E1 prefix flag jmp short Int09Next4 ; next code ; ------------- prefix E1 already set - ignore this key and change to E0 Int093: cmp byte [KeyPrefix],1 ; E1 prefix already set? je short Int094 ; E1 prefix, change to E0 prefix ; ------------- extended code E0 cmp al,0e0h ; extended prefix E0? jne short Int095 ; no E0 Int094: mov byte [KeyPrefix],80h ; set E0 prefix flag Int09Next4: jmp short Int09Next2 ; next code ; ------------- prepare key code -> AL, save release flag -> AH Int095: mov ah,al ; AH <- release flag (in B7) and al,7fh ; reset release flag or al,[KeyPrefix] ; add 80h flag mov byte [KeyPrefix],0 ; reset key prefix ; ------------- ignore fake Shifts (auto generated by keyboard) cmp al,KEY_LSHIFT2 ; fake Left Shift ? je short Int09Next2 ; ignore fake Left Shift cmp al,KEY_RSHIFT2 ; fake Right Shift ? je short Int09Next2 ; ignore fake Right Shift ; ------------- prepare offset in map table -> BX, and mask -> CH xor bx,bx ; BX <- 0 mov bl,al ; BL <- key code mov cl,3 ; CL <- number of rotations shr bx,cl ; BX /= 8 lea bx,[bx+KeyMap] ; BX <- map address mov cl,al ; CL <- key code and cl,7 ; CL <- lowest 3 bits mov ch,B0 ; CH <- mask shl ch,cl ; CH <- shift mask on position ; ------------- Lock correction - don't flip state on repeat or ah,ah ; press key? js short Int0958 ; no test [bx],ch ; already pressed? jz short Int0958 ; no cmp al,KEY_SCROLL ; Scroll Lock ? jne short Int0952 ; no xor byte [si],KEY_MODI_SCROLL ; pre-flip Scroll Lock flag Int0952: cmp al,KEY_NUMLOCK ; Num Lock ? jne short Int0953 ; no xor byte [si],KEY_MODI_NUM ; pre-flip Num Lock flag Int0953: cmp al,KEY_CAPSLOCK ; Caps Lock ? jne short Int0954 ; no xor byte [si],KEY_MODI_CAPS ; pre-flip Caps Lock flag Int0954: cmp al,KEY_INSERT ; Insert ? jne short Int0955 ; no xor byte [si],KEY_MODI_INSERT ; pre-flip Insert flag Int0955: cmp al,KEY_PAUSE ; Pause ? jne short Int0958 ; no xor byte [si],KEY_MODI_PAUSE ; pre-flip Pause flag ; ------------- press key Int0958: or [bx],ch ; set flag to be pressed ; ------------- release key or ah,ah ; release key ? jns short Int096 ; release key ; ------------- reset bit in map xor [bx],ch ; clear flag ; ------------- release Alt with numeric key cmp al,KEY_RALT ; Right Alt ? je short Int09582 ; yes cmp al,KEY_LALT ; Left Alt ? jne short Int09Next2 ; no Int09582: cmp byte [KeyAltChar],0 ; valid character? je short Int09Next2 ; no mov ah,0 mov al,[KeyAltChar] ; AL <- character mov byte [KeyAltChar],0 ; clear register jmp Int0988 ; store character Int09Next2: jmp Int09Next ; next key ; ------------- Scroll Lock Int096: cmp al,KEY_SCROLL ; Scroll Lock ? jne short Int0962 ; no mov al,[si] ; AL <- modifiers xor al,KEY_MODI_SCROLL ; change Scroll Lock flag mov [si],al ; save new flags and al,B0 ; AL <- Scroll Lock flag call SetLang ; set language mov al,KEY_SCROLL ; AL <- Scroll Lock jmp short Int0965 ; update LEDs ; ------------- Num Lock Int0962: cmp al,KEY_NUMLOCK ; Num Lock ? jne short Int0963 ; no xor byte [si],KEY_MODI_NUM ; change Num Lock flag jmp short Int0964 ; update LEDs ; ------------- Caps Lock Int0963: cmp al,KEY_CAPSLOCK ; Caps Lock ? jne short Int0965 ; no xor byte [si],KEY_MODI_CAPS ; change Caps Lock flag Int0964: call UpdateKeyModi ; update LEDs ; ------------- Insert Int0965: cmp al,KEY_INSERT ; Insert ? jne short Int0966 ; no xor byte [si],KEY_MODI_INSERT ; flip Insert flag ; ------------- Pause Int0966: cmp al,KEY_PAUSE ; Pause ? jne short Int0967 ; no xor byte [si],KEY_MODI_PAUSE ; flip Pause flag ; ------------- map Alt modifiers Int0967: mov ah,al ; AH <- key code call AltPressed ; check if Alt is pressed jc short Int09675 ; Alt is not pressed ; ------------- RAlt special characters mov al,0 ; AL <- 0, Alt flag KEYISPRESSED KEY_RALT ; check if right Alt is pressed jz short Int09673 ; RAlt is not pressed mov bx,[KeyMapSpec] ; BX <- special table Int09672: mov cx,[bx] ; CL <- scan code, CH <- character jcxz Int09673 ; end of table inc bx inc bx ; BX <- shift pointer cmp ah,cl ; check scan code jne short Int09672 ; next code mov al,ch ; AL <- character ; ------------- Alt + numberic character code Int09673: cmp ah,47h ; first numeric key jb short Int09674 ; not numeric key cmp ah,52h ; last numeric key ja short Int09674 ; not numeric key mov bx,KeyCharNumTab - 47h ; BX <- values of keys xchg ax,cx ; CH <- push AH mov ah,10 ; AH <- multiplier mov al,[KeyAltChar] ; AL <- old code mul ah ; AX <- shift value xchg ax,cx ; CX <- value, AH <- scan code mov al,ah ; AL <- scan code xlat ; AL <- key value add al,cl ; AL <- new value mov [KeyAltChar],al ; set new value jmp short Int09Next2 ; destroy character Int09674: jmp Int09837 ; Alt is pressed ; ------------- prepare index of key in mapping table -> CH Int09675: mov ch,KEYMAP_LEN ; CH <- remap ext. 1 cmp ah,KEYMAP_EXT1 ; extended character 1 ? je short Int0968 mov ch,KEYMAP_LEN+1 ; CH <- remap ext. 2 cmp ah,KEYMAP_EXT2 ; extended character 2 ? je short Int0968 mov ch,KEYMAP_LEN+2 ; CH <- remap ext. 3 cmp ah,KEYMAP_EXT3 ; extended character 3 ? je short Int0968 mov ch,0 ; CH <- default mapping cmp ah,KEYMAP_LEN ; check maximal code jae short Int0968 ; use default mapping mov ch,ah ; CH <- key code ; ------------- map Ctrl modifiers Int0968: call CtrlPressed ; check if Ctrl is pressed jc short Int0969 ; Ctrl is not pressed mov al,ch ; AL <- mapping index mov bx,[KeyMapCtrl] ; BX <- mapping table xlat ; AL <- remap Ctrl key jmp short Int0982 ; code key ; ------------- prepare Num Lock modification -> BL Int0969: xor bx,bx ; BX <- 0 cmp ah,47h ; first key jb short Int0972 ; not numeric key cmp ah,53h ; last key ja short Int0972 ; not numeric key mov bl,[KeyModi] ; BL <- modificators shr bl,1 ; BL <- NUm Lock into B0 and bl,B0 ; BL <- Num Lock B0 flag ; ------------- prepare mapping address -> BX, and default code -> AL Int0972: call ShiftPressed ; check if Shift is pressed xor al,bl ; check Num Lock shift mov bx,[KeyMapLower] ; BX <- lower case jz short Int0973 ; Shift it not pressed mov bx,[KeyMapUpper] ; BX <- upper case ; ------------- remap character -> AL Int0973: mov al,ch ; AL <- mapping index xlat ; AL <- remap character ; ------------- Caps Lock service Int0975: test byte [KeyModi],KEY_MODI_CAPS ; Caps Lock is ON ? jz short Int0982 ; Caps Lock is not ON call UpperLowerCaseNat ; change character upper/lower ; ------------- dead character Int0982: or al,al ; valid character? jz short Int09838 ; not valid character cmp [KeyMapDCh1],al ; dead character 1? jne short Int09832 ; no cmp al,[KeyDeadChar] ; already set? je short Int09837 ; character will be generated mov [KeyDeadChar],al ; set new dead character jmp short Int09Next ; next character Int09832: cmp [KeyMapDCh2],al ; dead character 2? jne short Int09834 ; no cmp al,[KeyDeadChar] ; already set? je short Int09837 ; character will be generated mov [KeyDeadChar],al ; set new dead character jmp short Int09Next ; next character Int09834: mov cl,[KeyDeadChar] ; CL <- current dead character or cl,cl ; dead character is set? jz short Int09838 ; no dead character mov bx,[KeyMapDead1] ; BX <- table 1 cmp cl,[KeyMapDCh1] ; check dead character 1 je short Int09835 ; use table 1 mov bx,[KeyMapDead2] ; BX <- table 2 Int09835: mov cx,[bx] ; CL <- ASCII character, CH <- accent jcxz Int09837 ; end of table inc bx inc bx ; BX <- increase pointer in table cmp al,cl ; character found? jnz short Int09835 ; continue with another character mov al,ch ; AL <- substitute with new character ; ------------- check control character (extended scans must be tabled!) Int09837: mov byte [KeyDeadChar],0 ; destroy dead character Int09838: mov cx,16 ; CX <- number of tabled characters mov bx,KeyCharTab-1 ; BX <- table of characters Int0984: inc bx ; BX <- new offset in table cmp al,[bx] ; is character in table? loopne Int0984 ; find character jne short Int0987 ; need no coding ; ------------- code control character AH:AL mov al,15 sub al,cl ; AL <- tabled code Int0985: mov ch,ah ; CH <- scan code and ch,80h ; CH <- extended flag or ah,80h ; AH <- set control flag or ch,al ; CH <- add extended flag call AltPressed ; check Alt modifier ror al,1 ror al,1 ; AL <- flag on B6 or ch,al ; CH <- add Alt flag call CtrlPressed ; check Ctrl modifier ror al,1 ror al,1 ror al,1 ; AL <- flag on B5 or ch,al ; CH <- add Ctrl flag call ShiftPressed ; check Shift modifier ror al,1 ror al,1 ror al,1 ror al,1 ; AL <- flag on B4 or al,ch ; AL <- modifiers jmp short Int0988 ; ------------- write key into buffer Int0987: and ah,7fh ; clear control flag Int0988: call SetKey ; write key into kyboard ring buffer ; ------------- try next key Int09Next: dec cx ; counter jz short Int099 ; end jmp Int092 ; next key ; ------------- enable interrupt controller Int099: in al,21h ; release interrupt controller 1 mov al,60h+KEY_IRQ ; AL <- keyboard IRQ out 20h,al ; acknowledge interrupt ; ------------- pop registers pop es ; pop ES pop ds ; pop DS pop si ; pop SI pop cx ; pop CX pop bx ; pop BX pop ax ; pop AX iret ; ----------------------------------------------------------------------------- ; Constant data ; ----------------------------------------------------------------------------- CONST_SECTION ; ------------- tabled characters KeyCharTab: db 0 ; 0: no character db 08h ; 1: BS, Ctrl+H, BackSpace db 09h ; 2: TAB, Ctrl+I db 0Ah ; 3: LF, Ctrl+J db 0Dh ; 4: CR, Ctrl+M, Enter db 1Bh ; 5: ESC, Ctrl+[ db 1Ch ; 6: FSEP,Ctrl+"\" db 1Dh ; 7: GSEP, Ctrl+] db 1Eh ; 8: RSEP, Ctrl+^ db 1Fh ; 9: USEP, Ctrl+_ db 20h ; 10: SPACE db 2Ah ; 11: "*" db 2Bh ; 12: "+" db 2Dh ; 13: "-" db 2Fh ; 14: "/" db 7Fh ; 15: DEL ; ------------- values of numeric keys KeyCharNumTab: db 7 ; 47h [7 Home] db 8 ; 48h [8 Up] db 9 ; 49h [9 PgUp] db 0 ; 4Ah Gray [-] db 4 ; 4Bh [4 Left] db 5 ; 4Ch [5] db 6 ; 4Dh [6 Right] db 0 ; 4Eh Gray [+] db 1 ; 4Fh [1 End] db 2 ; 50h [2 Down] db 3 ; 51h [3 PgDn] db 0 ; 52h [0 Ins] ; ----------------------------------------------------------------------------- ; Uninitialised data ; ----------------------------------------------------------------------------- DATA_SECTION align 4, resb 1 KeyBuff: resw KEYBUFSIZE ; key ring buffer KeyWriteInx: resb 1 ; write index into buffer KeyReadInx: resb 1 ; read index from buffer KeyPrefix: resb 1 ; 80h:prefix flag E0,01h:prefix flag E1 align 4, resb 1 KeyMap: resb KEYMAPSIZE ; keys map (1=key is pressed) KeyModi: resb 1 ; keyb. modifiers (KEY_MODI_SCROLL,...) KeyLED: resb 1 ; current LED state KeyDeadChar: resb 1 ; dead character (0=none) KeyAltChar: resb 1 ; char. code with Alt+[0]..[9] (0=none) ; ------------- current keyboard layout Language: resb 1 ; current language (LANG_EN, LANG_CZ) KeyLayoutSel: resb 1 ; index of current keyboard layout align 2, resb 1 KeyLayout: ; --- KEYLAOUT structure KeyMapLower: resw 1 ; pointer to current lower table KeyMapUpper: resw 1 ; pointer to current upper table KeyMapCtrl: resw 1 ; pointer to current control table KeyMapLowUp: resw 1 ; pointer to current lower/upper table KeyMapDCh1: resb 1 ; dead character 1 (0=none) KeyMapDCh2: resb 1 ; dead character 2 (0=none) KeyMapDead1: resw 1 ; pointer to dead table 1 KeyMapDead2: resw 1 ; pointer to dead table 2 KeyMapSpec: resw 1 ; special RAlt table