summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/KEYB/KEYBTBBL.ASM
blob: b28f08c8b88c837da1e5f75a449c3462f503942b (plain) (blame)
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
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
        PAGE    ,132
        TITLE   DOS KEYB Command  -  Transient Command Processing

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; DOS - NLS Support - KEYB Command
;; (C) Copyright 1988 Microsoft
;;
;; File Name:  KEYBTBBL.ASM
;; ----------
;;
;; Description:
;; ------------
;;       Build SHARED_DATA_AREA with parameters specified
;;       in KEYBCMD.ASM
;;
;; Documentation Reference:
;; ------------------------
;;       None
;;
;; Procedures Contained in This File:
;; ----------------------------------
;;     TABLE_BUILD: Build the header sections of the SHARED_DATA_AREA
;;     STATE_BUILD: Build the state sections in the table area
;;     FIND_CP_TABLE: Given the language and code page parm, determine the
;;            offset of the code page table in KEYBOARD.SYS
;;
;; Include Files Required:
;; -----------------------
;;       KEYBSHAR.INC
;;       KEYBSYS.INC
;;       KEYBDCL.INC
;;       KEYBI2F.INC
;;
;; External Procedure References:
;; ------------------------------
;;       None
;;
;; Change History:
;; ---------------
;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                       ;;
        PUBLIC TABLE_BUILD             ;;
        PUBLIC FIND_CP_TABLE           ;;
        PUBLIC CPN_INVALID             ;;
        PUBLIC SD_LENGTH               ;;
                                       ;;
CODE    SEGMENT PUBLIC 'CODE'          ;;
                                       ;;
        INCLUDE KEYBEQU.INC            ;;
        INCLUDE KEYBSHAR.INC           ;;
        INCLUDE KEYBSYS.INC            ;;
        INCLUDE KEYBCMD.INC            ;;
        INCLUDE KEYBDCL.INC            ;;
        INCLUDE COMMSUBS.INC           ;;
        INCLUDE KEYBCPSD.INC           ;;
                                       ;;
        ASSUME  CS:CODE,DS:CODE        ;;
                                       ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Module: TABLE_BUILD
;;
;; Description:
;;     Create the table area within the shared data structure. Each
;;     table is made up of a descriptor plus the state sections.
;;     Translate tables are found in the Keyboard definition file and are
;;     copied into the shared data area by means of the STATE_BUILD
;;     routine.
;;
;; Input Registers:
;;     DS - points to our data segment
;;     ES - points to our data segment
;;     BP - points at beginning of CMD_PARM_LIST
;;
;;     SHARED_DATA_STR must be allocated in memory
;;
;;     The following variables must also be passed from KEYB_COMMAND
;;         KEYBSYS_FILE_HANDLE is set to file handle after opening file
;;         CP_TAB_OFFSET is the offset of the CP table in the SHARED_DATA_AREA
;;         STATE_LOGIC_OFFSET is the offset of the state section in the SHARED_DATA_AREA
;;         SYS_CODE_PAGE is the binary representation of the system CP
;;         KEYBCMD_LANG_ENTRY_PTR is a pointer to the lang entry in KEY DEF file
;;         DESIG_CP_BUFFER is the buffer which holds a list of designated CPs
;;         DESIG_CP_OFFSET:WORD is the offset of that list
;;         NUM_DESIG_CP is the number of CPs designated
;;         FILE_BUFFER is the buffer to read in the KEY DEF file
;**********CNS ***************************************
;;         ID_PTR_SIZE is the size of the ID ptr structure
;**********CNS ***************************************
;;         LANG_PTR_SIZE is the size of the lang ptr structure
;;         CP_PTR_SIZE is the size of the CP ptr structure
;;         NUM_CP is the number of CPs in the KEYB DEF file for that lang
;;         SHARED_AREA_PTR segment and offset of the SHARED_DATA_AREA
;;
;;
;; Output Registers:
;;     CX - RETURN_CODE :=  0  - Table build successful
;;                          1  - Table build unsuccessful - ERROR 1
;;                                     (Invalid language parm)
;;                          2  - Table build unsuccessful - ERROR 2
;;                                     (Invalid Code Page parm)
;;                          3  - Table build unsuccessful - ERROR 3
;;                                     (Machine type unavaliable)
;;                          4  - Table build unsuccessful - ERROR 4
;;                                     (Bad or missing keyboard def file)
;;                          5  - Table build unsuccessful - ERROR 5
;;                                     (Memory overflow occurred)
;; Logic:
;;     Calculate Offset difference between TEMP and SHARED_DATA_AREAs
;;     Get LANGUAGE_PARM and CODE_PAGE_PARM from parm list
;;     Call FIND_CP_TABLE := Determine whether CP is valid for given language
;;     IF CP is valid THEN
;;        Store them in the SHARED_DATA_AREA
;;        Prepare to read Keyboard definition file by LSEEKing to the top
;;        READ the header
;;        Store maximum table values for calculation of RES_END
;;        Set DI to point at TABLE_AREA within SHARED_DATA_AREA
;;        FOR the state logic section of the specified language:
;;           IF STATE_LOGIC_PTR is not -1 THEN
;;               LSEEK to state logic section in keyboard definition file
;;               READ the state logic section into the TABLE_AREA
;;               Set the hot keyb scan codes
;;               Set the LOGIC_PTR in the header
;;        FOR the common translate section:
;;           IF Length parameter is not 0 THEN
;;               Build state
;;               Set the COMMON_XLAT_PTR in the header
;;        FOR the specific translate sections:
;;        Establish addressibility to list of designated code pages
;;        FOR each code page
;;           IF CP_ENTRY_PTR is not -1 THEN
;;               Determine offset of CP table in Keyb Def file
;;               IF CP table not avaliable THEN
;;                   Set CPN_INVALID flag
;;               ELSE
;;                   LSEEK to CPn state section in keyboard definition file
;;                   IF this is the invoked code page THEN
;;                       Set ACTIVE_XLAT_PTR in SHARED_DATA_AREA
;;                   Update RESIDENT_END ptr
;;                   Build state
;;        Update RESIDENT_END ptr
;;        End
;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                               ;;
FB                   EQU   FILE_BUFFER         ;;
KB_MASK              EQU   02H                 ;;
                                               ;;
FIRST_XLAT_TAB       DW    0                   ;;
NEXT_SECT_PTR        DW    -1                  ;;
                                               ;;
MAX_COM_SIZE         DW    ?                   ;;
MAX_SPEC_SIZE        DW    ?                   ;;
MAX_LOGIC_SIZE       DW    ?                   ;;
                                               ;;
RESIDENT_END_ACC     DW    0                   ;;
SA_HEADER_SIZE       DW    SIZE SHARED_DATA_STR;;
PARM_LIST_OFFSET     DW    ?                   ;;
;********************CNS*************************
TB_ID_PARM           DW    0
;********************CNS*************************
TB_LANGUAGE_PARM     DW    0                   ;;
TB_CODE_PAGE_PARM    DW    0                   ;;
                                               ;;
CPN_INVALID          DW    0                   ;;
                                               ;;
KEYB_INSTALLED       DW    0                   ;;
SD_AREA_DIFFERENCE   DW    0                   ;;
SD_LENGTH            DW    2000                ;;
                                               ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  Program Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                          ;;
TABLE_BUILD          PROC NEAR            ;;
                                          ;;
        MOV   AX,OFFSET SD_SOURCE_PTR     ;;    Setup the difference
        SUB   AX,OFFSET SD_DEST_PTR       ;;     value used to calculate
        MOV   SD_AREA_DIFFERENCE,AX       ;;      new ptr values for
                                          ;;        SHARED_DATA_AREA
        MOV   AX,[BP].ID_PARM             ;; WGR Get id parameter              ;AN000
        MOV   TB_ID_PARM,AX               ;; WGR                               ;AN000
        MOV   AX,[BP].LANGUAGE_PARM       ;;    Get language parameter
        MOV   TB_LANGUAGE_PARM,AX         ;;
        MOV   BX,[BP].CODE_PAGE_PARM      ;;    Get code page parameter
        MOV   TB_CODE_PAGE_PARM,BX        ;;
                                          ;;  Make sure code page is
        CALL  FIND_CP_TABLE               ;;   valid for the language
        CMP   CX,0                        ;; Test return codes
        JE    TB_CHECK_CONTINUE1          ;; IF code page is found
        JMP   TB_ERROR6                   ;;               for language THEN
                                          ;;
TB_CHECK_CONTINUE1:                       ;;;;;;;;
        MOV   BP,OFFSET SD_SOURCE_PTR           ;;    Put language parm and    ;AN000
        MOV   AX,TB_ID_PARM                     ;; WGR id parm and..           ;AN000
        MOV   ES:[BP].INVOKED_KBD_ID,AX         ;; WGR
        MOV   BX,TB_CODE_PAGE_PARM              ;;
        MOV   ES:[BP].INVOKED_CP_TABLE,BX       ;;;;;; code page parm into the
        MOV   AX,TB_LANGUAGE_PARM                   ;;  SHARED_DATA_AREA
        MOV   WORD PTR ES:[BP].ACTIVE_LANGUAGE,AX   ;;
                                                    ;;
        MOV   BX,KEYBSYS_FILE_HANDLE   ;;;;;;;;;;;;;;; Get handle
        XOR   DX,DX                    ;; LSEEK file pointer
        XOR   CX,CX                    ;;    back to top of file
        MOV   AH,42H                   ;;
        MOV   AL,0                     ;; If no problem with
        INT   21H                      ;;     Keyboard Def file THEN
        JNC   TB_START                 ;;
        JMP   TB_ERROR4                ;;
                                       ;;
TB_START:                              ;; Else
        XOR   DI,DI                    ;; Set number
        LEA   CX,[DI].KH_MAX_LOGIC_SZ+2;;        bytes to read header
        MOV   DX,OFFSET FILE_BUFFER    ;; Move contents into file buffer
        MOV   AH,3FH                   ;;     READ
        PUSH  CS                       ;;
        POP   DS                       ;;
        INT   21H                      ;;        File
        JNC   TB_CONTINUE1             ;;
        JMP   TB_ERROR4                ;;
                                       ;;
TB_CONTINUE1:                          ;;
        CMP   CX,AX                    ;;
        JE    TB_ERROR_CHECK1          ;;
        MOV   CX,4                     ;;
        JMP   TB_CPN_INVALID           ;;
                                       ;;
TB_ERROR_CHECK1:                       ;;
        MOV   CX,FB.KH_MAX_COM_SZ      ;;  Save values for RESIDENT_END
        MOV   MAX_COM_SIZE,CX          ;;           calculation
        MOV   CX,FB.KH_MAX_SPEC_SZ     ;;
        MOV   MAX_SPEC_SIZE,CX         ;;
        MOV   CX,FB.KH_MAX_LOGIC_SZ    ;;
        MOV   MAX_LOGIC_SIZE,CX        ;;
                                       ;;
        LEA   DI,[BP].TABLE_AREA       ;; Point at beginning of table area
                                       ;;           DI ---> TABLE_AREA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;   ** FOR STATE LOGIC SECTION FOR LANG **
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                               ;;
TB_STATE_BEGIN:                                ;;
        MOV   BX,KEYBSYS_FILE_HANDLE           ;; Get handle
        MOV   CX,WORD PTR STATE_LOGIC_OFFSET+2 ;;
        MOV   DX,WORD PTR STATE_LOGIC_OFFSET   ;; Get LSEEK file pointer
                                               ;;
        CMP   DX,-1                    ;;;;;;;;;; If no language table then
        JNE   TB_STATE_CONTINUE1       ;;           jump to code page begin
        JMP   TB_CP_BEGIN              ;;
                                       ;;
TB_STATE_CONTINUE1:                    ;; Else
        MOV   AH,42H                   ;; LSEEK to beginning of state logic sect
        MOV   AL,0                     ;; If no problem with
        INT   21H                      ;;     Keyboard Def file THEN
        JNC   TB_STATE_CONTINUE2       ;;
        JMP   TB_ERROR4                ;;
                                       ;;;;;;;;;;
TB_STATE_CONTINUE2:                            ;;
        MOV   DX,AX                            ;;
        MOV   WORD PTR SB_STATE_OFFSET+2,CX    ;;  Save the offset of the
        MOV   WORD PTR SB_STATE_OFFSET,DX      ;;     states in Keyb Def file
                                               ;;
        SUB   DI,SD_AREA_DIFFERENCE            ;;  Adjust for relocation
        MOV   ES:[BP].LOGIC_PTR,DI     ;;;;;;;;;;  Set because this is state
        ADD   DI,SD_AREA_DIFFERENCE    ;;  Adjust for relocation
                                       ;;
        MOV   CX,4                     ;; Set number bytes to read length and
                                       ;;    special features
        MOV   DX,OFFSET FILE_BUFFER    ;; Set the buffer address
        MOV   AH,3FH                   ;; Read from the Keyb Def file
        INT   21H                      ;;
        JNC   TB_STATE_CONTINUE3       ;;
        JMP   TB_ERROR4                ;;
                                       ;;
TB_STATE_CONTINUE3:                    ;;
        CMP   CX,AX                    ;;
        JE    TB_ERROR_CHECK2          ;;
        MOV   CX,4                     ;;
        JMP   TB_CPN_INVALID           ;;
                                       ;;;;;
TB_ERROR_CHECK2:                          ;;
        MOV   AX,FB.KT_SPECIAL_FEATURES   ;; Save the special features in the
        MOV   ES:[BP].SPECIAL_FEATURES,AX ;;  SHARED_DATA_AREA
                                          ;;
        CMP   HW_TYPE,JR_KB               ;;;;;;;;
        JNE   USE_F1_F2                         ;;
        TEST  AX,JR_HOT_KEY_1_2                 ;;
        JZ    USE_F1_F2                         ;;
        MOV   ES:[BP].HOT_KEY_ON_SCAN,ONE_SCAN  ;;
        MOV   ES:[BP].HOT_KEY_OFF_SCAN,TWO_SCAN ;;
        JMP   HOT_KEY_SET                       ;;
                                                ;;
USE_F1_F2:                                      ;;
        MOV   ES:[BP].HOT_KEY_ON_SCAN,F1_SCAN   ;;
        MOV   ES:[BP].HOT_KEY_OFF_SCAN,F2_SCAN  ;;
                                                ;;
HOT_KEY_SET:                              ;;;;;;;;
        MOV   CX,FB.KT_LOGIC_LEN          ;; Set length of section to read
        CMP   CX,0                        ;;
        JNE   TB_STATE_CONTINUE4          ;;
        MOV   CX,-1                    ;;;;;
        MOV   ES:[BP].LOGIC_PTR,CX     ;;
        JMP   SB_COMM_BEGIN            ;;
                                       ;;
TB_STATE_CONTINUE4:                    ;;
        MOV   ES:[DI],CX               ;; Store length parameter in
        ADD   DI,2                     ;;                  SHARED_DATA_AREA
        MOV   CX,FB.KT_SPECIAL_FEATURES;; Save the special features
        MOV   ES:[DI],CX               ;;
        ADD   DI,2                     ;;
        MOV   CX,FB.KT_LOGIC_LEN       ;; Set length of section to read
        SUB   CX,4                     ;; Adjust for what we have already read
        MOV   DX,DI                    ;; Set the address of SHARED_DATA_AREA
        PUSH  ES                       ;;
        POP   DS                       ;;
        MOV   AH,3FH                   ;; Read logic section from the
        INT   21H                      ;;      Keyb Def file
        PUSH  CS                       ;;
        POP   DS                       ;;
        JNC   TB_STATE_CONTINUE5       ;;
        JMP   TB_ERROR4                ;;
                                       ;;
TB_STATE_CONTINUE5:                    ;;
        CMP   CX,AX                    ;;
        JE    TB_ERROR_CHECK3          ;;
        MOV   CX,4                     ;;
        JMP   TB_CPN_INVALID           ;;
                                       ;;
TB_ERROR_CHECK3:                       ;;
        ADD   DI,CX                    ;; Set DI at new beginning of area
                                       ;;              TABLE_AREA
                                       ;;              STATE_LOGIC
        MOV   CX,RESIDENT_END_ACC      ;;      DI --->
        ADD   CX,SA_HEADER_SIZE        ;;
        ADD   CX,MAX_LOGIC_SIZE        ;;
        MOV   RESIDENT_END_ACC,CX      ;;  Refresh resident end size
                                       ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;   ** FOR COMMON TRANSLATE SECTION FOR LANG **
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                       ;;
SB_COMM_BEGIN:                         ;;
        MOV   CX,SIZE KEYBSYS_XLAT_SECT-1 ;; Set number bytes to read header
        MOV   DX,DI                    ;; Set the SHARED_DATA_AREA address
        PUSH  ES                       ;;
        POP   DS                       ;;
        MOV   AH,3FH                   ;; Read from the Keyb Def file
        INT   21H                      ;;
        PUSH  CS                       ;;
        POP   DS                       ;;
        JNC   TB_STATE_CONTINUE6       ;;
        JMP   TB_ERROR4                ;;
                                       ;;
TB_STATE_CONTINUE6:                    ;;
        MOV   CX,ES:[DI].KX_SECTION_LEN;; Set length of section to read
        CMP   CX,0                     ;;
        JNE   TB_STATE_CONTINUE7       ;;
        JMP   TB_CP_BEGIN              ;;
                                       ;;;;;;;
TB_STATE_CONTINUE7:                         ;;
        MOV   CX,WORD PTR SB_STATE_OFFSET   ;;  Save the offset of the
        ADD   CX,FB.KT_LOGIC_LEN            ;;
        MOV   WORD PTR SB_STATE_OFFSET,CX   ;;  Save the offset of the
        SUB   DI,SD_AREA_DIFFERENCE         ;;  Adjust for relocation
        MOV   ES:[BP].COMMON_XLAT_PTR,DI    ;;
        ADD   DI,SD_AREA_DIFFERENCE         ;;  Adjust for relocation
                                       ;;;;;;;
        CALL  STATE_BUILD              ;;
                                       ;; DI set at new beginning of area
                                       ;;              TABLE_AREA
                                       ;;              STATE_LOGIC
                                       ;;              COMMON_XLAT_SECTION
        MOV   CX,RESIDENT_END_ACC      ;;
        ADD   CX,MAX_COM_SIZE          ;;
        MOV   RESIDENT_END_ACC,CX      ;;  Refresh resident end size
                                       ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;    FOR ALL DESIGNATED OR INVOKED CODE PAGES
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                       ;;
TB_CP_BEGIN:                                           ;; Get the offset to
        MOV   CX,OFFSET DESIG_CP_BUFFER.DESIG_CP_ENTRY ;; the beginning of the
        MOV   DESIG_CP_OFFSET,CX                       ;; table of designated
                                                   ;;;;;; code pages
TB_CPN_BEGIN:                                      ;;
        MOV   AX,WORD PTR ES:[BP].ACTIVE_LANGUAGE  ;; Get the active language
        MOV   CX,NUM_DESIG_CP          ;;;;;;;;;;;;;; Get the number of CPs
        CMP   CX,0                     ;; IF we have done all requested CPs
        JNE   TB_CPN_VALID1            ;;
        JMP   TB_DONE                  ;;   Then done
                                       ;;
TB_CPN_VALID1:                         ;;
        MOV   SI,[DESIG_CP_OFFSET]     ;;
        MOV   BX,[SI]                  ;; Get the CP
        CMP   BX,-1                    ;;
        JNE   TB_CPN_CONTINUE1         ;;
        JMP   TB_CPN_REPEAT            ;;
                                       ;;
TB_CPN_CONTINUE1:                      ;; ELSE
        PUSH  DI                       ;;
        CALL  FIND_CP_TABLE            ;;   Find offset of code page table
        POP   DI                       ;;
                                       ;;
        CMP   CX,0                     ;; Test return codes
        JE    TB_CPN_VALID             ;; IF code page is not found for language
        MOV   CPN_INVALID,CX           ;;       Set flag and go to next CP
        JMP   TB_CPN_REPEAT            ;; Else
                                       ;;
TB_CPN_VALID:                          ;;;;;;
        MOV   BX,KEYBSYS_FILE_HANDLE       ;; Get handle
        MOV   CX,WORD PTR CP_TAB_OFFSET+2  ;; Get offset of the code page
        MOV   DX,WORD PTR CP_TAB_OFFSET    ;;    in the Keyb Def file
                                           ;;
        CMP   DX,-1                    ;;;;;; Test if code page is blank
        JNE   TB_CPN_CONTINUE2         ;;
        JMP   TB_CPN_REPEAT            ;; If it is then go get next CP
                                       ;;
TB_CPN_CONTINUE2:                      ;;
        MOV   AH,42H                   ;; LSEEK to table in Keyb Def file
        MOV   AL,0                     ;; If no problem with
        INT   21H                      ;;     Keyb Def file Then
        JNC   TB_CPN_CONTINUE3         ;;
        JMP   TB_ERROR4                ;;
                                       ;;;;;;;;;;
TB_CPN_CONTINUE3:                              ;;
        MOV   DX,AX                            ;;
        MOV   WORD PTR SB_STATE_OFFSET+2,CX    ;;  Save the offset of the
        MOV   WORD PTR SB_STATE_OFFSET,DX      ;;      states in Keyb Def file
                                               ;;
        MOV   CX,TB_CODE_PAGE_PARM          ;;;;;  If this code page is the
        MOV   SI,[DESIG_CP_OFFSET]          ;;        invoked code page
        CMP   CX,[SI]                       ;;
        JNE   TB_CPN_CONTINUE4              ;;  Then
                                            ;;
        SUB   DI,SD_AREA_DIFFERENCE         ;;  Adjust for relocation
        MOV   ES:[BP].ACTIVE_XLAT_PTR,DI    ;;  Set active xlat section
        ADD   DI,SD_AREA_DIFFERENCE         ;;  Adjust for relocation
                                       ;;;;;;;
TB_CPN_CONTINUE4:                      ;;
        SUB   DI,SD_AREA_DIFFERENCE    ;;  Adjust for relocation
        MOV   ES:[BP].FIRST_XLAT_PTR,DI;;          Set flag
        ADD   DI,SD_AREA_DIFFERENCE    ;;  Adjust for relocation
                                       ;;
TB_CPN_CONTINUE5:                      ;;
        CALL  STATE_BUILD              ;;  Build state
                                       ;;             TABLE_AREA
        CMP   CX,0                     ;;             COMMON_XLAT_SECTION
        JE    TB_CPN_REPEAT            ;;             SPECIFIC_XLAT_SECTION(S)
        JMP   TB_ERROR4                ;;    DI --->
                                       ;;
TB_CPN_REPEAT:                         ;;
        MOV   CX,RESIDENT_END_ACC      ;;
        ADD   CX,MAX_SPEC_SIZE         ;;  Refresh resident end size
        MOV   RESIDENT_END_ACC,CX      ;;
                                       ;;
        MOV   CX,DESIG_CP_OFFSET       ;;
        ADD   CX,2                     ;; Adjust offset to find next code page
        MOV   DESIG_CP_OFFSET,CX       ;;
                                       ;;
        MOV   CX,NUM_DESIG_CP          ;; Adjust the number of code pages left
        DEC   CX                       ;;
        MOV   NUM_DESIG_CP,CX          ;;
                                       ;;
        JMP   TB_CPN_BEGIN             ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                       ;;
TB_DONE:                               ;;
        MOV   CX,RESIDENT_END_ACC      ;;  Set final calculated value
        ADD   CX,BP                    ;;;;;;;;;;;
        SUB   CX,SD_AREA_DIFFERENCE             ;;  Adjust for relocation
        MOV   ES,WORD PTR SHARED_AREA_PTR       ;;    Set segment
        MOV   BP,WORD PTR SHARED_AREA_PTR+2     ;;
        CMP   CX,ES:[BP].RESIDENT_END           ;;
        JNA   TB_DONE_CONTINUE1        ;;;;;;;;;;;
        JMP   TB_ERROR5                ;;
                                       ;;
TB_DONE_CONTINUE1:                     ;;
        CMP   ES:[BP].RESIDENT_END,-1  ;;
        JNE   DONT_REPLACE             ;;
        PUSH  CS                       ;;
        POP   ES                       ;;
        MOV   BP,OFFSET SD_SOURCE_PTR  ;;
        MOV   ES:[BP].RESIDENT_END,CX  ;;  Save resident end
        JMP   CONTINUE_2_END           ;;
                                       ;;
DONT_REPLACE:                          ;;
        PUSH  CS                       ;;
        POP   ES                       ;;
        MOV   BP,OFFSET SD_SOURCE_PTR  ;;
                                       ;;
CONTINUE_2_END:                        ;;
        SUB   CX,OFFSET SD_DEST_PTR    ;;  Calculate # of bytes to copy
        MOV   SD_LENGTH,CX             ;;
                                       ;;
        XOR   CX,CX                    ;;  Set valid completion return code
        MOV   TB_RETURN_CODE,CX        ;;
        RET                            ;;
                                       ;;
TB_CPN_INVALID:                        ;;
        CMP   CX,1                     ;;  Set error 1 return code
        JNE   TB_ERROR2                ;;
        MOV   TB_RETURN_CODE,CX        ;;
        RET                            ;;
                                       ;;
TB_ERROR2:                             ;;
        CMP   CX,2                     ;;  Set error 2 return code
        JNE   TB_ERROR3                ;;
        MOV   TB_RETURN_CODE,CX        ;;
        RET                            ;;
                                       ;;
TB_ERROR3:                             ;;
        CMP   CX,3                     ;;  Set error 3 return code
        JNE   TB_ERROR4                ;;
        MOV   TB_RETURN_CODE,CX        ;;
        RET                            ;;
                                       ;;
TB_ERROR4:                             ;;
        CMP   CX,4                     ;;  Set error 4 return code
        JNE   TB_ERROR5                ;;
        MOV   TB_RETURN_CODE,CX        ;;
        RET                            ;;
                                       ;;
TB_ERROR5:                             ;;
        MOV   CX,5                     ;;  Set error 5 return code
        MOV   TB_RETURN_CODE,CX        ;;
        RET                            ;;
                                       ;;
TB_ERROR6:                             ;;
        MOV   BX,TB_CODE_PAGE_PARM     ;;
        MOV   CX,6                     ;;
        MOV   TB_RETURN_CODE,CX        ;;  Set error 6 return code
        RET                            ;;
                                       ;;
TABLE_BUILD          ENDP              ;;
                                       ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Module: STATE_BUILD
;;
;; Description:
;;     Create the state/xlat section within the specific translate section.
;;
;; Input Registers:
;;     DS - points to our data segment
;;     ES - points to our data segment
;;     SB_STATE_OFFSET - offset to the beginning of the info in Keyb Def SYS
;;     DI - offset of the beginning of the area used to build states
;;
;;     KEYBSYS_FILE_HANDLE - handle of the KEYBOARD.SYS file
;;
;; Output Registers:
;;     DI  - offset of the end of the area used by STATE_BUILD
;;
;;     CX - Return Code := 0  -  State build successful
;;                         4  -  State build unsuccessful
;;                              (Bad or missing Keyboard Def file)
;;
;; Logic:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                               ;;
END_OF_AREA_PTR      DW    0                   ;;
SB_FIRST_STATE       DW    0                   ;;
SB_STATE_LENGTH      DW    0                   ;;
SB_STATE_OFFSET      DD    0                   ;;
STATE_LENGTH         DW    0                   ;;
RESTORE_BP           DW    ?                   ;;
                                               ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  Program Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                       ;;
STATE_BUILD          PROC NEAR         ;;
                                       ;;
        MOV   SI,DI                    ;;  Get the tally pointer
        MOV   END_OF_AREA_PTR,DI       ;;  Save pointer
                                       ;;
        MOV   RESTORE_BP,BP            ;;  Save the base pointer
                                       ;;;;;;;;;
        MOV   BX,KEYBSYS_FILE_HANDLE          ;; Get handle
        MOV   DX,WORD PTR SB_STATE_OFFSET     ;; LSEEK file pointer
        MOV   CX,WORD PTR SB_STATE_OFFSET+2   ;;    back to top of XLAT table
        MOV   AH,42H                          ;;
        MOV   AL,0                     ;;;;;;;;; If no problem with
        INT   21H                      ;;     Keyboard Def file THEN
        JNC   SB_FIRST_HEADER          ;;
        JMP   SB_ERROR4                ;;
                                       ;;
SB_FIRST_HEADER:                       ;;
        XOR   BP,BP                    ;;
        LEA   CX,[BP].KX_FIRST_STATE   ;; Set number of bytes to read header
        MOV   DX,DI                    ;;
        PUSH  ES                       ;;
        POP   DS                       ;;
        MOV   AH,3FH                   ;; read in the header
        INT   21H                      ;;
        PUSH  CS                       ;;
        POP   DS                       ;;
        JNC   SB_HEAD_CONTINUE1        ;;
        JMP   SB_ERROR4                ;;
                                       ;;
SB_HEAD_CONTINUE1:                     ;;
        MOV   DX,NEXT_SECT_PTR         ;;
        CMP   DX,-1                    ;;
        JE    SB_HEAD_CONTINUE2        ;;
        SUB   DX,SD_AREA_DIFFERENCE    ;;  Adjust for relocation
                                       ;;;;;
SB_HEAD_CONTINUE2:                        ;;
        MOV   ES:[DI].XS_NEXT_SECT_PTR,DX ;;
        CMP   DX,-1                       ;;
        JE    SB_HEAD_CONTINUE3        ;;;;;
        ADD   DX,SD_AREA_DIFFERENCE    ;;  Adjust for relocation
                                       ;;
SB_HEAD_CONTINUE3:                     ;;
        ADD   DI,CX                    ;; Update the DI pointer
                                       ;;
SB_NEXT_STATE:                         ;;
        XOR   BP,BP                    ;;  Set number
        LEA   CX,[BP].KX_STATE_ID      ;;     bytes to read state length
        MOV   DX,DI                    ;;  Read the header into the
        MOV   BX,KEYBSYS_FILE_HANDLE   ;;     SHARED_DATA_AREA
        PUSH  ES                       ;;
        POP   DS                       ;;
        MOV   AH,3FH                   ;;
        INT   21H                      ;;
                                       ;;
SB_CONTINUE1:                          ;;
        PUSH  CS                       ;; Reset the data segment
        POP   DS                       ;;
        MOV   CX,ES:[DI].KX_STATE_LEN  ;; If the length of the state section
        MOV   STATE_LENGTH,CX          ;;
        ADD   DI,2                     ;;  is zero then done
        CMP   CX,0                     ;;
        JE    SB_DONE                  ;;
        XOR   BP,BP                    ;;  Set number
        LEA   CX,[BP].KX_FIRST_XLAT-2  ;;     bytes to read state length
        MOV   DX,DI                    ;;  Read the header into the
        MOV   BX,KEYBSYS_FILE_HANDLE   ;;     SHARED_DATA_AREA
        PUSH  ES                       ;;
        POP   DS                       ;;
        MOV   AH,3FH                   ;;
        INT   21H                      ;;
                                       ;;
SB_CONTINUE1A:                         ;;
        PUSH  CS                       ;; Reset the data segment
        POP   DS                       ;;
        SUB   DI,2                     ;;
        MOV   AX,ES:[DI].XS_KBD_TYPE   ;;   Get the keyboard type def
        TEST  AX,HW_TYPE               ;;   Does it match our hardware?
        JNZ   SB_CONTINUE2             ;;
        MOV   DX,ES:[DI].XS_STATE_LEN  ;;     No, then
        LEA   CX,[BP].KX_FIRST_XLAT    ;;
        SUB   DX,CX                    ;;
        XOR   CX,CX                    ;;
        MOV   AH,42H                   ;;          LSEEK past this state
        MOV   AL,01H                   ;;
        INT   21H                      ;;
        JMP   SB_NEXT_STATE            ;;
                                       ;;
SB_CONTINUE2:                          ;;     Yes, then
        MOV   AX,SIZE STATE_STR-1      ;;
        ADD   DI,AX                    ;;  Set PTR and end of header
                                       ;;
SB_XLAT_TAB_BEGIN:                     ;;  Begin getting xlat tables
        MOV   BX,KEYBSYS_FILE_HANDLE   ;;
        LEA   DX,[BP].KX_FIRST_XLAT    ;;  Adjust for what we have already read
        MOV   CX,STATE_LENGTH          ;;
        SUB   CX,DX                    ;;
        MOV   DX,DI                    ;;
        PUSH  ES                       ;;
        POP   DS                       ;;
        MOV   AH,3FH                   ;;  Read in the xlat tables
        INT   21H                      ;;
        PUSH  CS                       ;;
        POP   DS                       ;;
        JNC   SB_CONTINUE4             ;;
        JMP   SB_ERROR4                ;;
                                       ;;
SB_CONTINUE4:                          ;;
        CMP   CX,AX                    ;;
        JE    SB_ERROR_CHECK1          ;;
        JMP   SB_ERROR4                ;;
                                       ;;
SB_ERROR_CHECK1:                       ;;
        ADD   DI,CX                    ;;  Update the end of area ptr
                                       ;;
        MOV   SI,DI                    ;;
        JMP   SB_NEXT_STATE            ;;
                                       ;;
SB_DONE:                               ;;
        MOV   AX,-1                    ;;
        MOV   SI,END_OF_AREA_PTR       ;;
        MOV   NEXT_SECT_PTR,SI         ;;
                                       ;;
        MOV   BP,RESTORE_BP            ;;
        RET                            ;;
                                       ;;
SB_ERROR1:                             ;;
        MOV   CX,1                     ;;
        RET                            ;;
                                       ;;
SB_ERROR2:                             ;;
        MOV   CX,2                     ;;
        RET                            ;;
                                       ;;
SB_ERROR3:                             ;;
        MOV   CX,3                     ;;
        RET                            ;;
                                       ;;
SB_ERROR4:                             ;;
        MOV   CX,4                     ;;
        RET                            ;;
                                       ;;
                                       ;;
STATE_BUILD          ENDP              ;;
                                       ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Module: FIND_CP_TABLE
;;
;; Description:
;;     Determine the offset of the specified code page table in KEYBOARD.SYS
;;
;; Input Registers:
;;     DS - points to our data segment
;;     ES - points to our data segment
;;     AX - ASCII representation of the language parm
;;     BX - binary representation of the code page
;;
;;     KEYBSYS_FILE_HANDLE - handle of the KEYBOARD.SYS file
;;
;; Output Registers:
;;     CP_TAB_OFFSET - offset of the CP table in KEYBOARD.SYS
;;
;;     CX - Return Code := 0  -  State build successful
;;                         2  -  Invalid Code page for language
;;                         4  -  Bad or missing Keyboard Def file
;; Logic:
;;
;;     READ language table
;;     IF error in reading file THEN
;;         Display ERROR message and EXIT
;;     ELSE
;;         Use table to verify language parm
;;         Set pointer values
;;         IF code page was specified
;;             READ language entry
;;             IF error in reading file THEN
;;                  Display ERROR message and EXIT
;;             ELSE
;;                  READ Code page table
;;                  IF error in reading file THEN
;;                      Display ERROR message and EXIT
;;                  ELSE
;;                      Use table to get the offset of the code page parm
;;    RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                               ;;
FIND_CP_PARM          DW    ?                  ;;
                                               ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  Program Code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                       ;;
FIND_CP_TABLE          PROC  NEAR      ;;
                                       ;;
                                       ;;
        MOV   FIND_CP_PARM,BX          ;; Save Code page
                                       ;;;;;;;;;;;;;;
        MOV   BX,KEYBSYS_FILE_HANDLE               ;; Get handle
        MOV   DX,WORD PTR KEYBCMD_LANG_ENTRY_PTR   ;; LSEEK file pointer
        MOV   CX,WORD PTR KEYBCMD_LANG_ENTRY_PTR+2 ;;  to top of language entry
        MOV   AH,42H                               ;;
        MOV   AL,0                     ;;;;;;;;;;;;;; If no problem with
        INT   21H                      ;;     Keyb Def file Then
        JNC   FIND_BEGIN               ;;
        JMP   FIND_CP_ERROR4           ;;
                                       ;;;;;;;;;
FIND_BEGIN:                                   ;;
        MOV   DI,AX                           ;;
        MOV   CX,SIZE KEYBSYS_LANG_ENTRY-1    ;; Set number
                                              ;;        bytes to read header
        MOV   DX,OFFSET FILE_BUFFER    ;;;;;;;;;
        MOV   AH,3FH                   ;; Read language entry in
        INT   21H                      ;;        KEYBOARD.SYS file
        JNC   FIND_VALID4              ;; If no error in opening file then
        JMP   FIND_CP_ERROR4           ;;
                                       ;;
FIND_VALID4:                           ;;
;****************************** CNS *******************************************
        xor   ah,ah
        mov   al,FB.KL_NUM_CP
;****************************** CNS *******************************************
        MOV   NUM_CP,AX                ;; Save the number of code pages
        MUL   CP_PTR_SIZE              ;; Determine # of bytes to read
        MOV   DX,OFFSET FILE_BUFFER    ;; Establish beginning of buffer
        MOV   CX,AX                    ;;
        CMP   CX,FILE_BUFFER_SIZE      ;; Make sure buffer is not to small
        JBE   FIND_VALID5              ;;
        JMP   FIND_CP_ERROR4           ;;
                                       ;;
FIND_VALID5:                           ;;
        MOV   AH,3FH                   ;; Read code page table from
        INT   21H                      ;;              KEYBOARD.SYS file
        JNC   FIND_VALID6              ;; If no error in opening file then
        JMP   FIND_CP_ERROR4           ;;
                                       ;;
FIND_VALID6:                           ;;
        MOV   CX,NUM_CP                ;;    Number of valid codes
        MOV   DI,OFFSET FILE_BUFFER    ;;    Point to correct word in table
                                       ;;
F_SCAN_CP_TABLE:                       ;; FOR code page parm
        MOV   AX,FIND_CP_PARM          ;;    Get parameter
        CMP   [DI].KC_CODE_PAGE,AX     ;;    Valid Code ??
        JE    F_CODE_PAGE_FOUND        ;; If not found AND more entries THEN
        ADD   DI,LANG_PTR_SIZE         ;;    Check next entry
        DEC   CX                       ;;    Decrement count of entries
        JNE   F_SCAN_CP_TABLE          ;; Else
        JMP   FIND_CP_ERROR2           ;;    Display error message
                                       ;;;;;;;;;;
F_CODE_PAGE_FOUND:                             ;;
        MOV   AX,WORD PTR [DI].KC_ENTRY_PTR    ;;
        MOV   WORD PTR CP_TAB_OFFSET,AX        ;;
        MOV   AX,WORD PTR [DI].KC_ENTRY_PTR+2  ;;
        MOV   WORD PTR CP_TAB_OFFSET+2,AX      ;;
                                               ;;
        XOR   CX,CX                    ;;;;;;;;;;
        RET                            ;;
                                       ;;
FIND_CP_ERROR1:                        ;;
        MOV   CX,1                     ;;
        RET                            ;;
                                       ;;
FIND_CP_ERROR2:                        ;;
        MOV   CX,2                     ;;
        RET                            ;;
                                       ;;
FIND_CP_ERROR3:                        ;;
        MOV   CX,3                     ;;
        RET                            ;;
                                       ;;
FIND_CP_ERROR4:                        ;;
        MOV   CX,4                     ;;
        RET                            ;;
                                       ;;
FIND_CP_TABLE         ENDP             ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CODE   ENDS
       END    TABLE_BUILD