1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
|
PAGE ,132
TITLE DOS KEYB Command - Interrupt 9 Non-US Support
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; DOS - NLS Support - KEYB Command
;; (C) Copyright 1988 Microsoft
;;
;; File Name: KEYBI9.ASM
;; ----------
;;
;; Description:
;; ------------
;; Converts scan codes to ASCII for non-US keyboards.
;; This orutine uses the tables loaded into the SHARED_DATA_AREA
;; from KEYBOARD.SYS by the KEYB_COMMAND module.
;;
;; Documentation Reference:
;; ------------------------
;; PC DOS 3.3 Detailed Design Document - May 1986
;;
;; Procedures Contained in This File:
;; ----------------------------------
;; KEYB_STATE_PROCESSOR - Scan to ASCII translator.
;;
;; External Procedure References:
;; ------------------------------
;; None.
;;
;; Linkage Information: Refer to file KEYB.ASM
;; --------------------
;;
;; Change History:
;; ---------------
;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;****
INCLUDE KEYBEQU.INC ;;
INCLUDE DSEG.inc ;; System data segments
INCLUDE POSTEQU.inc ;; System equates
INCLUDE KEYBSHAR.INC ;;
INCLUDE KEYBI2F.INC ;;
INCLUDE KEYBI9C.INC ;;
INCLUDE KEYBCPSD.INC ;;
INCLUDE KEYBCMD.INC ;;
;;
PUBLIC KEYB_STATE_PROCESSOR ;;
;;
CODE SEGMENT PUBLIC 'CODE' ;;
;;
ASSUME CS:CODE,DS:CODE ;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Procedure: KEYB_STATE_PROCESSOR
;;
;; Description:
;; Convert scan to ASCII using the tables loaded into the
;; SHARED_DATA_AREA. Conversion is directed by the STATE LOGIC
;; commands contained in the SHARED_DATA_AREA. This routine
;; interprets those commands.
;;
;; Input Registers:
;; N/A
;;
;; Output Registers:
;; N/A
;;
;; Logic:
;; Enable interrupts
;; Save registers
;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
BREAK_CODE EQU 80H ;;
;;
HOT_KEY_ACTIVE DB 0 ;; 1 if hot key is active
;;
;;
;; These are copies of the BIOS FLAGS
FLAGS_TO_TEST LABEL BYTE ;; KB_FLAG, KB_FLAG_1,2,3
KB_SHADOW_FLAGS DB NUM_BIOS_FLAGS DUP(0) ;;
EXT_KB_FLAG DB 0 ;; Extended KB Flag for shift states
NLS_FLAG_1 DB 0 ;; NLS Flags for dead key etc
NLS_FLAG_2 DB 0 ;; .
;;
SAVED_NLS_FLAGS DB 0,0 ;; Saved copy of the NLS flags
;;
OPTION_BYTE DB 0 ;; Set by OPTION command
;;
KB_FLAG_PTRS DW OFFSET KB_FLAG ;; These are pointers to the BIOS flags
DW OFFSET KB_FLAG_1 ;; we must test
DW OFFSET KB_FLAG_2 ;;
DW OFFSET KB_FLAG_3 ;;
;;
XLAT_TAB_PTR DW 0 ;; pointer to xlat tables for cur state
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NEST_LEVEL DB 0 ;;
PROCESS_LEVEL DB 0 ;;
TAKE_ELSE DB 0 ;;
BUSY_FLAG DB 0 ;; Flag to prevent re-entry
;;
CMD_JUMP_TABLE LABEL WORD ;;
DW OFFSET IFF_PROC ;; CODE 0
DW OFFSET ANDF_PROC ;; 1
DW OFFSET ELSEF_PROC ;; 2
DW OFFSET ENDIFF_PROC ;; 3
DW OFFSET XLATT_PROC ;; 4
DW OFFSET OPTION_PROC ;; 5
DW OFFSET SET_FLAG_PROC ;; 6
DW OFFSET PUT_ERROR_PROC ;; 7
DW OFFSET IFKBD_PROC ;; 8
DW OFFSET GOTO_PROC ;; 9
DW OFFSET BEEP_PROC ;; A
DW OFFSET RESET_NLS_PROC ;; B
DW OFFSET UNKNOWN_COMMAND ;; C
DW OFFSET UNKNOWN_COMMAND ;; D
DW OFFSET UNKNOWN_COMMAND ;; E
DW OFFSET UNKNOWN_COMMAND ;; F
;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
KEYB_STATE_PROCESSOR PROC NEAR ;;
;;
TEST CS:SD.TABLE_OK,1 ;;
JNZ WE_HAVE_A_TABLE ;;
CLC ;; BACK TO US INT 9
RET ;;
EVEN
WE_HAVE_A_TABLE: ;;
PUSH DS ;; save DS
PUSH ES ;; save ES
PUSH AX ;; save scan code for caller
PUSH BX ;; save shift states for caller
PUSH CS ;;
POP DS ;; DS = our seg
MOV BX,DATA ;;
MOV ES,BX ;; addressability to BIOS data
;;
;;
CMP COUNTRY_FLAG,0FFH ;; Q..country mode?
JE INIT_STATE_PROCESSING ;; Y..continue
JMP GOTO_BIOS ;; N..exit
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; -------STATE SECTION PROCESSING-------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
INIT_STATE_PROCESSING: ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Set NLS shift flags EITHER_SHIFT, EITHER_ALT, EITHER_CTRL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Q..in shift state?
TEST ES:KB_FLAG,RIGHT_SHIFT+LEFT_SHIFT
JNZ IN_SHIFT_STATE ;; Y..go set bit
AND EXT_KB_FLAG,NOT EITHER_SHIFT ;; N..clear bit
JMP SHORT TEST_CTL ;;
IN_SHIFT_STATE: ;;
OR EXT_KB_FLAG,EITHER_SHIFT ;;
TEST_CTL: ;;
TEST ES:KB_FLAG,CTL_SHIFT ;; Q..in control state?
JNZ IN_CTL_STATE ;; Y..go set bit
TEST ES:KB_FLAG_3,R_CTL_SHIFT ;; Q..how bout the right ctl?
JNZ IN_CTL_STATE ;; Y..go set the bit
AND EXT_KB_FLAG,NOT EITHER_CTL ;; N..clear the bit
JMP SHORT TEST_ALT ;;
IN_CTL_STATE: ;;
OR EXT_KB_FLAG,EITHER_CTL ;;
TEST_ALT: ;;
TEST ES:KB_FLAG,ALT_SHIFT ;; Q..in alt state?
JNZ IN_ALT_STATE ;; Y..go set bit
TEST ES:KB_FLAG_3,R_ALT_SHIFT ;; Q..how bout the right alt?
JNZ IN_ALT_STATE ;; Y..go set the bit
AND EXT_KB_FLAG,NOT EITHER_ALT ;; N..clear the bit
JMP SHORT COPY_FLAGS ;;
IN_ALT_STATE: ;;
OR EXT_KB_FLAG,EITHER_ALT ;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Copy BIOS KB flags from BIOS data seg into the
;; FLAGS_TO_TEST structure.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
COPY_FLAGS: ;;
MOV CX,NUM_BIOS_FLAGS ;;
MOV SI,0 ;; pointers to the BIOS flags
MOV DI,0 ;; create shadow copies
MOVE_NEXT_FLAG: ;;
MOV BX,KB_FLAG_PTRS[SI] ;; pointer to next flag
MOV AL,ES:[BX] ;; flag in AL
MOV KB_SHADOW_FLAGS[DI],AL ;; save it in the shadow table
INC DI ;;
INC SI ;;
INC SI ;;
LOOP MOVE_NEXT_FLAG ;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Interpret State Logic Commands
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
PROCESS_STATES: ;;
MOV OPTION_BYTE,0 ;; clear options
MOV SI,SD.LOGIC_PTR ;;
LEA SI,[SI].SL_LOGIC_CMDS ;;
NEXT_COMMAND: ;;
MOV BL,[SI] ;; command byte in BL
SHR BL,1 ;;
SHR BL,1 ;;
SHR BL,1 ;;
SHR BL,1 ;; ISOLATE COMMAND CODE
SHL BL,1 ;; command code * 2
JMP CMD_JUMP_TABLE[BX] ;; go process command
UNKNOWN_COMMAND: ;;
JMP FATAL_ERROR ;; bad news
;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IFKBD_PROC: ;;
MOV AL,NEST_LEVEL ;;
CMP AL,PROCESS_LEVEL ;; Q..nest level = process level?
JNE IFKBD_DONE ;; N..don't process
MOV AX,[SI+1] ;; Keyboard Type Flag
;;
TEST SD.KEYB_TYPE,AX ;; Q..are we the right system?
JNZ IFKBD_TEST_OK ;; Y..
IFKBD_TEST_FAILED: ;;
MOV TAKE_ELSE,YES ;; test failed - take ELSE
JMP SHORT IFKBD_DONE ;;
IFKBD_TEST_OK: ;;
INC PROCESS_LEVEL ;; process commands within IF
MOV TAKE_ELSE,NO ;;
IFKBD_DONE: ;;
INC NEST_LEVEL ;; IFKBD increments nest level
INC SI ;; bump past IFKBD
INC SI ;;
INC SI ;;
JMP NEXT_COMMAND ;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
PUT_ERROR_PROC: ;;
MOV AL,NEST_LEVEL ;;
CMP AL,PROCESS_LEVEL ;; Q..nest level = process level?
JNE PUT_ERROR_DONE ;; N..don't process
MOV DI,SD.ACTIVE_XLAT_PTR ;; pointer to active Xlat Section
MOV AL,[SI+1] ;; state id in AL
CALL PUT_ERROR ;; check active section
JC PUT_ERROR_DONE ;; carry set if translation found
MOV DI,SD.COMMON_XLAT_PTR ;; check common Xlat Section
MOV AL,[SI+1] ;; state id for XLATT in AL
CALL PUT_ERROR ;;
;;
PUT_ERROR_DONE: ;;
INC SI ;;
INC SI ;;
JMP NEXT_COMMAND ;;
;;
PUT_ERROR PROC ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Search for a state whose ID matches the ID
;; on the PUT_ERROR command
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
CLC ;;
LEA DI,[DI].XS_FIRST_STATE ;; point to first state in section
PE_NEXT_STATE: ;;
CMP [DI].XS_STATE_LEN,0 ;; Q..out of states?
JE PE_EXIT ;; Y..exit
CMP AL,[DI].XS_STATE_ID ;; Q..is this the requested state?
JE PE_STATE_MATCH ;;
ADD DI,[DI].XS_STATE_LEN ;; N..check next state
JMP SHORT PE_NEXT_STATE ;;
;;
PE_STATE_MATCH: ;;
MOV AX,[DI].XS_ERROR_CHAR ;; get error char in AX
CALL BUFFER_FILL ;;
STC ;; indicate that we found the state
PE_EXIT: ;;
RET ;;
;;
PUT_ERROR ENDP ;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
GOTO_BIOS: ;;
CLC ;; clear carry flag indicating
POP BX ;; we should continue INT 9
POP AX ;; processing
POP ES ;;
POP DS ;;
RET ;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
IFF_PROC: ;;
MOV AL,NEST_LEVEL ;;
CMP AL,PROCESS_LEVEL ;; Q..nest level = process level?
JNE IFF_DONE ;; N..don't process IFF
MOV BL,[SI] ;; command byte
AND BL,FLAG_ID_BITS ;; isolate flag id
XOR BH,BH ;;
MOV AL,FLAGS_TO_TEST[BX] ;; flag in AL
TEST BYTE PTR[SI],NOT_TEST ;; Q..is this a NOT test?
JNZ ITS_A_NOT ;;
TEST AL,[SI]+1 ;; Y..check for bit set
JNZ IFF_MATCH ;;
JZ IFF_NO_MATCH ;;
ITS_A_NOT: ;;
TEST AL,[SI]+1 ;; Y..check for bit clear
JZ IFF_MATCH ;;
IFF_NO_MATCH: ;;
MOV TAKE_ELSE,YES ;; flag test failed - take ELSE
JMP SHORT IFF_DONE ;;
IFF_MATCH: ;;
INC PROCESS_LEVEL ;; process commands within IF
MOV TAKE_ELSE,NO ;;
;;
IFF_DONE: ;;
INC NEST_LEVEL ;; IFF increments nest level
INC SI ;; bump past IFF
INC SI ;;
JMP NEXT_COMMAND ;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
ELSEF_PROC: ;;
MOV AL,PROCESS_LEVEL ;;
CMP AL,NEST_LEVEL ;; Q..nest level = process level?
JNE CHECK_TAKE_ELSEF ;; N..check for take_else
DEC PROCESS_LEVEL ;; Y..we just finished the "IF" block
JMP ELSEF_DONE ;; so we are finished with IFF/ELSEF
CHECK_TAKE_ELSEF: ;;
CMP TAKE_ELSE,YES ;; Q..are we scanning for ELSE?
JNE ELSEF_DONE ;; N..done
DEC NEST_LEVEL ;; ELSEF itself is back a level
CMP AL,NEST_LEVEL ;; Q..nest level = process level?
JNE NOT_THIS_ELSEF ;; N..this else is not the one
INC PROCESS_LEVEL ;; Y..process ELSEF block
MOV TAKE_ELSE,NO ;; reset
NOT_THIS_ELSEF: ;;
INC NEST_LEVEL ;; stuff within the ELSEF is up a level
;;
ELSEF_DONE: ;;
INC SI ;; bump past ELSEF
JMP NEXT_COMMAND ;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ENDIFF_PROC: ;;
MOV AL,PROCESS_LEVEL ;;
CMP AL,NEST_LEVEL ;; Q..nest level = process level?
JNE ENDIFF_DONE ;; N..don't adjust process level
DEC PROCESS_LEVEL ;; Y..we just finished the IF/ELSE
ENDIFF_DONE: ;;
DEC NEST_LEVEL ;; ENDIF decrements nest level
INC SI ;; bump past ENDIF
JMP NEXT_COMMAND ;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Translations may be in the Common or Specific
;; Sections. Search the Specific section first
;; then the common section.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
XLATT_PROC: ;;
MOV AL,PROCESS_LEVEL ;;
CMP AL,NEST_LEVEL ;; Q..nest level = process level?
JNE XLATT_DONE ;; N..next command
MOV DI,SD.ACTIVE_XLAT_PTR ;; pointer to active Xlat Section
MOV AL,[SI+1] ;; state id for XLATT in AL
CALL TRANSLATE ;; check active section
JC XLATT_FOUND ;; carry set if translation found
MOV DI,SD.COMMON_XLAT_PTR ;; check common Xlat Section
MOV AL,[SI+1] ;; state id for XLATT in AL
CALL TRANSLATE ;;
JNC XLATT_DONE ;;
XLATT_FOUND: ;;
OR EXT_KB_FLAG,SCAN_MATCH ;; set flag indicating scan matched
TEST OPTION_BYTE,EXIT_IF_FOUND ;; Q..exit
JZ XLATT_DONE ;;
JMP EXIT ;; Y..BYE
;;
XLATT_DONE: ;;
INC SI ;;
INC SI ;;
JMP NEXT_COMMAND ;;
;;
TRANSLATE PROC ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Search for a state whose ID matches the ID
;; on the XLATT command
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
CLC ;;
LEA DI,[DI].XS_FIRST_STATE ;; point to first state in section
TP_NEXT_STATE: ;;
CMP [DI].XS_STATE_LEN,0 ;; Q..out of states?
JE TP_EXIT ;; Y..exit
CMP AL,[DI].XS_STATE_ID ;; Q..is this the requested state?
JE TP_STATE_MATCH ;;
ADD DI,[DI].XS_STATE_LEN ;; N..check next state
JMP SHORT TP_NEXT_STATE ;;
;;
TP_STATE_MATCH: ;;
AND EXT_KB_FLAG,NOT SCAN_MATCH ;; reset flag before search
PUSH SI ;; save pointer to next command
LEA SI,[DI].XS_FIRST_TAB ;; point to first xlat table
MOV XLAT_TAB_PTR,SI ;; start of XLAT tables
MOV AL,SCAN_CODE ;; restore incoming scan code
JMP SHORT NEXT_XLAT_TAB ;;
TP_DONE: ;; return here from XLAT
POP SI ;;
TP_EXIT: ;;
RET ;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Check xlate tables for matching scan code
;; The xlate table can be in one of two forms:
;; Type 1 = Table contains buffer entries only.
;; Scan code is used as an index into xlat table
;; Type 2 = Table contains pairs of SCAN/BUFFER_ENTRY.
;; Table must be searched for matching scan.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
NEXT_XLAT_TAB: ;;
MOV SI,XLAT_TAB_PTR ;; pointer to xlat tables
CMP [SI].XLAT_TAB_SIZE,0 ;; Q..any more xlat tables?
JNE PROCESS_XLAT_TAB ;; Y..check um
JMP TP_DONE ;; N..done
PROCESS_XLAT_TAB: ;;
MOV DL,[SI].XLAT_OPTIONS ;; save translate options IN DL
MOV BX,[SI].XLAT_TAB_SIZE ;; Y..calc pointer to next xlat tab
ADD BX,SI ;;
MOV XLAT_TAB_PTR,BX ;; pointer to next xlat tab
TEST DL,TYPE_2_TAB ;; Q..is this a type 2 table?
JZ TYPE_1_LOOKUP ;; N..go do table lookup
TYPE_2_SEARCH: ;; Y..search table
XOR CH,CH ;;
MOV CL,[SI].XLAT_NUM ;; number of xlat entries
MOV BX,DEFAULT_TAB_2_ENT_SZ ;; default entry size
TEST DL,ASCII_ONLY+ZERO_SCAN ;; Q..are buffer entries ASCII only?
JZ NEXT_TAB_2_ENTRY ;; N..continue
MOV BX,ASC_ONLY_TAB_2_ENT_SZ ;; Y..set size in BX
NEXT_TAB_2_ENTRY: ;; entry size is in BX
CMP CX,0 ;; Q..last entry?
JE NEXT_XLAT_TAB ;; y..go to next table
CMP AL,[SI].XLAT_SCAN ;; Q..scan match?
JE FOUND_TAB_2_ENTRY ;; Y..go create buffer entry
ADD SI,BX ;; point to next entry
LOOP NEXT_TAB_2_ENTRY ;;
JMP SHORT NEXT_XLAT_TAB ;;
FOUND_TAB_2_ENTRY: ;; Q..set scan code to 0?
MOV AH,AL ;; default scan code in AH
MOV AL,[SI].XLAT_2_BUF_ENTRY ;; ASCII code from table in AL
TEST DL,ASCII_ONLY+ZERO_SCAN ;; Q..are buffer entries ASCII only?
JNZ BUFFER_ENTRY_READY ;; Y..buffer entry is ready
MOV AH,[SI].XLAT_2_BUF_ENTRY+1 ;; N..scan code from table as well
JMP SHORT BUFFER_ENTRY_READY ;; go put entry in buffer
;;
TYPE_1_LOOKUP: ;;
CMP AL,[SI].XLAT_SCAN_LO ;; Q..is scan in range of this table?
JB NEXT_XLAT_TAB ;; N..next table
CMP AL,[SI].XLAT_SCAN_HI ;; Q..is scan in range of this table?
JA NEXT_XLAT_TAB ;; N..next table
SUB AL,[SI].XLAT_SCAN_LO ;; convert scan code to xlat index
TEST DL,ASCII_ONLY+ZERO_SCAN ;; Q..ASCII only in xlat ?
JZ TWO_BYTE_LOOKUP ;; N..go do 2-byte lookup
LEA BX,[SI].XLAT_1_BUF_ENTRY ;; Y..do 1-byte lookup
XLAT [SI].XLAT_1_BUF_ENTRY ;; ASCII code in AL
MOV AH,SCAN_CODE ;; SCAN in AH
JMP SHORT BUFFER_ENTRY_READY ;; go put entry in buffer
TWO_BYTE_LOOKUP: ;;
MOV BL,2 ;; multiply scan index
MUL BL ;; by two
MOV BX,AX ;; real index in BX
MOV AX,WORD PTR [SI].XLAT_1_BUF_ENTRY[BX] ;; get 2-byte buffer entry
;; AL=ASCII AH=SCAN
BUFFER_ENTRY_READY: ;;
TEST DL,ZERO_SCAN ;; Q..set scan part to zero?
JZ NO_ZERO_SCAN ;; N..
XOR AH,AH ;; scan = 0
NO_ZERO_SCAN: ;;
CALL BUFFER_FILL ;; go put entry in buffer
STC ;; indicate translation found
JMP TP_DONE ;;
;;
TRANSLATE ENDP ;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
OPTION_PROC: ;;
MOV AL,PROCESS_LEVEL ;;
CMP AL,NEST_LEVEL ;; Q..nest level = process level?
JNE DONE_OPTION ;; N..done
MOV AL,[SI]+1 ;; mask in AL
TEST BYTE PTR[SI],NOT_TEST ;; Q..is this a NOT?
JNZ AND_MASK ;;
OR OPTION_BYTE,AL ;; N..OR in the mask bits
JMP DONE_OPTION ;;
AND_MASK: ;;
NOT AL ;;
AND OPTION_BYTE,AL ;; Y..AND out the mask bits
DONE_OPTION: ;;
INC SI ;;
INC SI ;;
JMP NEXT_COMMAND ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RESET_NLS_PROC: ;;
MOV AL,NEST_LEVEL ;;
CMP AL,PROCESS_LEVEL ;; Q..nest level = process level?
JNE RN_DONE ;; N..don't process
MOV NLS_FLAG_1,0 ;;
MOV NLS_FLAG_2,0 ;;
RN_DONE: ;;
INC SI ;;
JMP NEXT_COMMAND ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BEEP_PROC: ;;
MOV AL,NEST_LEVEL ;;
CMP AL,PROCESS_LEVEL ;; Q..nest level = process level?
JNE BP_DONE ;; N..don't process
MOV BEEP_PENDING,YES ;; set beep pending flag. the beep
;; will be done just before iret
BP_DONE: ;;
INC SI ;;
JMP NEXT_COMMAND ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GOTO_PROC: ;;
MOV AL,NEST_LEVEL ;;
CMP AL,PROCESS_LEVEL ;; Q..nest level = process level?
JNE GOTO_DONE ;; N..don't process
MOV BL,[SI] ;; command byte in BL
AND BL,NOT COMMAND_BITS ;; remove command code
OR BL,BL ;; Q..goto label?
JZ GOTO_LABEL ;; Y..go jump
CMP BL,EXIT_INT_9_FLAG ;; Q..SPECIAL - Exit Int 9?
JNE NOT_EXIT_INT_9 ;; N..
JMP EXIT ;; Y..bye bye
NOT_EXIT_INT_9: ;;
CMP BL,EXIT_STATE_LOGIC_FLAG ;; Q..SPECIAL - Exit State Logic?
JNE NOT_EXIT_S_L ;; N..
JMP GOTO_BIOS ;; Y..goto bios
NOT_EXIT_S_L: ;;
JMP FATAL_ERROR ;; garbage in that command
GOTO_LABEL: ;;
ADD SI,[SI]+1 ;; bump by relative offset
MOV PROCESS_LEVEL,0 ;; reset process and nest level
MOV NEST_LEVEL,0 ;;
GOTO_DONE: ;;
ADD SI,3 ;; bump to next command
JMP NEXT_COMMAND ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
ANDF_PROC: ;;
MOV AL,NEST_LEVEL ;;
CMP AL,PROCESS_LEVEL ;; Q..nest level = process level?
JNE ANDF_DONE ;; N..don't process ANDF
MOV BL,[SI] ;; command byte
AND BL,FLAG_ID_BITS ;; isolate flag id
XOR BH,BH ;;
MOV AL,FLAGS_TO_TEST[BX] ;; flag in AL
TEST BYTE PTR[SI],NOT_TEST ;; Q..is this a NOT test?
JNZ ANDF_NOT ;;
TEST AL,[SI]+1 ;; Y..check for bit set
JNZ ANDF_DONE ;; if set then remain in IFF
JZ ANDF_NO_MATCH ;;
ANDF_NOT: ;;
TEST AL,[SI]+1 ;; Y..check for bit clear
JZ ANDF_DONE ;; if clear then remain in IFF
ANDF_NO_MATCH: ;;
MOV TAKE_ELSE,YES ;; flag test failed - take ELSE
DEC PROCESS_LEVEL ;; IFF would have inc'd - so dec
ANDF_DONE: ;;
INC SI ;; bump past ANDF
INC SI ;;
JMP NEXT_COMMAND ;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SET_FLAG Command.
;; Flag Table must be in the Common Section
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
SET_FLAG_PROC: ;;
MOV AL,NEST_LEVEL ;;
CMP AL,PROCESS_LEVEL ;; Q..nest level = process level?
JNE SF_DONE ;; N..don't process
;;
MOV DI,SD.COMMON_XLAT_PTR ;; check common Xlat Section
MOV AL,[SI+1] ;; state id in AL
LEA DI,[DI].XS_FIRST_STATE ;; point to first state in section
SF_NEXT_STATE: ;;
CMP [DI].XS_STATE_LEN,0 ;; Q..out of states?
JE SF_DONE ;; Y..exit
CMP AL,[DI].XS_STATE_ID ;; Q..is this the requested state?
JE SF_STATE_MATCH ;;
ADD DI,[DI].XS_STATE_LEN ;; N..check next state
JMP SHORT SF_NEXT_STATE ;;
;;
SF_STATE_MATCH: ;;
AND EXT_KB_FLAG,NOT SCAN_MATCH ;; reset flag before search
PUSH SI ;; save pointer to next command
LEA SI,[DI].XS_FIRST_TAB ;; point to table
MOV AL,SCAN_CODE ;; restore incoming scan code
MOV CX,[SI] ;; number of entries
CMP CX,0 ;; Q..any entries?
JE SF_RESTORE ;; N..done
INC SI ;; Y..Bump to first entry
INC SI ;;
NEXT_SF_ENTRY: ;;
CMP AL,[SI] ;; Q..scan match?
JE FOUND_SF_ENTRY ;; Y..go set flag
ADD SI,3 ;; point to next entry
LOOP NEXT_SF_ENTRY ;;
JMP SHORT SF_RESTORE ;; no match found
FOUND_SF_ENTRY: ;;
MOV NLS_FLAG_1,0 ;; clear all NLS bits
MOV NLS_FLAG_2,0 ;;
MOV BL,[SI]+1 ;; flag id in BX
XOR BH,BH ;;
MOV AL,[SI]+2 ;; mask in AL
OR FLAGS_TO_TEST[BX],AL ;; set the bit
OR EXT_KB_FLAG,SCAN_MATCH ;; set flag indicating scan matched
TEST OPTION_BYTE,EXIT_IF_FOUND ;; Q..exit
JZ SF_RESTORE ;;
POP SI ;;
JMP EXIT ;;
SF_RESTORE: ;;
POP SI ;;
SF_DONE: ;;
INC SI ;; bump past command
INC SI ;;
JMP NEXT_COMMAND ;;
;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Fatal Error routine. Come here when
;; we have a critical error such as an
;; invalid State Logic Command.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
FATAL_ERROR: ;;
JMP SHORT EXIT ;; end the int 9 processing
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Exit point.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
EXIT: ;;
MOV BUSY_FLAG,NO ;;
STC ;; indicate we should end INT 9
POP BX ;; processing
POP AX ;;
POP ES ;;
POP DS ;;
RET ;;
;;
KEYB_STATE_PROCESSOR ENDP ;;
;;
;;
CODE ENDS
END
|