summaryrefslogtreecommitdiffstats
path: root/private/mvdm/dos/v86/cmd/keyb/keybi9c.asm
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/mvdm/dos/v86/cmd/keyb/keybi9c.asm1768
1 files changed, 1768 insertions, 0 deletions
diff --git a/private/mvdm/dos/v86/cmd/keyb/keybi9c.asm b/private/mvdm/dos/v86/cmd/keyb/keybi9c.asm
new file mode 100644
index 000000000..a30c30082
--- /dev/null
+++ b/private/mvdm/dos/v86/cmd/keyb/keybi9c.asm
@@ -0,0 +1,1768 @@
+PAGE ,132
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; (C) Copyright Microsoft Corp. 1987-1990
+;; MS-DOS 5.00 - NLS Support - KEYB Command
+;;
+; File Name: KEYBI9C.ASM
+; ----------
+;
+;
+; Description:
+; ------------
+; Interrupt 9 mainline.
+; This routine handles all US keyboard support for the following
+; system units: PC, PC-XT, PC-AT, PC Convertible, PC-XT/286
+; Models 25 and 30 (PALACE),
+; PS/2's - all 8042 based 80286, 80386 and 80486.
+; - all PATRIOT and SEBRING based systems.
+; KEYB_STATE_PROCESSOR is called for non-US keyboard support.
+;
+;
+;
+; Procedures Contained in This File:
+; ----------------------------------
+; KEYB_INT_9 - Interrupt 9
+;
+; External Procedure References:
+; ------------------------------
+; FROM FILE KEYBI9.ASM:
+; KEYB_STATE_PROCESSOR - Non US keyboard support.
+;
+; Linkage Information: Refer to file KEYB.ASM
+; --------------------
+;
+; Change History:
+; ---------------
+; ; - DCR 478 - KEYBOARD INT SPLICING Nick Savage ;deleted by AN005
+; ; - PTM 3090 ENABLING RIGHT CTL FOR RE-BOOTING
+; ; - PTM 60XX PICK UP ALL KEYBOARD BIOS PTR's AND DCR's TO BRING
+; INT 9h UP TO THE TOPHAT (80486) SUPPORT LEVEL. '89 jwg
+; PTR 6600736 Keep INT's disabled till after PORT 60h read.
+; PTR 6600756 EXTRA EOI ISSUED IF INTERRUPTS SATURATED **********
+; NOTE: This is a fix for a BIOS bug that goes all
+; the way back to the first AT. The rationale for
+; the fix is as follows:
+; (deleted AN005) A stack frame is created upon entry (BP) and
+; CHK_EOI is called to check the frame. If no
+; EOI has been issued, CHK_EOI does it and
+; resets the frame, preventing any additinal
+; EOI's from being issued on subsequent calls
+; to CHK_EOI. All direct EOI's in the code
+; have been replaced with calls to CHK_EOI.
+;
+; ;Ax004; - PTM 2555 KEYB command locks keyboard. 10/5/89;cja
+; ; jwg 11/09/98 Updates - Wild Mouse, etc workaround.....
+; ; - PTM 5802 Restructure Interrupt Splicing to correct lost Mouse
+; interrupt when LED's are updated. Make it apply to
+; all systems. Essentially remove all code added by AN001.
+; Remove stack frame logic of AN003 and PTR 6600756 and do
+; an early EOI. Requires a CLI at K38B and other places.
+; Remove Chk_ibf before 60h.
+; Re-write ERROR_BEEP to make processor speed independent
+; for AT and PS/2 systems and right tone if interrupts.
+; Make SHIP_IT handle call on PC machines.
+; Use BP to hold system flags during interrupt processing.
+; PTR 6602049 Fix problem with Pause Key hanging system if Mouse
+; driver is using polled mode. (Port 60h hangs.)
+; PTR 6602247 Change JMP at K40 to stop extra Enable Keyboard cmd.
+; PTR 6602319 Fix interrupt window on System Request key allowing
+; following scan code(s) to be processed out of sequence.
+; PTR 6602355 Fix Print Screen clearing E0 state flags too late.
+; ; - ;deleted Add code the clear "Wild Mouse" condition at PAUSE wait.
+; ; - PTM 6660 Move determination code for original PC1 to COMMSUBS.ASM
+; - ;jwg 2/90 Add Patriot/Sebring HOT REPLUG code so keyboard can be
+; switched back to Scan Code Set 1 if repluged. LIB LITE
+; ; - PTM 6680 Remove code attempting to re-sync BIOS flags with reset
+; Keyboard. Test case simulators can/are sending invalid
+; sequence of AA,AA. Must leave BIOS flags alone on POR.
+; ; - PTM 6716 MicroSoft WORKS (German version) reentrancy problem with
+; - ;jwg 3/90 NLS state processor and save scan code. LED update ACK
+; overlays memory before NLS processing of scan code.
+; Remove AN006 "Wild Mouse" reset code, field tests done.
+; ; - PTM ???? Fix read ID logic to recognize 122 keyboards and set the
+; ;jwg 8/90 KBX flag on any enhansed keyboard.
+; ; - PTM ???? Add 122 Keyboard key support tables.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ INCLUDE KEYBEQU.INC
+ INCLUDE DSEG.INC ; System data segments
+ INCLUDE POSTEQU.INC ; System equates
+ INCLUDE KEYBSHAR.INC
+ INCLUDE KEYBI2F.INC
+ INCLUDE KEYBI9.INC
+ INCLUDE KEYBCPSD.INC
+ INCLUDE KEYBCMD.INC
+
+include bop.inc
+include vint.inc
+
+ PUBLIC KEYB_INT_9
+ PUBLIC K8 ; CTRL case tables
+ PUBLIC SCAN_CODE
+ PUBLIC BUFFER_FILL
+ PUBLIC COUNTRY_FLAG
+
+
+ PUBLIC COPY_NLS1_FLAG ;; (YST)
+
+
+ PUBLIC BEEP_PENDING
+ PUBLIC ERROR_BEEP
+ PUBLIC CHK_IBF
+
+
+
+ID_1 EQU 0ABH ; 1ST ID CHARACTER FOR KBX
+TID_2 EQU 041H ; US G-LAYOUT
+TID_2A EQU 054H ; US P-LAYOUT
+
+;UNTRANSLATED 2ND ID CHAR FOR KBDX
+ID_2U EQU 083H ; US G-LAYOUT (PATRIOT)
+ID_2AU EQU 084H ; US P-LAYOUT (PATRIOT)
+ID_122 EQU 086H ; 2ND ID CHARACTER FOR 122-KEYBOARD
+ID_2JG EQU 090H ; JPN G-LAYOUT
+ID_2JP EQU 091H ; JPN P-LAYOUT
+ID_2JA EQU 092H ; JPN A-LAYOUT
+
+
+DIAGS SEGMENT AT 0FFFFH
+ ORG 0
+RESET LABEL FAR
+DIAGS ENDS
+
+
+CODE SEGMENT PUBLIC 'CODE'
+ ASSUME CS:CODE,DS:DATA
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; TABLE OF SHIFT KEYS AND MASK VALUES
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;------ KEY_TABLE
+K6 LABEL BYTE
+ DB INS_KEY ; INSERT KEY
+ DB CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
+ DB LEFT_KEY,RIGHT_KEY
+K6L EQU $-K6
+
+;------ MASK_TABLE
+K7 LABEL BYTE
+ DB INS_SHIFT ; INSERT MODE SHIFT
+ DB CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
+ DB LEFT_SHIFT,RIGHT_SHIFT
+
+;---------- TABLES FOR ALT CASE -----
+;------ ALT-INPUT-TABLE
+K30 LABEL BYTE
+ DB 82,79,80,81,75
+ DB 76,77,71,72,73 ; 10 NUMBERS ON KEYPAD
+;------ SUPER-SHIFT-TABLE
+ DB 16,17,18,19,20,21 ; A-Z TYPEWRITER CHARS
+ DB 22,23,24,25,30,31
+ DB 32,33,34,35,36,37
+ DB 38,44,45,46,47,48
+ DB 49,50
+K30_LEN EQU $-K30-10
+
+;------ ALT-INPUT-FUNCTION-TABLE 53H - 7EH
+K30A LABEL BYTE
+ DB -1,-1,-1,-1,139,140 ; Del, SysReq, Undef, WT, F11, F12
+ DB -1,235,218,219,220 ; Undef, PA1, F13, F14, F15
+ DB -1,-1,-1,-1,-1 ; Pause, Undef 5F-62
+ DB 221,222,223,226,227 ; F16, F17, F18, F19, F20,
+ DB 228,229,230,231 ; F21, F22, F23, F24,
+ DB -1,243,-1,-1 ; K#69, ErEOF, Break, Play,
+ DB -1,-1,-1,-1,-1 ; Undef, Attn, CrSel, K#56, ExSel
+ DB -1,253 ; K#74, Clear,
+ifdef NOT_NTVDM
+;;* DB -1,-1,-1 ; Undef, K#109, Undef
+;;* DB -1,-1,-1,-1,-1 ; Undef, Undef, K#94, K#14, Undef
+else
+ DB -1,-1,-1 ; Undef, K#109, Undef
+ DB -1,-1,-1,-1,-1 ; Undef, Undef, K#94, K#14, K#107
+endif
+
+H_LAST_SCAN EQU $-K30A+52h ; Largest valid scan code in table
+ ; K30A K8 K15 K14 must have same ends
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; K8 is overlaid by K8_RPL (from module KEYB_COMMAND)
+; if extended INT 16 support is available
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+K8 LABEL BYTE ;-------- CHARACTERS ---------
+ DB 27,-1,00,-1,-1,-1 ; Esc, 1, 2, 3, 4, 5
+ DB 30,-1,-1,-1,-1,31 ; 6, 7, 8, 9, 0, -
+ DB -1,127,-1,17,23,5 ; =, Bksp, Tab, Q, W, E
+ DB 18,20,25,21,09,15 ; R, T, Y, U, I, O
+ DB 16,27,29,10,-1,01 ; P, [, ], Enter, Ctrl, A
+ DB 19,04,06,07,08,10 ; S, D, F, G, H, J
+ DB 11,12,-1,-1,-1,-1 ; K, L, ;, ', `, LShift
+ DB 28,26,24,03,22,02 ; \, Z, X, C, V, B
+ DB 14,13,-1,-1,-1,-1 ; N, M, ,, ., /, RShift
+ DB '*',-1,' ',-1 ; *, Alt, Space, CL
+ ;--------- FUNCTIONS ---------
+ DB 94,95,96,97,98,99 ; F1 - F6
+ DB 100,101,102,103,-1,-1 ; F7 - F10, NL, SL
+ DB 119,-1,132,-1,115,-1 ; Home, Up, PgUp, -, Left, Pad5
+ DB 116,-1,117,-1,118,-1 ; Right, +, End, Down, PgDn, Ins
+ DB -1,-1,-1,-1,137,138 ; Del, SysReq, Undef, WT, F11, F12
+ ;---------- 122 KEYBOARD not overlaid
+ DB -1,234,206,207,208 ; Undef, PA1, F13, F14, F15
+ DB -1,-1,-1,-1,-1 ; Pause, Undef 5F-62
+ DB 209,210,211,212,213 ; F16, F17, F18, F19, F20,
+ DB 214,215,216,217 ; F21, F22, F23, F24,
+ DB -1,242,-1,-1 ; K#69, ErEOF, Break, Play,
+ DB -1,-1,-1,-1,-1 ; Undef, Attn, CrSel, K#56, ExSel
+ DB -1,252 ; K#74, Clear,
+ifdef NOT_NTVDM
+;;* DB -1,-1,-1 ; Undef, K#109, Undef
+;;* DB -1,-1,-1,-1,-1 ; Undef, Undef, K#94, K#14, Undef
+else
+ DB -1,-1,-1 ; Undef, K#109, Undef
+ DB -1,-1,-1,-1,-1 ; Undef, Undef, K#94, K#14, K#107
+endif
+
+;----- TABLES FOR LOWER CASE (USA) --
+
+K10 LABEL BYTE
+ DB 27,'12345'
+ DB '67890-'
+ DB '=',08,09,'qwe'
+ DB 'rtyuio'
+ DB 'p[]',0DH,-1,'a' ; LETTERS, Return, Ctrl
+ DB 'sdfghj'
+ DB "kl;'`",-1 ; LETTERS, L Shift
+ DB '\zxcvb'
+ DB 'nm,./'
+ DB -1,'*',-1,' \' ; R Shift, *, Alt, Sp, CL (REALLY WT KEY)
+
+;------ LC TABLE SCAN
+ DB 59,60,61,62,63 ; BASE STATE OF F1 - F10
+ DB 64,65,66,67,68
+ DB -1,-1 ; NL, SL
+
+;------ KEYPAD TABLE
+K15 LABEL BYTE
+ DB 71,72,73,-1,75,-1 ; Home, Up, PgUp, -1, Left, -1
+ DB 77,-1,79,80,81,82 ; Right, -1, End, Down, PgDn, Ins
+ DB 83 ; Del
+ DB -1,-1,'\',133,134 ; SysRq, Undef, WT, F11, F12
+ DB -1,232,182,183,184 ; Undef, PA1, F13, F14, F15
+ DB -1,-1,-1,-1,-1 ; Pause, Undef 5F-62
+ DB 185,186,187,188,189 ; F16, F17, F18, F19, F20,
+ DB 190,191,192,193 ; F21, F22, F23, F24,
+ DB -1,240,-1,-1 ; K#69, ErEOF, Break, Play,
+ DB -1,-1,-1,-1,-1 ; Undef, Attn, CrSel, K#56, ExSel
+ DB -1,251 ; K#74, Clear,
+ifdef NOT_NTVDM
+;;* DB -1,-1,-1 ; Undef, K#109, Undef
+;;* DB -1,-1,-1,-1,-1 ; Undef, Undef, K#94, K#14, Undef
+else
+ DB -1,-1,-1 ; Undef, K#109, Undef
+ DB -1,-1,-1,-1,-1 ; Undef, Undef, K#94, K#14, K#107
+endif
+
+;------- TABLES FOR UPPER CASE (USA)
+
+K11 LABEL BYTE
+ DB 27,'!@#$%'
+ DB '^&*()_'
+ DB '+',08,00,'QWE'
+ DB 'RTYUIO'
+ DB 'P{}',0DH,-1,'A' ; LETTERS, Return, Ctrl
+ DB 'SDFGHJ'
+ DB 'KL:"~',-1 ; LETTERS, L Shift
+ DB '|ZXCVB'
+ DB 'NM<>?'
+ DB -1,'*',-1,' |' ; R Shift, *, Alt, Sp, CL (REALLY WT KEY)
+
+;------ UC TABLE SCAN
+K12 LABEL BYTE
+ DB 84,85,86,87,88 ; SHIFTED STATE OF F1 - F10
+ DB 89,90,91,92,93
+ DB -1,-1 ; NL, SL
+
+;------ NUM STATE TABLE
+K14 LABEL BYTE
+ DB '789-456+1230.' ; NUMLOCK STATE OF KEYPAD KEYS
+ DB -1,-1,'|',135,136 ; SysRq, Undef, WT, F11, F12
+ DB -1,233,194,195,196 ; Undef, PA1, F13, F14, F15
+ DB -1,-1,-1,-1,-1 ; Pause, Undef 5F-62
+ DB 197,198,199,200,201 ; F16, F17, F18, F19, F20,
+ DB 202,203,204,205 ; F21, F22, F23, F24,
+ DB -1,241,-1,-1 ; K#69, ErEOF, Break, Play,
+ DB -1,-1,-1,-1,-1 ; Undef, Attn, CrSel, K#56, ExSel
+ DB -1,251 ; K#74, Clear,
+ifdef NOT_NTVDM
+;;* DB -1,-1,-1 ; Undef, K#109, Undef
+;;* DB -1,-1,-1,-1,-1 ; Undef, Undef, K#94, K#14, Undef
+else
+ DB -1,-1,-1 ; Undef, K#109, Undef
+ DB -1,-1,-1,-1,-1 ; Undef, Undef, K#94, K#14, K#107
+endif
+PAGE
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; Procedure: KEYB_INT_9
+;
+; Description:
+; Entry point for interrupt 9 processing.
+;
+; Input Registers:
+; None
+;
+; Output Registers:
+; None
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ EVEN ; Keep KEYB_INT_9 entry on even boundry
+BEEP_PENDING DB NO ; YES if a beep is needed
+SCAN_CODE DB 0 ; Last SCAN code read
+
+KEYB_INT_9 PROC NEAR
+
+ JMP SHORT KB_INT_1 ;; (YST)
+COPY_NLS1_FLAG DB 0 ;; (YST)
+COUNTRY_FLAG DB -1 ; WHERE THE INT9 VECTOR POINTS
+
+KB_INT_1:
+
+ ; Do NOT enable interrupts untill after
+ ; PORT 60h has been read. INT 15h has
+ ; interrupt window, do EOI, fast pass.
+ PUSH BP ; Reserved in KEYBi9c for SD.SYSTEM_FLAG
+ PUSH AX
+ PUSH BX
+ PUSH CX
+ PUSH DX
+ PUSH SI
+ PUSH DI
+ PUSH DS
+ PUSH ES
+ CLD ; FORWARD DIRECTION
+ MOV BX,DATA ; SET UP ADDRESSING
+ MOV DS,BX ; DS POINTS AT THE ROM BIOS DATA AREA
+ MOV BP,CS:SD.SYSTEM_FLAG ; GET CS:SD.SYSTEM_FLAG, AND USE BP
+
+
+ifdef NOT_NTVDM
+;/* -- WAIT TILL KEYBOARD DISABLE COMMAND CAN BE ACCEPTED
+ MOV AL,DIS_KBD ; DISABLE THE KEYBOARD COMMAND
+ CALL SHIP_IT ; EXECUTE DISABLE
+else
+ mov ah, 1 ; notify I9 entry to softpc
+ BOP 09h
+ nop ; Carbon copy traces for
+ nop ; "in al,PORT_A"
+endif ; keep it traceable
+
+ IN AL,PORT_A ; READ IN THE CHARACTER
+
+
+;/* -- SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INTERRUPT LEVEL 9H)
+
+ MOV AH,04FH ; SYSTEM INTERCEPT - KEY CODE FUNCTION
+ STC ; SET CY= 1 (IN CASE OF IRET)
+ INT 15H ; CASSETTE CALL (AL)= KEY SCAN CODE
+ ; RETURNS CY= 1 FOR INVALID FUNCTION
+
+ifdef NOT_NTVDM
+ ; EARLY EOI for all interrupts done
+ ; after INT 15h to prevent re-entrancy
+ XCHG BX,AX ; SAVE SCAN CODE
+ MOV AL,EOI ; END OF INTERRUPT COMMAND (EARLY EOI)
+ OUT INTA00,AL ; SEND EOI TO INTERRUPT CONTROL PORT
+ XCHG BX,AX ; RECOVER SCAN CODE
+endif
+
+ JC KB_INT_02 ; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
+ JMP K26 ; EXIT IF SYSTEM HANDLED SCAN CODE
+ ; EXIT HANDLES ENABLE
+
+;/* --- CHECK FOR A POSSIBLE HOT REPLUG AND A POR COMPLETE CODE
+KB_INT_02: ; (AL)= SCAN CODE
+
+ifdef NOT_NTVDM
+; ntvdm we don't do keyboard resets\power on stuff
+;
+ ; CHECK FOR POR
+ CMP AL,KB_OK ; CHECK FOR POSSIBLE KEYBOARD POR CHAR
+ JNE KB_INT_03 ; CONTINUE NOT A POR OF AA
+ ; CHECK FOR ENHANSED KEYB
+ TEST KB_FLAG_3,LC_E0 ; WAS E0h LAST SCAN CODE? DCR467
+ JNZ KB_INT_03 ; SKIP KB POR IF IT WAS
+ ; CHECK FOR LEFT SHIFT BREAK
+ TEST KB_FLAG,LEFT_SHIFT ; IS LEFT SHIFT ACTIVE?
+ JNZ KB_INT_03 ; SKIP KB POR IF IT WAS
+ ; KEYBOARD POWER ON DETECTED
+ MOV CS:BEEP_PENDING,YES ; INDICATE WE NEED A BEEP
+ MOV KB_FLAG_2,0 ; CLEAR ALL LED FLAGS TO FORCE UPDATE
+ ; LEAVE OTHERS SO KB SIMULATORS WORK
+
+ TEST BP,PS_8042 ; SYSTEM USING 8042 & SCAN CODE SET 01?
+ JZ KB_INT_03 ; SKIP IF SYSTEM USES DEFAULT SCS 02
+ ; PATRIOT/SEBRING 8042 GATE ARRAY
+ MOV AL,SCAN_CODE_CMD ; SELECT SCAN CODE SET COMMAND
+ CALL SND_DATA ; SEND IT DIRECTLY TO THE KEYBOARD
+ MOV AL,01h ; SELECT SCAN CODE SET 01
+ CALL SND_DATA ; SEND IT TO THE KEYBOARD
+ MOV AL,KB_OK ; RESTORE POR SCAN CODE IN (AL)
+endif
+
+KB_INT_03:
+
+;/* --- CHECK FOR A RESEND COMMAND TO KEYBOARD
+
+ ;; NTVDM STI ; ENABLE INTERRUPTS AGAIN
+ CMP AL,KB_RESEND ; IS THE INPUT A RESEND
+ JE KB_INT_4 ; GO IF RESEND
+
+;/* --- CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
+
+ CMP AL,KB_ACK ; IS THE INPUT AN ACKNOWLEDGE
+ JNZ KB_INT_2 ; GO IF NOT
+
+;/* --- A COMMAND TO THE KEYBOARD WAS ISSUED
+
+ ;; NTVDM CLI ; DISABLE INTERRUPTS
+ OR KB_FLAG_2,KB_FA ; INDICATE ACK RECEIVED
+ JMP K26 ; RETURN IF NOT (ACK RETURNED FOR DATA)
+
+;/* --- RESEND THE LAST BYTE
+
+KB_INT_4:
+ ;; NTVDM CLI ; DISABLE INTERRUPTS
+ OR KB_FLAG_2,KB_FE ; INDICATE RESEND RECEIVED
+ JMP K26 ; RETURN IF NOT (ACK RETURNED FOR DATA)
+
+
+;/* --- UPDATE MODE INDICATORS IF CHANGE IN STATE
+
+KB_INT_2:
+ PUSH AX ; SAVE DATA IN
+ CALL MAKE_LED ; GO GET MODE INDICATOR DATA BYTE
+ MOV BL, KB_FLAG_2 ; GET PREVIOUS BITS
+ XOR BL,AL ; SEE IF ANY DIFFERENT
+ AND BL,KB_LEDS ; ISOLATE INDICATOR BITS
+ JZ UP0 ; IF NO CHANGE BYPASS UPDATE
+ CALL SND_LED ; GO TURN ON MODE INDICATORS
+UP0: POP AX ; RESTORE DATA IN
+
+;---------------------------------------------------------------------
+; START OF KEY PROCESSING -
+;---------------------------------------------------------------------
+
+ MOV AH,AL ; SAVE SCAN CODE IN AH ALSO
+ ; END OF RE-ENTRANT CODE PATHS
+ MOV CS:SCAN_CODE,AL ; SAVE SCAN CODE TO BE PROCESSED BY KEYB
+
+;------ TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
+
+ CMP AL,KB_OVER_RUN ; IS THIS AN OVERRUN CHAR?
+ JNZ K16 ; NO, TEST FOR SHIFT KEY
+
+ MOV CS:BEEP_PENDING,YES
+ JMP K26 ; BUFFER_FULL_BEEP, EXIT
+
+K16:
+
+ PUSH CS
+ POP ES ; ESTABLISH ADDRESS OF TABLES
+ MOV BH, KB_FLAG_3 ; LOAD FLAGS FOR TESTING
+
+;------ TEST TO SEE IF A READ_ID IS IN PROGRESS
+
+ TEST BH,RD_ID+LC_AB ; ARE WE DOING A READ ID?
+ JZ NOT_ID ; CONTINUE IF NOT
+ JNS TST_ID_2 ; IS THE RD_ID FLAG ON?
+ CMP AL,ID_1 ; IS THIS THE 1ST ID CHARACTER?
+ JNE RST_RD_ID
+ OR KB_FLAG_3,LC_AB ; INDICATE 1ST ID WAS OK
+RST_RD_ID:
+ AND KB_FLAG_3,NOT RD_ID ; RESET THE READ ID FLAG
+ JMP SHORT ID_EX ; AND EXIT
+
+
+;------ CHECK 2ND US KBD ID - FOR SETTING NUM LOCK ON
+TST_ID_2:
+ AND KB_FLAG_3,NOT LC_AB ; RESET FLAG
+ OR KB_FLAG_3,KBX ; INDICATE ENHANCED KEYBOARD WAS FOUND
+ CMP AL,TID_2 ; IS THIS US G-LAYOUT KBD w 8042
+ JE NUM_LOCK_000 ; JUMP IF SO
+ CMP AL,ID_2U ; IS THIS US G-LAYOUT KBD w/o 8042
+ JE NUM_LOCK_000 ; JUMP IF SO
+ CMP AL,ID_122 ; IS THIS THE 122 KEY ENHANCED KEYBOARD
+ JE NUM_LOCK_000 ; JUMP IF SO
+
+;------ CHECK 2ND JAPANESE KBD ID ;DCR355
+
+ CMP AL,ID_2JG ; IS THIS JPN KBD - G ?
+ JE NUM_LOCK_000 ; JUMP IF SO
+ CMP AL,ID_2JA ; IS THIS JPN KBD - A ?
+ JNE ID_EX ; EXIT IF NUM LOCK NOT REQUIRED
+ ; These ID's do not set NUM LOCK ON
+ ; ID_2AU = US P-LAYOUT KBD w/o 8042
+ ; TID_2A = US P-LAYOUT KBD w 8042
+ ; ID_2JP = JPN KBD - P
+
+;------ A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
+
+NUM_LOCK_000:
+ TEST BH,SET_NUM_LK ; SHOULD WE SET NUM LOCK?
+ JZ ID_EX ; EXIT IF NOT
+ OR KB_FLAG,NUM_STATE ; FORCE NUM LOCK ON
+ CALL SND_LED ; GO SET THE NUM LOCK INDICATOR
+ID_EX:
+ JMP K26 ; EXIT
+PAGE
+NOT_ID:
+ CMP AL,MC_E0 ; IS THIS THE GENERAL MARKER CODE?
+ JNE TEST_E1
+ OR KB_FLAG_3,LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
+ JMP SHORT EXIT ; THROW AWAY THIS CODE
+
+TEST_E1:
+ CMP AL,MC_E1 ; IS THIS THE PAUSE KEY?
+ JNE NOT_HC
+ OR KB_FLAG_3,LC_E1+KBX ; SET FLAG, PAUSE KEY MARKER CODE
+EXIT: JMP K26A ; THROW AWAY THIS CODE
+
+NOT_HC:
+ AND AL,07FH ; TURN OFF THE BREAK BIT
+ TEST BH,LC_E0 ; LAST CODE THE E0 MARKER CODE?
+ JZ NOT_LC_E0 ; JUMP IF NOT
+
+ MOV CX,2 ; LENGTH OF SEARCH
+ MOV DI,OFFSET K6+6 ; IS THIS A SHIFT KEY?
+ REPNE SCASB ; CHECK IT
+ JNE K16A ; NO, CONTINUE KEY PROCESSING
+ JMP SHORT K16B ; YES, THROW AWAY & RESET FLAG
+
+NOT_LC_E0:
+ TEST BH,LC_E1 ; LAST CODE THE E1 MARKER CODE?
+ JZ T_SYS_KEY ; JUMP IF NOT
+
+ MOV CX,4 ; LENGTH OF SEARCH
+ MOV DI,OFFSET K6+4 ; IS THIS AN ALT, CTL, OR SHIFT?
+ REPNE SCASB ; CHECK IT
+ JE EXIT ; THROW AWAY IF SO
+
+ CMP AL,NUM_KEY ; IS IT THE PAUSE KEY?
+ JNE K16B ; NO, THROW AWAY & RESET FLAG
+ TEST AH,80H ; YES, IS IT THE BREAK OF THE KEY?
+ JNZ K16B ; YES, THROW THIS AWAY, TOO
+ TEST KB_FLAG_1,HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
+ JNZ K16B ; YES, THROW AWAY
+ JMP K39P ; NO, THIS IS THE REAL PAUSE STATE
+PAGE
+;------ TEST FOR SYSTEM KEY
+
+T_SYS_KEY:
+ CMP AL,SYS_KEY ; IS IT THE SYSTEM KEY?
+ JNE K16A ; CONTINUE IF NOT
+
+ TEST AH,080H ; CHECK IF THIS A BREAK CODE
+ ;; NTVDM CLI ; DISABLE INTERRUPTS PTR 6602319
+ JNZ K16C ; DON'T TOUCH SYSTEM INDICATOR IF TRUE
+
+ TEST KB_FLAG_1,SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN
+ JNZ K16B ; IF YES, DON'T PROCESS SYSTEM INDICATOR
+
+ OR KB_FLAG_1,SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
+
+ifdef NOT_NTVDM
+ MOV AL,ENA_KBD ; INSURE KEYBOARD IS ENABLED
+ CALL SHIP_IT ; EXECUTE ENABLE
+else
+ mov ah, 3 ; K27A exit notify
+ BOP 09h
+endif
+ MOV AX,08500H ; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
+ INT 15H ; USER INTERRUPT
+ JMP K27A ; END PROCESSING
+
+K16B: JMP K26 ; IGNORE SYSTEM KEY
+
+K16C: AND KB_FLAG_1,NOT SYS_SHIFT; TURN OFF SHIFT KEY HELD DOWN
+
+ifdef NOT_NTVDM
+ MOV AL,ENA_KBD ; INSURE KEYBOARD IS ENABLED
+ CALL SHIP_IT ; EXECUTE ENABLE
+else
+ mov ah, 3 ; K27A exit notify
+ BOP 09h
+endif
+
+ MOV AX,08501H ; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
+ INT 15H ; USER INTERRUPT
+ JMP K27A ; IGNORE SYSTEM KEY
+PAGE
+;------ TEST FOR SHIFT KEYS
+;
+; HERE IS WHERE KB_FLAGS ARE SET. WHAT HAPPENS IS, THE SYSTEM SEARCHES TABLE
+; 'K6' FOR THE KEY. IF FOUND, IT GETS THE APPROPRIATE BIT FROM TABLE 'K7'
+; AND SETS IT ON. (TABLES ARE ALL AT THE TOP OF THIS ROUTINE) FLAGS FOR THE
+; SECOND ALT AND CTRL ARE SET IN KB_FLAG_3 AND HAVE THE SAME BIT POSITIONS AS
+; THEIR ORIGINAL COUNTERPARTS IN KB_FLAG
+
+K16A: MOV BL, KB_FLAG ; PUT STATE FLAGS IN BL
+ MOV DI,OFFSET K6 ; SHIFT KEY TABLE
+ MOV CX,K6L ; LENGTH
+ REPNE SCASB ; LOOK THROUGH THE TABLE FOR A MATCH
+ MOV AL,AH ; RECOVER SCAN CODE
+ JE K17 ; JUMP IF MATCH FOUND
+ JMP K25 ; IF NO MATCH, THEN SHIFT NOT FOUND
+
+;------ SHIFT KEY FOUND
+
+K17: SUB DI,OFFSET K6+1 ; ADJUST PTR TO SCAN CODE MTCH
+ MOV AH,CS:K7[DI] ; GET MASK INTO AH
+ MOV CL,2 ; SET UP COUNT FOR FLAG SHIFTS
+ TEST AL,80H ; TEST FOR BREAK KEY
+ JZ K17C
+ JMP K23 ; JUMP IF BREAK
+
+;------ SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
+
+K17C: CMP AH,SCROLL_SHIFT
+ JAE K18 ; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
+
+;------ PLAIN SHIFT KEY, SET SHIFT ON
+
+ CMP COUNTRY_FLAG,0FFh ; ARE WE IN FOREIGN LANG MODE?
+ JNE K17C1 ; NO, US MODE, JUMP
+ CMP AL,ALT_KEY ; IS THIS THE ALT KEY?
+ JNE K17C1 ; NO, NORMAL KEY
+ ;**CNS
+
+K17C1: OR KB_FLAG,AH ; TURN ON SHIFT BIT
+K17C2: TEST AH,CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
+ JZ K17F ; NO, JUMP
+K17D: TEST BH,LC_E0 ; IS THIS ONE OF THE NEW KEYS?
+ JZ K17E ; NO, JUMP
+ OR KB_FLAG_3,AH ; SET BITS FOR RIGHT CTRL, ALT
+; JMP K26 ; INTERRUPT_RETURN
+ jmp short K17G ; (YST)
+
+K17E: SHR AH,CL ; MOVE FLAG BITS TWO POSITIONS
+ OR KB_FLAG_1,AH ; SET BITS FOR LEFT CTRL, ALT
+; JMP K26 ; INTERRUPT RETURN
+ jmp short K17G ; (YST)
+
+K17F:
+ TEST CS:SD.SPECIAL_FEATURES,TYPEWRITER_CAPS_LK
+ JZ K17G ; N..all done
+ CMP COUNTRY_FLAG,0FFh ; ARE WE IN LANG MODE?
+ JNE K17G ; NO, ALL DONE WITH SHIFT KEY
+
+;------ If keyboard is P12 then we still need to release caps_lk
+
+ TEST BP,PC_LAP ; IS THIS A P12 KEYBOARD?
+ JNZ REMOVE_CAPS_SHIFT
+
+ TEST BH,KBX ; THIS THE ENHANCED KEYBOARD?
+ JZ K17G ; NO, ALL DONE WITH SHIFT KEY
+REMOVE_CAPS_SHIFT:
+ AND KB_FLAG,NOT CAPS_SHIFT ; YES, TAKE KB OUT OF C_L STATE
+ CALL SND_LED ; AND UPDATE THE LED INDICATORS
+K17G:
+
+
+; ===========================================
+; Russian Keyboard (YST)
+; ===========================================
+ CMP COUNTRY_FLAG,0FFh ; ARE WE IN FOREIGN LANG MODE? (YST)
+ JNE K17H ; NO, US MODE, RETURN (YST)
+ TEST CS:SD.SPECIAL_FEATURES,SHIFTS_TO_LOGIC; CAN OUR STATE (YST)
+ ; LOGIC SUPPORT THIS CALL? (YST)
+ JZ K17H ; NO, RETURN (YST)
+ OR CS:FLAGS_TO_TEST[EXT_KB_FLAG_ID],SHIFTS_PRESSED; (YST)
+ ; SET FLAG FOR STATE LOGIC (YST)
+ CALL KEYB_STATE_PROCESSOR ; ******** (YST)
+ AND CS:FLAGS_TO_TEST[EXT_KB_FLAG_ID],NOT SHIFTS_PRESSED; (YST)
+ ; CLEAR FLAG AFTER USE (YST)
+; ===========================================
+; End of Russian Keyboard (YST)
+; ===========================================
+
+
+K17H: JMP K26 ; RETURN
+
+;------ TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
+
+K18: ; SHIFT-TOGGLE
+ TEST BL,CTL_SHIFT ; CHECK CTL SHIFT STATE
+ JZ K18A ; JUMP IF NOT CTL STATE
+ JMP K25 ; JUMP IF CTL STATE
+K18A: CMP AL,INS_KEY ; CHECK FOR INSERT KEY
+ JNE K22 ; JUMP IF NOT INSERT KEY
+ TEST BL,ALT_SHIFT ; CHECK FOR ALTERNATE SHIFT
+ JZ K18B ; JUMP IF NOT ALTERNATE SHIFT
+ JMP K25 ; JUMP IF ALTERNATE SHIFT
+K18B: TEST BH,LC_E0 ; IS THIS THE NEW INSERT KEY?
+ JNZ K22 ; YES, THIS ONE'S NEVER A "0"
+K19: TEST BL,NUM_STATE ; CHECK FOR BASE STATE
+ JNZ K21 ; JUMP IF NUM LOCK IS ON
+ TEST BL,LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
+ JZ K22 ; JUMP IF BASE STATE
+K20: MOV AH,AL ; PUT SCAN CODE BACK IN AH
+ JMP K25 ; NUMERAL "0", STNDRD. PROCESSING
+
+K21: TEST BL,LEFT_SHIFT+RIGHT_SHIFT ; MIGHT BE NUMERIC
+ JZ K20 ; IS NUMERIC, STD. PROC.
+
+K22: ; SHIFT TOGGLE KEY HIT; PROCESS IT
+ TEST AH, KB_FLAG_1 ; IS KEY ALREADY DEPRESSED?
+ JZ K22A
+ JMP K26 ; JUMP IF KEY ALREADY DEPRESSED
+K22A: OR KB_FLAG_1,AH ; INDICATE THAT THE KEY IS DEPRESSED
+ XOR KB_FLAG,AH ; TOGGLE THE SHIFT STATE
+
+ TEST CS:SD.SPECIAL_FEATURES,TYPEWRITER_CAPS_LK
+ JZ K22C ; N..all done
+
+;------ If keyboard is P12 then we do not toggle
+
+ TEST BP,PC_LAP ; IS THIS A P12 KEYBOARD?
+ JNZ LAP_SO_DONT_TOGGLE
+
+ TEST BH,KBX ; THIS THE ENHANCED KEYBOARD?
+ JZ K22C ; NO, ALL DONE WITH TOGGLE KEYS
+
+LAP_SO_DONT_TOGGLE:
+ CMP CS:COUNTRY_FLAG,0FFh ; ARE WE IN FOREIGN LANG MODE?
+ JNE K22C ; NO, NO SPECIAL STUFF FOR U.S.
+ TEST AH,CAPS_SHIFT ; IS IT THE CAPS_LOCK KEY?
+ JZ K22C ; NO, NOTHING ELSE TO DO
+ OR KB_FLAG,AH ; YES, SET CAPS_LOCK (NOT TOGGLE)
+
+K22C:
+
+;------ TOGGLE LED IF CAPS, NUM, OR SCROLL KEY DEPRESSED
+
+ TEST AH,CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
+ JZ K22B ; GO IF NOT
+ PUSH AX ; SAVE SCAN CODE AND SHIFT MASK
+ CALL SND_LED ; GO TURN MODE INDICATORS ON
+ POP AX ; RESTORE SCAN CODE
+
+K22B: CMP AL,INS_KEY ; TEST FOR 1ST MAKE OF INSERT KEY
+ JNE K26 ; JUMP IF NOT INSERT KEY
+ MOV AH,AL ; SCAN CODE IN BOTH HALVES OF AX
+ JMP K28 ; FLAGS UPDATED, PROC. FOR BUFFER
+
+;------ BREAK SHIFT FOUND
+
+K23: ; BREAK-SHIFT-FOUND
+ CMP AH,SCROLL_SHIFT ; IS THIS A TOGGLE KEY?
+ NOT AH ; INVERT MASK
+ JAE K24 ; YES, HANDLE BREAK TOGGLE
+ AND KB_FLAG,AH ; TURN OFF SHIFT BIT
+ CMP AH,NOT CTL_SHIFT ; IS THIS ALT OR CTL?
+ JA K23D ; NO, ALL DONE
+
+ TEST BH,LC_E0 ; 2ND ALT OR CTL?
+ JZ K23A ; NO, HANDLE NORMALLY
+ AND KB_FLAG_3,AH ; RESET BIT FOR RIGHT ALT OR CTL
+ JMP SHORT K23B ; CONTINUE
+K23A: SAR AH,CL ; MOVE THE MASK BIT TWO POSITIONS
+ AND KB_FLAG_1,AH ; RESET BIT FOR LEFT ALT OR CTL
+K23B: MOV AH,AL ; SAVE SCAN CODE
+ MOV AL, KB_FLAG_3 ; GET RIGHT ALT & CTRL FLAGS
+ CMP COUNTRY_FLAG,0FFH ; ARE WE IN LANGUAGE MODE?
+ JNE K23C ; NO, LEAVE RIGHT FLAGS AS IS
+;**CNS
+ AND AL,NOT GRAPH_ON ; YES, FILTER OUT THE ALT_GR KEY
+;**CNS
+K23C: SHR AL,CL ; MOVE TO BITS 1 & 0
+ OR AL, KB_FLAG_1 ; PUT IN LEFT ALT & CTL FLAGS
+ SHL AL,CL ; MOVE BACK TO BITS 3 & 2
+ AND AL,ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
+ OR KB_FLAG,AL ; PUT RESULT IN THE REAL FLAGS
+ MOV AL,AH ; RECOVER SAVED SCAN CODE
+
+K23D: CMP AL,ALT_KEY+80H ; IS THIS ALTERNATE SHIFT RELEASE
+ JNE K26 ; INTERRUPT_RETURN
+
+;------ ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
+
+ MOV AL, ALT_INPUT
+ xor ah,ah ; scan code of 0
+ MOV ALT_INPUT,AH ; ZERO OUT THE FIELD
+ or al,al ; was the input = 0?
+ JE K26 ; INTERRUPT_RETURN
+ CALL BUFFER_FILL_ANY_CHAR ; Put in buffer, but use this
+ ; entry point to avoid trashing
+ ; an ASCII code of 255
+ JMP SHORT K26 ; INTERRUPT_RETURN
+
+K24: ; BREAK-TOGGLE
+ AND KB_FLAG_1,AH ; INDICATE NO LONGER DEPRESSED
+ JMP SHORT K26 ; INTERRUPT_RETURN
+
+;------ TEST FOR HOLD STATE
+ ; AL, AH = SCAN CODE
+K25: ; NO-SHIFT-FOUND
+ CMP AL,80H ; TEST FOR BREAK KEY
+ JAE K26 ; NOTHING FOR BREAK CHARS FROM HERE ON
+ TEST KB_FLAG_1,HOLD_STATE ; ARE WE IN HOLD STATE
+ JZ K28 ; BRANCH AROUND TEST IF NOT
+ CMP AL,NUM_KEY
+ JE K26 ; CAN'T END HOLD ON NUM_LOCK
+ AND KB_FLAG_1,NOT HOLD_STATE ; TURN OFF THE HOLD STATE BIT
+
+K26:
+ AND KB_FLAG_3,NOT LC_E0+LC_E1 ; RESET LAST CHAR H.C. FLAG
+
+K26A: ; INTERRUPT-RETURN
+ifdef NOT_NTVDM
+ ;; NTVDM CLI ; TURN OFF INTERRUPTS
+ CALL ERROR_BEEP ; CHECK FOR ERROR BEEP PENDING
+
+ CMP CS:BUFFER_ENTRY_OK,YES ; HAS A CHARACTER BEEN PLACED IN BUFFER
+ JNE K27 ; NO, SKIP POST
+
+ MOV byte ptr CS:BUFFER_ENTRY_OK,NO ; CLEAR POST CHARACTER IN BUFFER FLAG
+ MOV AX,09102H ; MOVE IN POST CODE & TYPE
+ INT 15H ; PERFORM OTHER FUNCTION
+K27:
+ MOV AL,ENA_KBD ; ENSURE KEYBOARD IS ENABLED (AT PS/2)
+ CALL SHIP_IT ; EXECUTE ENABLE
+else
+
+ mov ah, 2
+ mov bh, CS:BEEP_PENDING
+ mov bl, CS:BUFFER_ENTRY_OK
+ MOV byte ptr CS:BUFFER_ENTRY_OK,NO
+ MOV byte ptr CS:BEEP_PENDING,NO
+ BOP 09h
+endif
+
+
+K27A: ;; NTVDM CLI ; DISABLE INTERRUPTS
+ POP ES ; RESTORE REGISTERS
+ POP DS ; *
+ POP DI ; *
+ POP SI ; *
+ POP DX ; *
+ POP CX ; *
+ POP BX ; *
+ POP AX ; *
+ POP BP ; *
+
+ jmp DOIRET ; RETURN
+PAGE
+;------ NOT IN HOLD STATE
+ ; AL, AH = SCAN CODE (ALL MAKES)
+K28: ; NO-HOLD-STATE
+ CMP AL,H_LAST_SCAN ; TEST FOR OUT-OF-RANGE SCAN CODES
+ JA SHORT K26 ; IGNORE IF OUT-OF-RANGE
+
+ TEST BP,EXT_122 ; IS EXTENDED 122 KEYBOARD SUPPORT OK
+ JNZ K28_122 ; SKIP NON-122 OUT-OF-RANGE CHECK
+
+ifdef NOT_NTVDM
+ CMP AL,88 ; TEST FOR OUT-OF-RANGE SCAN CODES
+else
+ CMP AL,7Eh ; MAX SCANCODE ON BRAZILIAN ABNT KBD
+endif
+ JA K26 ; IGNORE IF OUT-OF-RANGE
+
+K28_122:
+ TEST BL,ALT_SHIFT ; ARE WE IN ALTERNATE SHIFT?
+ JZ K28A ; JUMP IF NOT ALTERNATE
+
+ TEST BH,KBX ; IS THIS THE ENHANCED KEYBOARD?
+ JZ K29 ; NO, ALT STATE IS REAL
+
+ TEST KB_FLAG_1,SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
+ JZ K29 ; NO, ALT STATE IS REAL
+;**CNS
+ TEST AH,LC_E0 ; IS IT THE ALT_GR KEY?
+ JZ K28A ; YES, DON'T SET KB_FLAG
+
+ TEST AL,R_ALT_SHIFT ; TURN ON SHIFT BIT
+ JNZ K29 ; TURN ON SHIFT BIT
+;**CNS
+
+K28A: JMP K38 ; YES, THIS IS PHONY ALT STATE
+ ; DUE TO PRESSING SYSREQ
+
+;------ TEST FOR RESET KEY SEQUENCE (CTL ALT DEL) OR HOT KEY DEPRESSED
+
+K29: ; TEST-RESET
+ TEST BL,CTL_SHIFT ; ARE WE IN CONTROL SHIFT ALSO?
+ JZ K31 ; NO_RESET
+ CMP AL,DEL_KEY ; SHIFT STATE IS THERE, TEST KEY
+ JNE K31A ; NO_RESET, TRANSLATE TABLE SWAP
+
+;------ CTL-ALT-DEL HAS BEEN FOUND, DO I/O CLEANUP
+
+ MOV RESET_FLAG,1234H ; SET FLAG FOR RESET FUNCTION
+ AND WORD PTR KB_FLAG_3,KBX ; CLEAR ALL FLAG BITS EXCEPT KBX PED 6-25-86
+ JMP RESET ; JUMP TO POWER ON DIAGNOSTICS
+
+;------ IN ALTERNATE SHIFT, RESET NOT FOUND
+
+K31: ; NO-RESET
+ CALL KEYB_STATE_PROCESSOR
+ JC K26 ; TRANSLATIONS FOUND - EXIT
+
+ CMP AL,57 ; TEST FOR SPACE KEY
+ JNE K311 ; NOT THERE
+ MOV AL,' ' ; SET SPACE CHAR
+ JMP K57 ; BUFFER_FILL
+K311:
+ TEST BP,EXT_16 ; IS EXTENDED INT 16 LOADED?
+ JZ K32 ; NO, SKIP THIS EXTENDED STUFF
+ CMP AL,15 ; TEST FOR TAB KEY
+ JNE K312 ; NOT THERE
+ MOV AX,0A500h ; SET SPECIAL CODE FOR ALT-TAB
+ JMP K57 ; BUFFER_FILL
+K312:
+ CMP AL,74 ; TEST FOR KEYPAD -
+ JE K312A ; GO PROCESS
+ CMP AL,78 ; TEST FOR KEYPAD +
+ JNE K32 ; SKIP TEST FOR LANG SWAP & CONT.
+K312A: JMP K37B ; GO PROCESS
+
+;------ SET COUNTRY FLAG TO INDICATE WHICH TABLE WE'RE USING, FOREIGN OR DOMESTIC
+
+K31A: CMP AL,CS:SD.HOT_KEY_ON_SCAN ; TEST FOR HOT KEY TO US
+ JNE K31B
+ MOV CS:COUNTRY_FLAG,00 ; SET FLAG FOR DOMESTIC KEY'S
+ JMP K26 ; INTERRUPT RETURN
+
+K31B: CMP AL,CS:SD.HOT_KEY_OFF_SCAN ; TEST FOR HOT KEY TO FOREIGN
+ JNE K31C ; IF NOT TEST FOR FRONT ENGRAV
+ MOV CS:COUNTRY_FLAG,0FFH ; SET FLAGS FOR FOREIGN KEY'S
+ JMP K26 ; INTERRUPT RETURN
+
+
+;------ ALT, CTRL DOWN ; NO HOT KEY
+
+K31C: CMP CS:COUNTRY_FLAG,0FFH
+ JNE K32 ; TRY ALT_KEY_PAD
+ CALL KEYB_STATE_PROCESSOR
+ JC K32A ;K26 ; TRANSLATIONS FOUND - EXIT
+
+
+;------ LOOK FOR KEY PAD ENTRY
+
+K32: ; ALT-KEY-PAD
+ MOV DI,OFFSET K30 ; ALT-INPUT-TABLE
+ MOV CX,10 ; LOOK FOR ENTRY USING KEYPAD
+ REPNE SCASB ; LOOK FOR MATCH
+ JNE K33 ; NO_ALT_KEYPAD
+ TEST BH,LC_E0 ; IS THIS ONE OF THE NEW KEYS?
+ JNZ K37C ; YES, JUMP, NOT NUMPAD KEY
+ SUB DI,OFFSET K30+1 ; DI NOW HAS ENTRY VALUE
+ MOV AL, ALT_INPUT ; GET THE CURRENT BYTE
+ MOV AH,10 ; MULTIPLY BY 10
+ MUL AH
+ ADD AX,DI ; ADD IN THE LATEST ENTRY
+ MOV ALT_INPUT,AL ; STORE IT AWAY
+K32A: JMP K26 ; THROW AWAY THAT KEYSTROKE
+
+;------ LOOK FOR SUPERSHIFT ENTRY
+
+K33: ; NO-ALT-KEYPAD
+ MOV ALT_INPUT,0 ; ZERO ANY PREVIOUS ENTRY INTO INPUT
+ ; DI,ES ALREADY POINTING
+ MOV CX,K30_LEN ; NORMALLY 26, BUT 27 FOR FR, DUE
+ ; TO THE ";" KEY BEING "M"
+ REPNE SCASB ; LOOK FOR MATCH IN ALPHABET
+ JE K37A ; MATCH FOUND, GO FILL THE BUFFER
+
+;------ LOOK FOR TOP ROW OF ALTERNATE SHIFT
+
+K34: ; ALT-TOP-ROW
+ CMP AL,2 ; KEY WITH '1' ON IT
+ JB K37B ; MUST BE ESCAPE
+ CMP AL,13 ; IS IT IN THE REGION
+ JA K35 ; NO, ALT-SOMETHING ELSE
+ ADD AH,118 ; CONVERT PSEUDO SCAN CODE TO RANGE
+ JMP SHORT K37A ; GO FILL THE BUFFER
+
+;------ TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
+
+K35: ; ALT-FUNCTION
+ CMP AL,F11_M ; IS IT F11 or GREATER ?
+ JB K35A ; NO, BRANCH
+ SUB AL,52h ; SET UP TO SEARCH ALT-FUNCTION-TABLE
+ MOV BX,OFFSET K30A ; BASE CASE TABLE
+ JMP K64 ; CONVERT TO PSEUDO SCAN
+
+K35A: TEST BH,LC_E0 ; DO WE HAVE ONE OF THE NEW KEYS?
+ JZ K37 ; NO, JUMP
+ TEST BP,EXT_16 ; IS THE EXTENDED INT 16 LOADED?
+ JZ K37 ; NO, DO COMPATIBLE OUTPUT
+ CMP AL,28 ; TEST FOR KEYPAD ENTER
+ JNE K35B ; NOT THERE
+ MOV AX,0A600h ; SPECIAL CODE
+ JMP K57 ; BUFFER FILL
+K35B: CMP AL,83 ; TEST FOR DELETE KEY
+ JE K37C ; HANDLE WITH OTHER EDIT KEYS
+ CMP AL,53 ; TEST FOR KEYPAD /
+ JNE K32A ; NOT THERE, NO OTHER E0 SPECIALS
+ MOV AX,0A400h ; SPECIAL CODE
+ JMP K57 ; BUFFER FILL
+
+K37: CMP AL,59 ; TEST FOR FUNCTION KEYS (F1)
+ JB K37B ; NO FN, HANDLE W/OTHER EXTENDED
+ CMP AL,68 ; IN KEYPAD REGION?
+ ; OR NUMLOCK, SCROLLOCK?
+ JA K32A ; IF SO, IGNORE
+ ADD AH,45 ; CONVERT TO PSEUDO SCAN CODE
+
+K37A: xor al,al ; ASCII CODE OF ZERO
+ JMP K57 ; PUT IT IN THE BUFFER
+
+K37B:
+ TEST BP,EXT_16 ; IS THE EXTENDED INT 16 LOADED?
+ JZ K32A ;K26 ; NO, IGNORE THIS ONE
+ MOV AL,0F0h ; USE SPECIAL ASCII CODE
+ JMP K57 ; PUT IT IN THE BUFFER
+
+K37C:
+ TEST BP,EXT_16 ; IS THE EXTENDED INT 16 LOADED?
+ JZ K37A ; NO, DO COMPATIBLE OUTPUT
+ ADD AL,80 ; CONVERT SCAN CODE (EDIT KEYS)
+ MOV AH,AL ; (SCAN CODE NOT IN AH FOR INSERT)
+ JMP K37A ; PUT IT IN THE BUFFER
+PAGE
+;------ NOT IN ALTERNATE SHIFT
+
+K38: ; NOT-ALT-SHIFT
+ ; BL STILL HAS SHIFT FLAGS
+ TEST BL,CTL_SHIFT ; ARE WE IN CONTROL SHIFT?
+ JNZ K38A ; YES, START PROCESSING
+ JMP K44 ; NOT-CTL-SHIFT
+
+;------ CONTROL SHIFT, TEST SPECIAL CHARACTERS
+
+;------ TEST FOR BREAK
+
+K38A: CMP AL,SCROLL_KEY ; TEST FOR BREAK
+ JNE K39 ; JUMP, NO-BREAK
+ TEST BP,PC_LAP ; IS THIS THE LAP COMPUTER?
+ JNZ K38B ; YES, THIS IS CTRL-BREAK
+ TEST BH,KBX ; IS THIS THE ENHANCED KEYBOARD?
+ JZ K38B ; NO, BREAK IS VALID
+ TEST BH,LC_E0 ; YES, WAS LAST CODE AN E0?
+ JZ K39 ; NO-BREAK, TEST FOR PAUSE
+
+K38B:
+ ;; NTVDM CLI ; Disable interrupts because EOI issued
+ MOV BX, BUFFER_HEAD ; RESET BUFFER TAIL TO BUFFER HEAD
+ MOV BUFFER_TAIL,BX
+ MOV BIOS_BREAK,80H ; TURN ON BIOS_BREAK BIT
+
+;-------- ENABLE KEYBOARD
+
+ifdef NOT_NTVDM
+ MOV AL,ENA_KBD ; ENABLE KEYBOARD
+ CALL SHIP_IT ; EXECUTE ENABLE
+else
+ mov ah, 4
+ BOP 09h
+endif
+ INT 1BH ; BREAK INTERRUPT VECTOR
+ SUB AX,AX ; PUT OUT DUMMY CHARACTER
+ JMP K57 ; BUFFER_FILL
+
+;-------- TEST FOR PAUSE
+
+K39: ; NO-BREAK
+ CMP AL,NUM_KEY ; LOOK FOR PAUSE KEY
+ JNE K41 ; NO-PAUSE
+ TEST BH,KBX ; IS THIS THE ENHANCED KEYBOARD?
+ JZ K39P ; NO, THIS IS A VALID PAUSE
+ TEST BP,PC_LAP ; IS THIS THE LAP COMPUTER?
+ JZ K41 ; NO, IT'S NOT PAUSE THIS TIME
+K39P: OR KB_FLAG_1,HOLD_STATE ; TURN ON THE HOLD FLAG
+
+;-------- ENABLE KEYBOARD
+
+ MOV AL,ENA_KBD ; ENABLE KEYBOARD
+ CALL SHIP_IT ; EXECUTE ENABLE
+
+ifdef NOT_NTVDM
+
+;------ DURING PAUSE INTERVAL, TURN CRT BACK ON
+
+ CMP CRT_MODE,7 ; IS THIS BLACK AND WHITE CARD
+ JAE K40 ; YES, NOT CGA MODES NOTHING TO DO
+ MOV DX,03D8H ; PORT FOR COLOR CARD
+ MOV AL,CRT_MODE_SET ; GET THE VALUE OF THE CURRENT MODE
+ OUT DX,AL ; SET THE CRT MODE, SO THAT CRT IS ON
+K40: ; PAUSE-LOOP
+ TEST BP,PC_LAP ; IS THIS THE LAP COMPUTER?
+ JZ K40A ; NO, SKIP THE BATTERY LIFE STUFF
+ MOV AX,4104H ; FUNCTION 41, AL=04=RETURN IF 0
+ MOV BX,HOLD_STATE*100H ; BH=HOLD_STATE, BL=0=NO TIME OUT
+ PUSH DS ; MAKE ES:DI POINT TO KB_FLAG_1
+ POP ES
+ MOV DI,OFFSET KB_FLAG_1
+ INT 15H ; SLEEP UNTIL OUT OF HOLD
+
+;------ CHECK FOR AUX ADAPTER INPUT PENDING
+K40A:
+ MOV CX,100 ; COUNT FOR WAIT LOOP
+else
+ mov ah, 3 ; K27A exit notify
+ BOP 09h
+ call DOSTI
+K40A:
+ mov cx, 16
+ xor ax, ax
+ BOP BOP_WAITIFIDLE ; idle bop
+endif
+K40B:
+ TEST KB_FLAG_1,HOLD_STATE ; ARE WE IN HOLD STATE
+ JZ K40E ; EXIT IF NOT
+
+ifdef NOT_NTVDM
+ TEST BP,PC_XT+PC_LAP ; Check for systems without AUX BIOS
+ JNZ K40B ; For them, just loop on hold flag
+
+ IN AL,STATUS_PORT ; READ CURRENT STATUS
+ AND AL,MOUSE_OBF+OUT_BUF_FULL ; MASK OFF ALL BUT MOUSE DATA BITS
+ CMP AL,MOUSE_OBF+OUT_BUF_FULL ; IS THERE STILL MOUSE DATA PENDING?
+endif
+ LOOPE K40B ; WAIT FOR MOUSE DATA TO GO
+ JNE K40A ; CONTINUE IF PAUSE STATE ;an005
+K40E:
+ifndef NOT_NTVDM
+ call DOCLI
+endif
+ AND KB_FLAG_1,NOT HOLD_STATE ; CLEAR HOLD STATE FLAG
+ JMP K27A ; INTERRUPT_RETURN_NO_EOI PTR 2247
+
+;------ TEST SPECIAL CASE KEY 55
+
+K41: ; NO-PAUSE
+ CMP AL,55 ; TEST FOR */PRTSC KEY
+ JNE K42 ; NOT-KEY-55
+ TEST BP,PC_LAP ; IS THIS THE LAP COMPUTER?
+ JZ K41B ; NO, JUMP
+ TEST BH,LC_E0 ; YES, WAS LAST CODE AN E0?
+ JZ K41A ; NO, THIS IS THE PRTSC KEY
+ JMP SHORT K42B ; YES, E0 MEANS THE "*" KEY
+
+K41B: TEST BH,KBX ; IS THIS THE ENHANCED KEYBOARD?
+ JZ K41A ; NO, CTL-PRTSC IS VALID
+ TEST BH,LC_E0 ; YES, WAS LAST CODE AN E0?
+ JZ K42B ; NO, TRANSLATE TO A FUNCTION
+K41A: MOV AX,114*256 ; START/STOP PRINTING SWITCH
+ JMP K57 ; BUFFER_FILL
+
+;------ SET UP TO TRANSLATE CONTROL SHIFT
+
+K42: ; NOT-KEY-55
+ CALL KEYB_STATE_PROCESSOR
+ JC K449 ;K26 ; TRANSLATIONS FOUND - EXIT
+
+ CMP AL,15 ; IS IT THE TAB KEY?
+ JE K42B ; YES, XLATE TO FUNCTION CODE
+ CMP AL,53 ; IS IT THE / KEY?
+ JNE K42A ; NO, NO MORE SPECIAL CASES
+ TEST BH,LC_E0 ; YES, IS IT FROM THE KEYPAD?
+ JZ K42A ; NO, JUST TRANSLATE
+ MOV AX,9500h ; YES, SPECIAL CODE FOR THIS ONE
+ JMP K57 ; BUFFER FILL
+
+K42A: MOV BX,OFFSET K8 ; SET UP TO TRANSLATE CTL
+ CMP AL,59 ; IS IT IN CHARACTER TABLE?
+ JB K45F ; YES, GO TRANSLATE CHAR
+K42B: MOV BX,OFFSET K8 ; SET UP TO TRANSLATE CTL
+ JMP K64 ; NO, GO TRANSLATE_SCAN
+PAGE
+;------ NOT IN CONTROL SHIFT
+
+K44:
+ CALL KEYB_STATE_PROCESSOR
+ JC K449 ;K26 ; TRANSLATIONS FOUND - EXIT
+
+ CMP AL,55 ; PRINT SCREEN KEY?
+ JNE K45 ; NOT-PRINT-SCREEN
+ TEST BP,PC_LAP ; IS THIS THE LAP COMPUTER?
+ JZ K441 ; NO, JUMP
+ TEST BH,LC_E0 ; YES, WAS LAST CODE THE MARKER?
+ JZ K44A ; NO, TEST THE SHIFT STATE
+ JMP SHORT K45C ; YES, XLATE TO "*" CHAR
+K441: TEST BH,KBX ; IS THIS ENHANCED KEYBOARD?
+ JZ K44A ; NO, TEST FOR SHIFT STATE
+ TEST BH,LC_E0 ; YES, LAST CODE A MARKER?
+ JNZ K44B ; YES, IS PRINT SCREEN
+ JMP SHORT K45C ; NO, XLATE TO "*" CHARACTER
+K44A: TEST BL,LEFT_SHIFT+RIGHT_SHIFT ;NOT 101 KBD, SHIFT KEY DOWN?
+ JZ K45C ; NO, XLATE TO "*" CHARACTER
+
+;------ ISSUE INTERRUPT TO PERFORM PRINT SCREEN FUNCTION
+K44B:
+ ;; NTVDM CLI ; DISABLE INTERRUPTS PTR 2355
+ AND KB_FLAG_3,NOT LC_E0+LC_E1 ;ZERO OUT THESE FLAGS
+
+ifdef NOT_NTVDM
+ MOV AL,ENA_KBD ; INSURE KEYBOARD IS ENABLED
+ CALL SHIP_IT ; EXECUTE ENABLE
+else
+ mov ah, 3 ; K27A exit notify
+ BOP 09h
+endif
+ PUSH BP ; SAVE POINTER (compatibility)
+ INT 5H ; ISSUE PRINT SCREEN INTERRUPT
+ POP BP ; RESTORE POINTER
+ JMP K27A ; EXIT WITHOUT EXTRA EOI OR ENABLE
+
+K449:
+ JMP K26 ; EXIT
+
+;------ HANDLE THE IN-CORE KEYS
+K45: ; NOT-PRINT-SCREEN
+ CMP AL,58 ; TEST FOR IN-CORE AREA
+ JA K46 ; JUMP IF NOT
+
+ TEST BH,GRAPH_ON ; IS ALT GRAPHICS ON? AEV
+ JNZ K449 ;K26 ; YES, TRASH KEYSTROKE
+
+ CMP AL,53 ; IS THIS THE "/" KEY?
+ JNE K45A ; NO, JUMP
+ TEST BH,LC_E0 ; WAS LAST CODE THE MARKER?
+ JNZ K45C ; YES, TRANSLATE TO CHARACTER
+
+K45A: MOV CX,K30_LEN ; LENGTH OF SEARCH
+ MOV DI,OFFSET K30+10 ; POINT TO TABLE OF A-Z CHARS
+ REPNE SCASB ; IS THIS A LETTER KEY?
+ JNE K45B ; NO, SYMBOL KEY
+
+ TEST BL,CAPS_STATE ; ARE WE IN CAPS_LOCK?
+ JNZ K45D ; TEST FOR SURE
+K45B: TEST BL,LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
+ JNZ K45E ; YES, UPPERCASE
+ ; NO, LOWERCASE
+K45C: MOV BX,OFFSET K10 ; TRANSLATE TO LOWERCASE LETTERS
+ JMP SHORT K56
+K45D: ; ALMOST-CAPS-STATE
+ TEST BL,LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
+ JNZ K45C ; SHIFTED TEMP OUT OF CAPS STATE
+K45E: MOV BX,OFFSET K11 ; TRANSLATE TO UPPERCASE LETTERS
+K45F: JMP SHORT K56
+
+
+;------ TEST FOR KEYS F1 - F10
+K46: ; NOT IN-CORE AREA
+ CMP AL,68 ; TEST FOR F1 - F10
+ JA K47 ; JUMP IF NOT
+ JMP SHORT K53A ; YES, GO DO FN KEY PROCESS
+
+
+;------ HANDLE THE NUMERIC PAD KEYS
+
+K47: ; NOT F1 - F10
+ CMP AL,83 ; TEST FOR NUMPAD KEYS
+ JA K52 ; JUMP IF NOT
+
+;------ KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
+K48: CMP AL,74 ; SPECIAL CASE FOR MINUS
+ JE K45E ; GO TRANSLATE (US & WT ARE SAME)
+ CMP AL,78 ; SPECIAL CASE FOR PLUS
+ JE K45E ; GO TRANSLATE (US & WT ARE SAME)
+ TEST BH,LC_E0 ; IS THIS ONE OF THE NEW KEYS?
+ JNZ K49 ; YES, TRANSLATE TO BASE STATE
+
+ TEST BL,NUM_STATE ; ARE WE IN NUM_LOCK?
+ JNZ K50 ; TEST FOR SURE
+ TEST BL,LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
+ JNZ K51 ; IF SHIFTED, REALLY NUM STATE
+
+;------ BASE CASE FOR KEYPAD
+K49: CMP AL,76 ; SPECIAL CASE FOR BASE STATE 5
+ JNE K49A ; CONTINUE IF NOT KEYPAD 5
+ TEST BP,EXT_16 ; IS THE EXTENDED INT 16 LOADED?
+ JZ K59 ;K26 ; NO, INGORE
+
+ MOV AL,0F0h ; SPECIAL ASCII CODE
+ JMP SHORT K57 ; BUFFER FILL
+K49A: MOV BX,OFFSET K10 ; BASE CASE TABLE
+ JMP SHORT K64 ; CONVERT TO PSEUDO SCAN
+
+;------ MIGHT BE NUM LOCK, TEST SHIFT STATUS
+K50: TEST BL,LEFT_SHIFT+RIGHT_SHIFT ;ALMOST-NUM-STATE
+ JNZ K49 ; SHIFTED TEMP OUT OF NUM STATE
+K51: JMP SHORT K45E ; REALLY_NUM_STATE
+ ; (US & WT ARE SAME)
+
+;------ TEST FOR THE NEW KEY ON WT KEYBOARDS
+
+K52: ; NOT A NUMPAD KEY
+ CMP AL,86 ; IS IT THE NEW WT KEY?
+ JNE K53 ; JUMP IF NOT
+ MOV AL,58 ; WE'RE GOING TO PULL A SNEAKY
+ JMP K45 ; TRICK HERE. WT TABLES ARE TOO SHORT TO
+ ; XLATE 86, SO WE'LL CHANGE IT TO CAPS_LOCK
+ ; AND PUT THE CHAR IN THE TABLES IN THE C_L
+ ; POSITION, SINCE C_L SCAN CODES NEVER GET
+ ; HERE ANYWAY.
+
+;------ MUST BE F11 OR F12
+
+K53: TEST BP,EXT_16 ; IS THE EXTENDED INT 16 THERE?
+ JZ K59 ; NO, INGORE F11 & F12 (NEAR RET)
+ ; F1 - F10 COME HERE, TOO
+K53A: TEST BL,LEFT_SHIFT+RIGHT_SHIFT ;TEST SHIFT STATE
+ JZ K49 ; JUMP, LOWERCASE PSEUDO SC'S
+
+ MOV BX,OFFSET K11 ; UPPER CASE PSEUDO SCAN CODES
+ JMP SHORT K64 ; TRANSLATE_SCAN
+PAGE
+;------ TRANSLATE THE CHARACTER
+
+K56: ; TRANSLATE-CHAR
+ DEC AL ; CONVERT ORIGIN
+ XLAT CS:K11 ; CONVERT THE SCAN CODE TO ASCII
+ TEST KB_FLAG_3,LC_E0 ; IS THIS A NEW KEY?
+ JZ K57 ; NO, GO FILL BUFFER
+ TEST BP,EXT_16 ; IS THE EXTENDED INT 16 THERE?
+ JZ K57 ; NO, DO COMPATIBLE OUTPUT
+ MOV AH,MC_E0 ; YES, PUT SPECIAL MARKER IN AH
+ JMP SHORT K57 ; PUT IT INTO THE BUFFER
+
+;------ TRANSLATE SCAN FOR PSEUDO SCAN CODES
+
+K64: ; TRANSLATE-SCAN-ORGD
+ DEC AL ; CONVERT ORIGIN
+ XLAT CS:K8 ; CTL TABLE SCAN
+ MOV AH,AL ; PUT VALUE INTO AH
+ xor al,al ; ZERO ASCII CODE
+ TEST KB_FLAG_3,LC_E0 ; IS THIS A NEW KEY?
+ JZ K57 ; NO, GO FILL BUFFER
+ TEST BP,EXT_16 ; IS THE EXTENDED INT 16 THERE?
+ JZ K57 ; NO, DO COMPATIBLE OUTPUT
+ MOV AL,MC_E0 ; YES, PUT SPECIAL MARKER IN AL
+
+;------ PUT CHARACTER INTO BUFFER
+
+K57: ; BUFFER-FILL
+ CALL BUFFER_FILL
+K59:
+ JMP K26 ;-- THAT'S ALL FOLKS --
+
+KEYB_INT_9 ENDP
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; Procedure: BUFFER_FILL
+;
+; Description:
+; Generate keyboard buffer entry
+;
+; Input Registers:
+; AX - the buffer entry
+; DS - BIOS data segment
+;
+; Output Registers:
+; None
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+BUFFER_ENTRY_OK DB NO ; YES if character put into buffer
+
+BUFFER_FILL PROC NEAR
+
+; CMP AL,-1 ; IS THIS AN IGNORE CHAR
+; JE K61B ; YES, EXIT (commented YST)
+ CMP AH,-1 ; LOOK FOR -1 PSEUDO SCAN
+ JE K61B ; EXIT
+;
+; BUFFER_FILL_ANY_CHAR is an alternate entry point to this PROC.
+; Entry at this point will avoid trashing ASCII values of 255.
+;
+BUFFER_FILL_ANY_CHAR LABEL NEAR
+
+ PUSH SI
+ PUSH BX
+ PUSH DS ; This routine may be called
+ ; externally so make sure DS points
+ MOV BX,DATA ; to BIOS data
+ MOV DS,BX
+
+ ;; NTVDM cli ; disable interrupts P724
+ MOV BX, BUFFER_TAIL ; GET THE END POINTER TO THE BUFFER
+ MOV SI,BX ; SAVE THE VALUE
+ INC BX ; MOVE TO NEXT WORD IN LIST
+ INC BX
+
+;; VERIFY IF THE CURRENT ROM LEVEL IN THE SYSTEM IS FOR THE ORIGINAL PC1
+
+ TEST BP,PC_81 ; CHECK FOR '81 DATE FLAG SET
+ JNE NOT_PC1 ; IF IT'S A LATER ROM RELEASE, BRANCH
+
+ CMP BX,OFFSET KB_BUFFER_END ; AT END OF BUFFER?
+ JNE K5 ; NO, CONTINUE
+ MOV BX,OFFSET KB_BUFFER ; YES, RESET TO BUFFER BEGINNING
+ JMP SHORT K5
+NOT_PC1:
+ CMP BX, BUFFER_END ; AT END OF BUFFER?
+ JNE K5 ; NO, CONTINUE
+ MOV BX, BUFFER_START ; YES, RESET TO BUFFER BEGINNING
+K5:
+ CMP BX,BUFFER_HEAD ; HAS THE BUFFER WRAPPED AROUND
+ JE K62 ; BUFFER_FULL_BEEP
+ MOV [SI],AX ; STORE THE VALUE
+ MOV BUFFER_TAIL,BX ; MOVE THE POINTER UP
+ MOV CS:BUFFER_ENTRY_OK,YES ; INDICATE WE PUT SOMETHING IN BUFFER
+ JMP SHORT K61A
+K62:
+ MOV CS:BEEP_PENDING,YES ; INDICATE WE NEED A BEEP
+K61A:
+ POP DS
+ POP BX
+ POP SI
+ ;; NTVDM sti ; enable interrupts P724
+K61B:
+ RET
+BUFFER_FILL ENDP
+
+PAGE
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; Procedure: ERROR_BEEP
+;
+; Description:
+; General routine to generate beep tones
+;
+; Input Registers:
+; None
+;
+; Output Registers:
+; None
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+ERROR_BEEP PROC NEAR
+
+ CMP CS:BEEP_PENDING,YES ; Q..SHOULD WE BEEP?
+ JNE NO_BEEP
+
+ MOV CS:BEEP_PENDING,NO ; Reset BEEP required
+ifndef NOT_NTVDM
+ mov ah, 0eh
+ mov al, 07h
+ int 10h
+
+else
+ MOV CX,216-32 ; NUMBER OF CYCLES FOR 1/8 SECOND TONE
+ IN AL,PORT_B ; Get control info
+ PUSH AX
+LOOP01:
+ AND AL,0FCH ; Turn off timer gate and speaker
+ OUT PORT_B,AL ; output to control - speaker off
+ CALL WAITFB ; half cycle time for tone
+ OR AL,2 ; turn on speaker
+ CLI ; Disable interrupts for 1/2 cycle, 300u
+ OUT PORT_B,AL ; output to control
+ CALL WAITFB ; another half cycle
+ STI ; Enable interrupts between 1/2 cycle
+ LOOP LOOP01
+
+ POP AX
+ OUT PORT_B,AL ; Restore control
+ MOV CX,32*2 ; Short delay count of 32 cycles
+LOOP02:
+ CALL WAITFB ; Add a short delay to complete 1/8 sec
+ LOOP LOOP02 ; Repeat
+ CLI ; Disable interrupts
+endif
+
+NO_BEEP:
+ RET ; RETURN
+ERROR_BEEP ENDP
+
+
+ifdef NOT_NTVDM
+WAITFB PROC NEAR ; DELAY FOR (CX)*15.085737 US
+ PUSH AX ; SAVE WORK REGISTER (AH)
+ PUSH CX ; SAVE COUNT
+ MOV CX,19 ; The half cycle time for 1745 hz
+ TEST BP,PC_AT+PC_386 ; IF THE SYSTEM IS AN 80x86
+ JNZ WAITF1 ; SKIP TO REFRESH BIT DELAY
+
+WAITF0:
+ NOP ; Force two fetch cycles on Model 30
+ LOOP WAITF0 ; SOFTWARE DELAY LOOP ON 808x MACHINES
+
+ JMP SHORT WAITFE ; EXIT
+
+WAITF1: ; USE TIMER 1 OUTPUT BITS
+ IN AL,PORT_B ; READ CURRENT COUNTER OUTPUT STATUS
+ AND AL,REFRESH_BIT ; MASK FOR REFRESH DETERMINE BIT
+ CMP AL,AH ; DID IT JUST CHANGE
+ JE WAITF1 ; WAIT FOR A CHANGE IN OUTPUT LINE
+
+ MOV AH,AL ; SAVE NEW FLAG STATE
+ LOOP WAITF1 ; DECREMENT HALF CYCLES TILL COUNT END
+WAITFE:
+
+ POP CX ; RESTORE COUNT
+ POP AX ; RESTORE (AH)
+ RET ; RETURN (CX)= 0
+
+WAITFB ENDP
+endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; SHIP_IT
+;
+; THIS ROUTINE HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
+; TO THE KEYBOARD CONTROLLER.
+;
+; On entry the AL contains the command byte.
+; On Enable keyboard commands, the reset keyboard input latch is done
+; if the system is the old PC type.
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+SHIP_IT PROC NEAR
+
+ifdef NOT_NTVDM
+;------- TEST SYSTEM TYPE
+ PUSHF ; SAVE FLAGS P725
+ CLI ; DISABLE INTERRUPTS TILL DATA SENT
+
+ TEST BP,PC_XT+PC_LAP
+ JZ SI5 ; USE AT 8042 COMMAND IF NOT PC TYPE
+
+ CMP AL,ENA_KBD ; CHECK FOR ENABLE KEYBOARD COMMAND
+ JNE SI9 ; SKIP ENABLE RESET
+ ; FOR PC, XT, P12: RESET THE KEYBOARD
+ PUSH AX ; SAVE AX
+ IN AL,KB_CTL ; GET THE CONTROL PORT
+ MOV AH,AL ; SAVE VALUE
+ OR AL,80H ; RESET BIT FOR KEYBOARD ON PC/PC-XT
+ OUT KB_CTL,AL
+ XCHG AH,AL ; GET BACK ORIGINAL CONTROL
+ OUT KB_CTL,AL ; KB HAS BEEN RESET
+ POP AX ; RESTORE AX
+ ; EXIT as NOT next system
+SI5:
+ TEST BP,PC_AT+PC_386 ; IF THE SYSTEM IS NOT AN 80x86
+ JZ SI9 ; MACHINE, EXIT THIS PROC.
+
+;------- WAIT FOR COMMAND TO BE ACCEPTED;
+
+ CALL chk_ibf ; GO READ KEYBOARD CONTROLLER STATUS
+endif
+
+ OUT STATUS_PORT,AL ; SEND TO KEYBOARD CONTROLLER
+
+ifdef NOT_NTVDM
+SI9: ; ENABLE INTERRUPTS AGAIN
+ POPF ; RESTORE FLAGS P725
+endif
+ RET ; RETURN TO CALLER
+SHIP_IT ENDP
+
+ifdef NOT_NTVDM
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; SND_DATA
+;
+; THIS ROUTINE HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
+; TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
+; HANDLES ANY RETRIES IF REQUIRED
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+SND_DATA PROC NEAR
+ PUSH AX ; SAVE REGISTERS
+ PUSH BX ; *
+ PUSH CX
+ MOV BH,AL ; SAVE TRANSMITTED BYTE FOR RETRIES
+
+ MOV BL,3 ; LOAD RETRY COUNT
+SD0:
+ CLI ; DISABLE INTERRUPTS
+ AND KB_FLAG_2,NOT (KB_FE+KB_FA+kb_err) ; CLEAR ACK, RESEND and
+ ; error flags
+
+ CALL CHK_IBF ; Wait for command accepted
+
+ MOV AL,BH ; REESTABLISH BYTE TO TRANSMIT
+ OUT PORT_A,AL ; SEND BYTE
+ STI ; ENABLE INTERRUPTS
+ MOV CX,DLY_15MS ; DELAY FOR 15 ms TIMEOUT
+SD1: TEST KB_FLAG_2,KB_FE+KB_FA ; SEE IF EITHER BIT SET
+ JNZ SD3 ; IF SET, SOMETHING RECEIVED GO PROCESS
+ IN AL,PORT_B ; WAIT LOOP USING REFRESH BIT
+ AND AL,REFRESH_BIT
+ CMP AL,AH
+ JE SD1 ; KEEP TESTING
+ MOV AH,AL ; DEC CX ON REFRESH TIC
+ LOOP SD1 ; KEEP TESTING
+ ; !! TIMEOUT !!
+
+SD2: DEC BL ; DECREMENT RETRY COUNT
+ JNZ SD0 ; RETRY TRANSMISSION
+ OR KB_FLAG_2,KB_ERR ; TURN ON TRANSMIT ERROR FLAG
+ JMP SHORT SD4 ; RETRIES EXHAUSTED FORGET TRANSMISSION
+
+SD3: TEST KB_FLAG_2,KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
+ JZ SD2 ; IF NOT, GO RESEND
+
+SD4: POP CX ; RESTORE REGISTERS
+ POP BX
+ POP AX ; *
+ RET ; RETURN, GOOD TRANSMISSION
+SND_DATA ENDP
+endif
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; SND_LED
+;
+; THIS ROUTINE TURNS ON THE MODE INDICATORS.
+;
+; NTVDM - we do not need to update led's as this is controlled
+; by the host\system. We also assume that interrupts are
+; off upon entry
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+SND_LED PROC NEAR
+ifdef NOT_NTVDM
+ CLI ; TURN OFF INTERRUPTS
+
+ TEST BP,PC_AT+PC_386 ; IF THE SYSTEM IS NOT A 80x86
+ JZ SL1 ; MACHINE, EXIT THIS PROC
+endif
+
+ TEST KB_FLAG_2,KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
+ JNZ SL1 ; DONT UPDATE AGAIN IF UPDATE UNDERWAY
+ OR KB_FLAG_2,KB_PR_LED ; TURN ON UPDATE IN PROCESS
+ifdef NOT_NTVDM
+ MOV AL,LED_CMD ; LED CMD BYTE
+ CALL SND_DATA ; SEND DATA TO KEYBOARD
+ CLI
+endif
+ CALL MAKE_LED ; GO FORM INDICATOR DATA BYTE
+ AND KB_FLAG_2,0F8H ; CLEAR MODE INDICATOR BITS
+ OR KB_FLAG_2,AL ; SAVE PRESENT INDICATORS FOR NEXT TIME
+
+ mov ah, 3 ; inform softpc to set lights
+ BOP 16h
+
+
+ifdef NOT_NTVDM
+ TEST KB_FLAG_2,KB_ERR ; TRANSMIT ERROR DETECTED
+ JNZ SL2 ; YES, BYPASS SECOND BYTE TRANSMISSION
+ CALL SND_DATA ; SEND DATA TO KEYBOARD
+ CLI ; TURN OFF INTERRUPTS
+ TEST KB_FLAG_2,KB_ERR ; TRANSMIT ERROR DETECTED
+ JZ SL3 ; IF NOT, DONT SEND AN ENABLE COMMAND
+SL2: MOV AL,KB_ENABLE ; GET KEYBOARD CSA ENABLE COMMAND
+ CALL SND_DATA ; SEND DATA TO KEYBOARD
+ CLI ; TURN OFF INTERRUPTS
+endif
+
+SL3: AND KB_FLAG_2,NOT(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
+ ; UPDATE AND TRANSMIT ERROR FLAG
+SL1:
+ifdef NOT_NTVDM
+ STI ; ENABLE INTERRUPTS
+endif
+ RET ; RETURN TO CALLER
+SND_LED ENDP
+PAGE
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; MAKE_LED
+;
+; THIS ROUTINE FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
+; THE MODE INDICATORS
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+MAKE_LED PROC NEAR
+ PUSH CX ; SAVE CX
+ MOV AL, KB_FLAG ; GET CAPS & NUM LOCK INDICATORS
+ AND AL,CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
+ MOV CL,4 ; SHIFT COUNT
+ ROL AL,CL ; SHIFT BITS OVER TO TURN ON INDICATORS
+ AND AL,07H ; MAKE SURE ONLY MODE BITS ON
+ POP CX
+ RET ; RETURN TO CALLER
+MAKE_LED ENDP
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; CHK_IBF
+;
+; Description:
+; Waits for a keyboard command to be accepted
+; wait until ibf = 0 (empty)
+;
+; Input Registers:
+; None
+;
+; Output Registers:
+; ZF=0 time out & IBF still full
+; ZF=1 IBF is empty
+;
+; ---------------------------------------------------------------
+; This procedure replaces the previous one which used a software
+; timing loop. (For 80286, 80386 and 80486 based machines.)
+; ---------------------------------------------------------------
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+chk_ibf proc near
+
+ push ax ; Save register used
+ push cx
+ mov cx,DLY_15MS ; Timeout 15 milleseconds (15000/15.086;
+chk_ibfl:
+ in al,PORT_B ; Read current refresh output bit
+ and al,refresh_bit ; Mask all but refresh bit
+ cmp al,ah ; Did it change? (or first pass thru)
+ jz short chk_ibfl ; No, wait for change, else continue
+
+ mov ah,al ; Save new refresh bit state
+ in al,status_port ; Read status port
+ test al,inpt_buf_full ; Check for input buffer empty
+ loopnz chk_ibfl ; Loop until input buf empty or timeout;
+
+ pop cx
+ pop ax ; Restore register used
+ ret ; Return to caller
+
+chk_ibf endp
+
+
+
+DOSTI proc near
+ FSTI
+ ret
+DOSTI endp
+
+DOCLI proc near
+ FCLI
+ ret
+DOCLI endp
+
+DOIRET:
+ FIRET
+
+CODE ENDS
+ END