summaryrefslogtreecommitdiff
path: root/v4.0/src/BIOS/SYSINIT2.ASM
blob: ff8b8ae36bf77b6480e4d770ee403a68bf732ba8 (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
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
	PAGE	,132			;
;	SCCSID = @(#)sysinit2.asm	1.13 85/10/15
TITLE	BIOS SYSTEM INITIALIZATION
%OUT ...SYSINIT2

;==============================================================================
;REVISION HISTORY:
;AN000 - New for DOS Version 4.00 - J.K.
;AC000 - Changed for DOS Version 4.00 - J.K.
;AN00x - PTM number for DOS Version 4.00 - J.K.
;==============================================================================
;AN001; p132 Multiple character device installation problem.	    6/27/87 J.K.
;AN002; d24  MultiTrack= command added. 			    6/29/87 J.K.
;AN003; p29  Extra space character in parameters passed.
;	     (Modification on ORGANIZE routine for COMMENT= fixed this
;	      problem too)					    6/29/87 J.K.
;AN004; d41  REM command in CONFIG.SYS				    7/7/87  J.K.
;AN005; d184 Set DEVMARK for MEM command			    8/25/87 J.K.
;AN006; p1820 New Message SKL file				   10/20/87 J.K.
;AN007; p1821 Include the COPYRIGH.INC file			   10/22/87 J.K.
;AN008; p2210 IBMDOS returns incorrect DBCS vector table length    11/02/87 J.K.
;AN009; p2667 ccMono_Ptr problem				   11/30/87 J.K.
;AN010; p2792 Device?driver.sys /d:2 command should not work	   12/09/87 J.K.
;AN011; p3120 REM followed by CR, LF causes problem		   01/13/88 J.K.
;AN012; p3111 Take out the order dependency of the INSTALL=	   01/25/88 J.K.
;AN013; d479  New option to disable extended INT 16h function call 02/12/88 J.K.
;AN014; D486 SHARE installation for big media			   02/23/88 J.K.
;AN015; D526 Add /NC parameter when installing SHARE.EXE	   04/28/88 J.K.
;==============================================================================

TRUE	    EQU 0FFFFh
FALSE	    EQU 0
LF	equ	10
CR	equ	13
TAB	equ	 9

IBMVER	   EQU	   TRUE
IBM	   EQU	   IBMVER
STACKSW    EQU	   TRUE 		;Include Switchable Hardware Stacks
IBMJAPVER  EQU	   FALSE		;If TRUE set KANJI true also
MSVER	   EQU	   FALSE
ALTVECT    EQU	   FALSE		;Switch to build ALTVECT version
KANJI	   EQU	   FALSE

	IF	IBMJAPVER
NOEXEC	EQU	TRUE
	ELSE
NOEXEC	EQU	FALSE
	ENDIF

DOSSIZE EQU	0A000H

.xlist
;	INCLUDE dossym.INC
	include smdossym.inc	;J.K. Reduced version of DOSSYM.INC
	INCLUDE devsym.INC
	include ioctl.INC
	include DEVMARK.inc
.list

	IF	NOT IBM
	IF	NOT IBMJAPVER
	EXTRN	RE_INIT:FAR
	ENDIF
	ENDIF

code segment public 'code'
	extrn EC35_Flag: byte
code ends

SYSINITSEG	SEGMENT PUBLIC 'SYSTEM_INIT' BYTE

ASSUME	CS:SYSINITSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING

	EXTRN	BADOPM:BYTE,CRLFM:BYTE,BADCOM:BYTE,BADMEM:BYTE,BADBLOCK:BYTE
	EXTRN	BADSIZ_PRE:BYTE,BADLD_PRE:BYTE
;	 EXTRN	 BADSIZ_POST:BYTE,BADLD_POST:BYTE
	EXTRN	SYSSIZE:BYTE,BADCOUNTRY:BYTE

	EXTRN  dosinfo:dword,entry_point:dword,
	EXTRN  MEMORY_SIZE:WORD,fcbs:byte,keep:byte
	EXTRN  DEFAULT_DRIVE:BYTE,confbot:word,alloclim:word
	EXTRN  BUFFERS:WORD,zero:byte,sepchr:byte
	EXTRN  FILES:BYTE
	EXTRN  count:word,chrptr:word
	EXTRN  bufptr:byte,memlo:word,prmblk:byte,memhi:word
	EXTRN  ldoff:word,area:word,PACKET:BYTE,UNITCOUNT:BYTE,
	EXTRN  BREAK_ADDR:DWORD,BPB_ADDR:DWORD,drivenumber:byte
	extrn  COM_Level:byte, CMMT:byte, CMMT1:byte, CMMT2:byte
	extrn  Cmd_Indicator:byte
	extrn  DoNotShowNum:byte
	extrn  MultDeviceFlag:byte
	extrn  DevMark_Addr:word			;AN005;
	extrn  SetDevMarkFlag:byte			;AN005;
	extrn  Org_Count:word				;AN012;

	EXTRN  Stall:near
	EXTRN  Error_Line:near

	PUBLIC Int24,Open_Dev,Organize,Mem_Err,Newline,CallDev,Badload
	PUBLIC PrnDev,AuxDev,Config,Commnd,Condev,GetNum,BadFil,PrnErr
	PUBLIC Round,Delim,Print,Set_Break
	PUBLIC SetParms, ParseLine, DiddleBack
	PUBLIC Skip_delim,SetDOSCountryInfo,Set_Country_Path,Move_Asciiz
	PUBLIC Cntry_Drv,Cntry_Root,Cntry_Path
	PUBLIC Delim
	public PathString				;AN014;
	public LShare					;AN014;

;
; The following set of routines is used to parse the DRIVPARM = command in
; the CONFIG.SYS file to change the default drive parameters.
;
SetParms:
	push	ds
	push	ax
	push	bx
	push	cx
	push	dx
	push	cs
	pop	ds
	ASSUME DS:SYSINITSEG
	xor	bx,bx
	mov	bl,byte ptr drive
	inc	bl		    ; get it correct for IOCTL call (1=A,2=B...)
	mov	dx,offset DeviceParameters
	mov	ah, IOCTL
	mov	al, GENERIC_IOCTL
	mov	ch, RAWIO
	mov	cl, SET_DEVICE_PARAMETERS
	int	21H
	test	word ptr Switches, flagec35
	jz	Not_EC35

	mov	cl, byte ptr drive	; which drive was this for?
	mov	ax, Code		; get Code segment
	mov	ds, ax			; set code segment
	assume ds:code
	mov	al, 1			; assume drive 0
	shl	al, cl			; set proper bit depending on drive
	or	ds:EC35_Flag, al	; set the bit in the permanent flags

Not_EC35:
	pop	dx			; fix up all the registers
	pop	cx
	pop	bx
	pop	ax
	pop	ds
	assume ds:nothing
	ret

;
; Replace default values for further DRIVPARM commands
;
DiddleBack:
	push	ds
	push	cs
	pop	ds
	assume	ds:sysinitseg
	mov	word ptr DeviceParameters.DP_Cylinders,80
	mov	byte ptr DeviceParameters.DP_DeviceType, DEV_3INCH720KB
	mov	word ptr DeviceParameters.DP_DeviceAttributes,0
	mov	word ptr switches,0	    ; zero all switches
	pop	ds
	assume	ds:nothing
	ret

;
; Entry point is ParseLine. AL contains the first character in command line.
;
ParseLine:			    ; don't get character first time
	push	ds
	push	cs
	pop	ds
	ASSUME	DS:SYSINITSEG
NextSwtch:
	cmp	al,CR			; carriage return?
	jz	done_line
	cmp	al,LF			; linefeed?
	jz	put_back		; put it back and done
; Anything less or equal to a space is ignored.
	cmp	al,' '                  ; space?
	jbe	get_next		; skip over space
	cmp	al,'/'
	jz	getparm
	stc			    ; mark error invalid-character-in-input
	jmp	short exitpl

getparm:
	call	Check_Switch
	mov	word ptr Switches,BX	     ; save switches read so far
	jc	swterr
get_next:
	invoke	getchr
	jc	done_line
	jmp	NextSwtch
swterr:
	jmp	exitpl		    ; exit if error

done_line:
	test	word ptr Switches,flagdrive  ; see if drive specified
	jnz	okay
	stc			    ; mark error no-drive-specified
	jmp	short exitpl

okay:
	mov	ax,word ptr switches
	and	ax,0003H	    ; get flag bits for changeline and non-rem
	mov	word ptr DeviceParameters.DP_DeviceAttributes,ax
	mov	word ptr DeviceParameters.DP_TrackTableEntries, 0
	clc			    ; everything is fine
	call	SetDeviceParameters
exitpl:
	pop	ds
	ret

put_back:
	inc	count			; one more char to scan
	dec	chrptr			; back up over linefeed
	jmp	short done_line
;
; Processes a switch in the input. It ensures that the switch is valid, and
; gets the number, if any required, following the switch. The switch and the
; number *must* be separated by a colon. Carry is set if there is any kind of
; error.
;
Check_Switch:
	invoke	getchr
	jc	err_check
	and	al,0DFH 	    ; convert it to upper case
	cmp	al,'A'
	jb	err_check
	cmp	al,'Z'
	ja	err_check
	push	es
	push	cs
	pop	es
	mov	cl,byte ptr switchlist	     ; get number of valid switches
	mov	ch,0
	mov	di,1+offset switchlist	; point to string of valid switches
	repne	scasb
	pop	es
	jnz	err_check
	mov	ax,1
	shl	ax,cl		; set bit to indicate switch
	mov	bx,word ptr switches	 ; get switches so far
	or	bx,ax		; save this with other switches
	mov	cx,ax
	test	ax, switchnum	; test against switches that require number to follow
	jz	done_swtch
	invoke	getchr
	jc	err_Swtch
	cmp	al,':'
	jnz	err_swtch
	invoke	getchr
	push	bx			; preserve switches
	mov	byte ptr cs:sepchr,' '          ; allow space separators
	call	GetNum
	mov	byte ptr cs:sepchr,0
	pop	bx			; restore switches
; Because GetNum does not consider carriage-return or line-feed as OK, we do
; not check for carry set here. If there is an error, it will be detected
; further on (hopefully).
	call	Process_Num

done_swtch:
	clc
	ret

err_swtch:
	xor	bx,cx			; remove this switch from the records
err_check:
	stc
	ret

;
; This routine takes the switch just input, and the number following (if any),
; and sets the value in the appropriate variable. If the number input is zero
; then it does nothing - it assumes the default value that is present in the
; variable at the beginning. Zero is OK for form factor and drive, however.
;
Process_Num:
	test	word ptr Switches,cx	 ; if this switch has been done before,
	jnz	done_ret	    ; ignore this one.
	test	cx,flagdrive
	jz	try_f
	mov	byte ptr drive,al
	jmp	short done_ret

try_f:
	test	cx,flagff
	jz	try_t
; Ensure that we do not get bogus form factors that are not supported
	;cmp	al,Max_Dev_Type
	;ja	done_ret
	mov	byte ptr DeviceParameters.DP_DeviceType,al
	jmp	short done_ret

try_t:
	or	ax,ax
	jz	done_ret	    ; if number entered was 0, assume default value
	test	cx,flagcyln
	jz	try_s
	mov	word ptr DeviceParameters.DP_Cylinders,ax
	jmp	short done_ret

try_s:
	test	cx,flagseclim
	jz	try_h
	mov	word ptr slim,ax
	jmp	short done_ret
;
; Must be for number of heads
try_h:
	mov	word ptr hlim,ax

done_ret:
	clc
	ret

;
; SetDeviceParameters sets up the recommended BPB in each BDS in the
; system based on the form factor. It is assumed that the BPBs for the
; various form factors are present in the BPBTable. For hard files,
; the Recommended BPB is the same as the BPB on the drive.
; No attempt is made to preserve registers since we are going to jump to
; SYSINIT straight after this routine.
;
SetDeviceParameters:
	push	es
	push	cs
	pop	es
ASSUME ES:SYSINITSEG
	xor	bx,bx
	mov	bl,byte ptr DeviceParameters.DP_DeviceType
	cmp	bl,DEV_5INCH
	jnz	Got_80
	mov	cx,40			; 48tpi has 40 cylinders
	mov	word ptr DeviceParameters.DP_Cylinders,cx
Got_80:
	shl	bx,1			; get index into BPB table
	mov	si,offset BPBTable
	mov	si,word ptr [si+bx]	; get address of BPB
Set_RecBPB:
	mov	di,offset DeviceParameters.DP_BPB	 ; es:di -> BPB
	mov	cx,size a_BPB
	cld
	repe	movsb
	pop	es
ASSUME ES:NOTHING
	test	word ptr switches,flagseclim
	jz	see_heads
	mov	ax,word ptr slim
	mov	word ptr DeviceParameters.DP_BPB.BPB_SectorsPerTrack,ax
see_heads:
	test	word ptr switches,flagheads
	jz	Set_All_Done
	mov	ax,word ptr hlim
	mov	word ptr DeviceParameters.DP_BPB.BPB_Heads,ax
;
; We need to set the media byte and the total number of sectors to reflect the
; number of heads. We do this by multiplying the number of heads by the number
; of 'sectors per head'. This is not a fool-proof scheme!!
;
	mov	cx,ax			; cx has number of heads
	dec	cl			; get it 0-based
	mov	ax,DeviceParameters.DP_BPB.BPB_TotalSectors	; this is OK for two heads
	sar	ax,1			; ax contains # of sectors/head
	sal	ax,cl
	jc	Set_All_Done		; We have too many sectors - overflow!!
	mov	DeviceParameters.DP_BPB.BPB_TotalSectors,ax
; Set up correct Media Descriptor Byte
	cmp	cl,1
	mov	bl,0F0H
	mov	al,2			; AL contains sectors/cluster
	ja	Got_Correct_Mediad
	mov	bl,byte ptr DeviceParameters.DP_BPB.BPB_MediaDescriptor
	je	Got_Correct_Mediad
; We have one head - OK for 48tpi medium
	mov	al,1			; AL contains sectors/cluster
	mov	ch,DeviceParameters.DP_DeviceType
	cmp	ch,DEV_5INCH
	jz	Dec_Mediad
	mov	bl,0F0H
	jmp	short Got_Correct_Mediad
Dec_Mediad:
	dec	bl			; adjust for one head
Got_Correct_Mediad:
	mov	byte ptr DeviceParameters.DP_BPB.BPB_MediaDescriptor,bl
	mov	byte ptr DeviceParameters.DP_BPB.BPB_SectorsPerCluster,al
	clc
Set_All_Done:
	RET

ASSUME DS:NOTHING, ES:NOTHING

NOCHAR1: STC
	 return

ORGANIZE:
	MOV	CX,[COUNT]
	JCXZ	NOCHAR1
	CALL	MAPCASE
	XOR	SI,SI
	MOV	DI,SI
	xor	ax,ax
	mov	COM_Level, 0

;ORG1:	 CALL	 GET			 ;SKIP LEADING CONTROL CHARACTERS
;	 CMP	 AL,' '
;	 JB	 ORG1
Org1:
	call	Skip_Comment		;AN000;
	jz	End_Commd_Line		;AN000; found a comment string and skipped.
	call	Get2			;AN000; Not a comment string. Then get a char.
	cmp	al, LF			;AN000;
	je	End_Commd_Line		;AN000; starts with a blank line.
	cmp	al, ' '                 ;AN000;
	jbe	Org1			;AN000; skip leading control characters
	jmp	Findit			;AN000;
End_Commd_Line: 			;AN000;
	stosb				;AN000; store line feed char in buffer for the LineCount.
	mov	COM_Level, 0		;AN000; reset the command level.
	jmp	Org1			;AN000;
Findit: 				;AN000;
	PUSH	CX
	PUSH	SI
	PUSH	DI
	MOV	BP,SI
	DEC	BP
	MOV	SI,OFFSET COMTAB	;Prepare to search command table
	MOV	CH,0
FINDCOM:
	MOV	DI,BP
	MOV	CL,[SI]
	INC	SI
	JCXZ	NOCOM
	REPE	CMPSB
	LAHF
	ADD	SI,CX			;Bump to next position without affecting flags
	SAHF
	LODSB				;Get indicator letter
	JNZ	FINDCOM
	cmp	byte ptr es:[di], CR	;AN011;The next char might be CR,LF
	je	GotCom0 		;AN011; such as in "REM",CR,LF case.
	cmp	byte ptr es:[di], LF	;AN011;
	je	GotCom0 		;AN011;
	push	ax			;AN010;
	mov	al, byte ptr es:[di]	;AN010;Now the next char. should be a delim.
	call	delim			;AN010;
	pop	ax			;AN010;
	jnz	findcom 		;AN010;
GotCom0:
	POP	DI
	POP	SI
	POP	CX
	JMP	SHORT GOTCOM

NOCOM:
	POP	DI
	POP	SI
	POP	CX
	MOV	AL,'Z'
	stosb				;AN000; save indicator char.
Skip_Line:				;AN000;
	call	Get2			;AN000;
	cmp	al, LF			;AN000; skip this bad command line
	jne	Skip_Line		;AN000;
	jmp	End_Commd_Line		;AN000; handle next command line

GOTCOM: STOSB				;SAVE INDICATOR CHAR IN BUFFER
	mov	Cmd_Indicator, al	;AN000; save it for the future use.

ORG2:	CALL	GET2			;SKIP the commad name UNTIL DELIMITER
	cmp	al, LF			;AN011;
	je	Org21			;AN011;
	cmp	al, CR			;AN011;
	je	Org21			;AN011;
	CALL	DELIM			;
	JNZ	ORG2
	jmp	short	Org3		;AN011;
Org21:					;AN011;if CR or LF then
	dec	si			;AN011; undo SI, CX register
	inc	cx			;AN011;  and continue

;ORG4:	 CALL	 GET2
;	 call	 Delim			 ;J.K. 5/30/86. To permit "device=filename/p..." stuff.
;	 jz	 ORG_EXT		 ;J.K. 5/30/86
;Org4_Cont:
;	 STOSB
;	 CMP	 AL,' '
;	 JA	 ORG4
;	 CMP	 AL,10
;	 JZ	 ORG1
;
;	 MOV	 BYTE PTR ES:[DI-1],0

Org3:
	cmp	Cmd_Indicator, 'Y'      ;AN000; Comment= command?
	je	Get_Cmt_Token		;AN000;
	cmp	Cmd_Indicator, 'I'      ;AN000; Install= command?
	je	Org_file		;AN000;
	cmp	Cmd_Indicator, 'D'      ;AN000; Device= command?
	je	Org_file		;AN000;
	cmp	Cmd_Indicator, 'J'      ;AN000; IFS= command?
	je	Org_file		;AN000;
	cmp	Cmd_Indicator, 'S'      ;AN000; Shell= is a special one!!!
	je	Org_file		;AN000;
	cmp	Cmd_Indicator, '1'      ;AN013; SWITCHES= command?
	je	Org_Switch		;AN013;
	jmp	Org4			;AN000;
Org_Switch:
	call	Skip_Comment		;AN013;
	jz	End_Commd_Line_Brdg	;AN013;
	call	Get2			;AN013;
	call	Org_Delim		;AN013;
	jz	Org_Switch		;AN013;
	stosb				;AN013;
	jmp	Org5			;AN013;
Org_file:				;AN000; Get the filename and put 0 at end,
	call	Skip_Comment		;AN000;
	jz	Org_Put_Zero		;AN000;
	call	Get2			;AN000; Not a comment
	call	Delim			;AN000;
	jz	Org_file		;AN000; Skip the possible delimeters
	stosb				;AN000; copy the first non delim char found in buffer
Org_Copy_File:				;AN000;
	call	Skip_Comment		;AN000; comment char in the filename?
	jz	Org_Put_Zero		;AN000; then stop copying filename at that point
	call	Get2			;AN000;
	cmp	al, '/'                 ;AN000; a switch char? (device=filename/xxx)
	je	End_File_slash		;AN000; this will be the special case.
	stosb				;AN000; save the char. in buffer
	call	Delim			;AN000;
	jz	End_Copy_File		;AN000;
	cmp	al, ' '                 ;AN000;
	ja	Org_Copy_File		;AN000; keep copying
	jmp	End_Copy_File		;AN000; otherwise, assume end of the filename.
Get_Cmt_token:				;AN000; get the token. Just max. 2 char.
	call	Get2			;AN000;
	cmp	al, ' '                 ;AN000; skip white spaces or "=" char.
	je	Get_Cmt_Token		;AN000; (we are allowing the other special
	cmp	al, TAB 		;AN000;  charaters can used for comment id.
	je	Get_Cmt_Token		;AN000;  character.)
	cmp	al, '='                 ;AN000; = is special in this case.
	je	Get_Cmt_Token		;AN000;
	cmp	al, CR			;AN000;
	je	Get_Cmt_End		;AN000; cannot accept the carridge return
	cmp	al, LF			;AN000;
	je	Get_Cmt_End		;AN000;
	mov	CMMT1, al		;AN000; store it
	mov	CMMT, 1 		;AN000; 1 char. so far.
	call	Get2			;AN000;
	cmp	al, ' '                 ;AN000;
	je	Get_Cmt_End		;AN000;
	cmp	al, TAB 		;AN000;
	je	Get_Cmt_End		;AN000;
	cmp	al, CR			;AN000;
	je	Get_Cmt_End		;AN000;
	cmp	al, LF			;AN000;
	je	End_Commd_Line_Brdg	;AN000;
	mov	CMMT2, al		;AN000;
	inc	CMMT			;AN000;
Get_Cmt_End:				;AN000;
	call	Get2			;AN000;
	cmp	al, LF			;AN000;
	jne	Get_Cmt_End		;AN000; skip it.
End_Commd_Line_Brdg: jmp End_Commd_Line ;AN000; else jmp to End_Commd_Line

Org_Put_Zero:				;AN000; Make the filename in front of
	mov	byte ptr es:[di], 0	;AN000;  the comment string to be an asciiz.
	inc	di			;AN000;
	jmp	End_Commd_Line		;AN000;  (Maybe null if device=/*)
End_file_slash: 			;AN000; AL = "/" option char.
	mov	byte ptr es:[di],0	;AN000; make a filename an asciiz
	inc	di			;AN000; and
	stosb				;AN000; store "/" after that.
	jmp	Org5			;AN000; continue with the rest of the line

End_Copy_File:				;AN000;
	mov	byte ptr es:[di-1], 0	;AN000; make it an asciiz and handle the next char.
	cmp	al, LF			;AN000;
	je	End_Commd_Line_brdg	;AN000;
	jmp	Org5			;AN000;

Org4:					;AN000; Org4 skips all delimiters after the command name except for '/'
	call	Skip_Comment		;AN000;
	jz	End_Commd_Line_brdg	;AN000;
	call	Get2			;AN000;
	call	Org_Delim		;AN000; skip delimiters EXCEPT '/' (mrw 4/88)
	jz	Org4			;AN000;
	jmp	Org51			;AN000;
Org5:					;AN000; rest of the line
	call	Skip_Comment		;AN000; Comment?
	jz	End_Commd_Line_brdg	;AN000;
	call	Get2			;AN000; Not a comment.
Org51:					;AN000;
	stosb				;AN000; copy the character
	cmp	al, '"'                 ;AN000; a quote ?
	je	At_Quote		;AN000;
	cmp	al, ' '                 ;AN000;
	ja	Org5			;AN000;
	cmp	al, LF			;AN000; line feed?
	je	Org1_brdg		;AN000; handles the next command line.
	jmp	Org5			;AN000; handles next char in this line.
Org1_brdg: jmp	 Org1			;AN000;
At_Quote:				;AN000;
	cmp	COM_Level, 0		;AN000;
	je	Up_Level		;AN000;
	mov	COM_Level, 0		;AN000; reset it.
	jmp	Org5			;AN000;
Up_Level:				;AN000;
	inc	COM_level		;AN000; set it.
	jmp	Org5			;AN000;


;ORG5:	 CALL	 GET2
;	 STOSB
;	 CMP	 AL,10
;	 JNZ	 ORG5
;	 JMP	 ORG1
;
;ORG_EXT:
;	 cmp	 al,' '                  ;space?
;	 je	 Org4_Cont		 ;then do not make an exception. Go back.
;	 cmp	 al,9			 ;Tab?
;	 je	 Org4_Cont
;	 mov	 byte ptr es:[di], 0	 ;put 0 at the current DI to make it an ASCIIZ
;	 inc	 DI			 ;
;	 stosb				 ;and copy the delimeter char.
;	 jmp	 short ORG5		 ;and continue as usual.


GET2:
	JCXZ	NOGET
	MOV	AL,ES:[SI]
	INC	SI
	DEC	CX
	return

;GET:	 JCXZ	 NOGET
;	 MOV	 AL,ES:[SI]
;	 INC	 SI
;	 DEC	 CX
;	 CALL	 Org_DELIM
;	 JZ	 GET
;	 return

Skip_Comment:
;J.K.Skip the commented string until LF, if current es:si-> a comment string.
;J.K.In) ES:SI-> sting
;J.K.	 CX -> length.
;J.K.Out) Zero flag not set if not found a comment string.
;J.K.	  Zero flag set if found a comment string and skipped it. AL will contain
;J.K.	  the line feed charater at this moment when return.
;J.K.	  AX register destroyed.
;J.K.	  If found, SI, CX register adjusted accordingly.

	jcxz	NoGet		;AN000; Get out of the Organize routine.
	cmp	COM_Level, 0	;AN000; only check it if parameter level is 0.
	jne	No_Commt	;AN000;  (Not inside quotations)

	cmp	CMMT, 1 	;AN000;
	jb	No_Commt	;AN000;
	mov	al, es:[si]	;AN000;
	cmp	CMMT1, al	;AN000;
	jne	No_Commt	;AN000;
	cmp	CMMT, 2 	;AN000;
	jne	Skip_Cmmt	;AN000;
	mov	al, es:[si+1]	;AN000;
	cmp	CMMT2, al	;AN000;
	jne	No_Commt	;AN000;
Skip_Cmmt:			;AN000;
	jcxz	NoGet		;AN000; get out of Organize routine.
	mov	al, es:[si]	;AN000;
	inc	si		;AN000;
	dec	cx		;AN000;
	cmp	al, LF		;AN000; line feed?
	jne	Skip_Cmmt	;AN000;
No_Commt:			;AN000;
	ret			;AN000;


DELIM:
	CMP	AL,'/'          ;J.K. 5/30/86. IBM will assume "/" as an delimeter.
	retz
	cmp	al, 0		;J.K. 5/23/86 Special case for sysinit!!!
	retz
Org_Delim:			;AN000;  Used by Organize routine except for getting
	CMP	AL,' '          ;the filename.
	retz
	CMP	AL,9
	retz
	CMP	AL,'='
	retz
	CMP	AL,','
	retz
	CMP	AL,';'
	return


NOGET:	POP	CX
	MOV	COUNT,DI
	mov	Org_Count, DI	;AN012;
	XOR	SI,SI
	MOV	CHRPTR,SI
	return

;Get3:	 jcxz	 NOGET		 ;J.K.do not consider '/',',' as a delim.
;	 mov	 al, es:[si]
;	 inc	 si
;	 dec	 cx
;	 call	 DELIM
;	 jnz	 Get3_ret
;	 cmp	 al,'/'
;	 je	 Get3_ret
;	 cmp	 al,','
;	 jne	 Get3
;Get3_ret:
;	 ret



;
;  NEWLINE RETURNS WITH FIRST CHARACTER OF NEXT LINE
;
NEWLINE:invoke	GETCHR			;SKIP NON-CONTROL CHARACTERS
	retc
	CMP	AL,LF			;LOOK FOR LINE FEED
	JNZ	NEWLINE
	invoke	GETCHR
	return

MAPCASE:
	PUSH	CX
	PUSH	SI
	PUSH	DS
	PUSH	ES
	POP	DS
	XOR	SI,SI
CONVLOOP:
	LODSB

	IF	KANJI
	CALL	TESTKANJ
	JZ	NORMCONV
	INC	SI			;Skip next char
	DEC	CX
	JCXZ	CONVDONE		;Just ignore 1/2 kanji error
;Fall through, know AL is not in 'a'-'z' range
NORMCONV:
	ENDIF

	CMP	AL,'a'
	JB	NOCONV
	CMP	AL,'z'
	JA	NOCONV
	SUB	AL,20H
	MOV	[SI-1],AL
NOCONV:
	LOOP	CONVLOOP
CONVDONE:
	POP	DS
	POP	SI
	POP	CX
	return

	IF	KANJI
TESTKANJ:
	CMP	AL,81H
	JB	NOTLEAD
	CMP	AL,9FH
	JBE	ISLEAD
	CMP	AL,0E0H
	JB	NOTLEAD
	CMP	AL,0FCH
	JBE	ISLEAD
NOTLEAD:
	PUSH	AX
	XOR	AX,AX			;Set zero
	POP	AX
	return

ISLEAD:
	PUSH	AX
	XOR	AX,AX			;Set zero
	INC	AX			;Reset zero
	POP	AX
	return
	ENDIF

ASSUME DS:NOTHING

Yes_Break_Failed:			;device driver Init failed and aborted.
	stc
	pop	ax
	return

SET_BREAK:
;J.K. 8/14/86  For DOS 3.3, this routine is modified to take care of the
;Device driver's initialization error and abort.
;If [break_addr+2] == [memhi] && [break_addr] = 0 then assume
;that the device driver's initialization has an error and wanted to
;abort the device driver.  In this case, this routine will set carry
;and return to the caller.
;J.K. 6/26/87 If MultDeviceFlag <> 0, then do not perform the check.
;This is to allow the multiple character device driver which uses
;the same ending address segment with the offset value 0 for each
;of the drives.

	PUSH	AX
	MOV	AX,WORD PTR [BREAK_ADDR+2]  ;REMOVE THE INIT CODE
	cmp	MultDeviceFlag, 0	    ;AN001;
	jne	Set_Break_Continue	    ;AN001;Do not check it.
	cmp	ax, [MEMHI]
	jne	Set_Break_Continue	    ;if not same, then O.K.

	cmp	word ptr [BREAK_ADDR],0
	je	Yes_Break_failed	    ;[Break_addr+2]=[MEMHI] & [Break_addr]=0

Set_Break_Continue:
	MOV	[MEMHI],AX
	MOV	AX,WORD PTR [BREAK_ADDR]
	MOV	[MEMLO],AX
	POP	AX			    ; NOTE FALL THROUGH
	or	[SetDevMarkFlag], SETBRKDONE	;AN005; Signal the successful Set_break

;
; Round the values in MEMLO and MEMHI to paragraph boundary.
; Perform bounds check.
;
ROUND:
	PUSH	AX
	MOV	AX,[MEMLO]

	invoke	ParaRound		; para round up

	ADD	[MEMHI],AX
	MOV	[MEMLO],0
	mov	ax,memhi		; ax = new memhi
	CMP	AX,[ALLOCLIM]		; if new memhi >= alloclim, error
	JAE	MEM_ERR
	test	cs:[SetDevMarkFlag], FOR_DEVMARK	    ;AN005;
	jz	Skip_Set_DEVMARKSIZE			;AN005;
	push	es					;AN005;
	push	si					;AN005;
	mov	si, cs:[DevMark_Addr]			;AN005;
	mov	es, si					;AN005;
	sub	ax, si					;AN005;
	dec	ax					;AN005;
	mov	es:[DEVMARK_SIZE], ax			;AN005; Paragraph
	and	cs:[SetDevMarkFlag], NOT_FOR_DEVMARK	    ;AN005;
	pop	si					;AN005;
	pop	es					;AN005;
Skip_Set_DEVMARKSIZE:					;AN005;
	POP	AX
	clc				;clear carry
	return

MEM_ERR:
	MOV	DX,OFFSET BADMEM
	PUSH	CS
	POP	DS
	CALL	PRINT
	JMP	STALL

CALLDEV:MOV	DS,WORD PTR CS:[ENTRY_POINT+2]
	ADD	BX,WORD PTR CS:[ENTRY_POINT]	;Do a little relocation
	MOV	AX,DS:[BX]
	PUSH	WORD PTR CS:[ENTRY_POINT]
	MOV	WORD PTR CS:[ENTRY_POINT],AX
	MOV	BX,OFFSET PACKET
	CALL	[ENTRY_POINT]
	POP	WORD PTR CS:[ENTRY_POINT]
	return

BADNUM:
	MOV	sepchr,0
	XOR	AX,AX		; Set Zero flag, and AX = 0
	pop	bx		; J.K.
	stc			; AND carry set
	return

ToDigit:
	SUB	AL,'0'
	JB	NotDig
	CMP	AL,9
	JA	NotDig
	CLC
	return
NotDig: STC
	return

; GetNum parses a decimal number.
; Returns it in AX, sets zero flag if AX = 0 (MAY BE considered an
; error), if number is BAD carry is set, zero is set, AX=0.
GETNUM: push	bx			; J.K.
	XOR	BX,BX			; running count is zero
B2:	CALL	ToDigit 		; do we have a digit
	JC	BadNum			; no, bomb
	XCHG	AX,BX			; put total in AX
	PUSH	BX			; save digit
	MOV	BX,10			; base of arithmetic
	MUL	BX			; shift by one decimal di...
	POP	BX			; get back digit
	ADD	AL,BL			; get total
	ADC	AH,0			; make that 16 bits
	JC	BADNUM			; too big a number
	XCHG	AX,BX			; stash total

	invoke	GETCHR			;GET NEXT DIGIT
	JC	B1			; no more characters
	cmp	al, ' '                 ;J.K. 5/23/86 space?
	jz	B15			;J.K. 5/23/86 then end of digits
	cmp	al, ','                 ;J.K. 5/23/86 ',' is a seperator!!!
	jz	B15			;J.K. 5/23/86 then end of digits.
	cmp	al, TAB 		;J.K. 5/23/86 TAB
	jz	B15			;J.K.
	CMP	AL,SepChr		; allow 0 or special separators
	JZ	b15
	cmp	al,SWTCHR		; See if another switch follows
	JZ	b15
	cmp	al,LF			; Line-feed?
	jz	b15
	cmp	al,CR			; Carriage return?
	jz	b15
	OR	AL,AL			; end of line separator?
	JNZ	B2			; no, try as a valid char...
b15:	INC	COUNT			; one more character to s...
	DEC	CHRPTR			; back up over separator
B1:	MOV	AX,BX			; get proper count
	OR	AX,AX			; Clears carry, sets Zero accordingly
	pop	bx
	return

SKIP_DELIM	proc	near		;J.K.
;Skip the delimeters pointed by CHRPTR.  AL will contain the first non delimeter
;character encountered and CHRPTR will point to the next character.
;This rouitne will assume the second "," found as a non delimiter character. So
;in case if the string is " , , ", this routine will stop at the second ",". At
;this time, Zero flag is set.
;If COUNT is exhausted, then carry will be set.
Skip_delim_char:
	call	getchr
	jc	Skip_delim_exit
	cmp	al, ','                 ;the first comma?
	je	Skip_delim_next
	call	delim			;check the charater in AL.
	jz	Skip_delim_char
	jmp	short Skip_delim_exit	;found a non delim char
Skip_delim_next:
	call	getchr
	jc	Skip_delim_exit
	cmp	al, ','                 ;the second comma?
	je	Skip_delim_exit 	;done
	call	delim
	jz	Skip_delim_next
Skip_delim_exit:
	return
SKIP_DELIM	endp

;J.K. 5/26/86 *****************************************************************
SetDOSCountryInfo	proc	near
;Input: ES:DI -> pointer to DOS_COUNTRY_CDPG_INFO
;	DS:0  -> buffer.
;	SI = 0
;	AX = country id
;	DX = code page id. (If 0, then use ccSysCodePage as a default.)
;	BX = file handle
;	This routine can handle maxium 72 COUNTRY_DATA entries.
;Output: DOS_country_cdpg_info set.
;	 Carry set if any file read failure or wrong information in the file.
;	 Carry set and CX = -1 if cannot find the matching COUNTRY_id, CODEPAGE
;	 _id in the file.

	push	di
	push	ax
	push	dx

	xor	cx,cx
	xor	dx,dx
	mov	ax, 512 		;read 512 bytes
	call	ReadInControlBuffer	;Read the file header
	jc	SetDOSData_fail
	push	es
	push	si
	push	cs
	pop	es
	mov	di, offset COUNTRY_FILE_SIGNATURE
	mov	cx, 8			;length of the signature
	repz	cmpsb
	pop	si
	pop	es
	jnz	SetDOSData_fail 	;signature mismatch

	add	si, 18			;SI -> county info type
	cmp	byte ptr ds:[si], 1	;Only accept type 1 (Currently only 1 header type)
	jne	SetDOSData_fail 	;cannot proceed. error return
	inc	si			;SI -> file offset
	mov	dx, word ptr ds:[si]	;Get the INFO file offset.
	mov	cx, word ptr ds:[si+2]
	mov	ax, 1024		;read 1024 bytes.
	call	ReadInControlBuffer	;Read INFO
	jc	SetDOSData_fail
	mov	cx, word ptr ds:[si]	;get the # of country, codepage combination entries
	cmp	cx, 72			;cannot handle more than 72 entries.
	ja	SetDOSData_fail
	inc	si
	inc	si			;SI -> entry information packet
	pop	dx			;restore code page id
	pop	ax			;restore country id
	pop	di

SetDOSCntry_find:			;Search for desired country_id,codepage_id.
	cmp	ax, word ptr ds:[si+2]	;compare country_id
	jne	SetDOSCntry_next
	cmp	dx, 0			;No user specified code page ?
	je	SetDOSCntry_any_codepage;then no need to match code page id.
	cmp	dx, word ptr ds:[si+4]	;compare code page id
	je	SetDOSCntry_got_it
SetDOSCntry_next:
	add	si, word ptr ds:[si]	;next entry
	inc	si
	inc	si			;take a word for size of entry itself
	loop	SetDOSCntry_find
	mov	cx, -1			;signals that bad country id entered.
SetDOSCntry_fail:
	stc
	ret

SetDOSData_fail:
	pop	si
	pop	cx
	pop	di
	jmp	short	SetDOSCntry_fail

SetDOSCntry_any_CodePage:		;use the code_page_id of the country_id found.
	mov	dx, word ptr ds:[si+4]
SetDOSCntry_got_it:			;found the matching entry
	mov	cs:CntryCodePage_Id, dx ;save code page ID for this country.
	mov	dx, word ptr ds:[si+10] ;get the file offset of country data
	mov	cx, word ptr ds:[si+12]
	mov	ax, 512 		;read 512 bytes
	call	ReadInControlBuffer
	jc	SetDOSCntry_fail
	mov	cx, word ptr ds:[si]	;get the number of entries to handle.
	inc	si
	inc	si			;SI -> first entry

SetDOSCntry_data:
	push	di			;ES:DI -> DOS_COUNTRY_CDPG_INFO
	push	cx			;save # of entry left
	push	si			;si -> current entry in Control buffer

	mov	al, byte ptr ds:[si+2]	;get data entry id
	call	GetCountryDestination	;get the address of destination in ES:DI
	jc	SetDOSCntry_data_next	;No matching data entry id in DOS


	mov	dx, word ptr ds:[si+4]	;get offset of data
	mov	cx, word ptr ds:[si+6]
	mov	ax, 4200h
	stc
	int	21h			;move pointer
	jc	SetDOSData_fail
	mov	dx, 512 		;start of data buffer
;	 mov	 cx, word ptr es:[di]	 ;length of the corresponding data in DOS.
;	 add	 cx, 10 		 ;Signature + A word for the length itself
	mov	cx, 20			;read 20 bytes only. We only need to
	mov	ah, 3fh 		;look at the length of the data in the file.
	stc
	int	21h			;read the country.sys data
	jc	SetDOSData_fail 	;read failure
	cmp	ax, cx
	jne	SetDOSData_fail

	mov	dx, word ptr ds:[si+4]	;AN008;get offset of data again.
	mov	cx, word ptr ds:[si+6]	;AN008;
	mov	ax, 4200h		;AN008;
	stc				;AN008;
	int	21h			;AN008;move pointer back again
	jc	SetDOSData_fail 	;AN008;

	push	si			;AN008;
	mov	si, (512+8)		;AN008;get length of the data from the file
	mov	cx, word ptr ds:[si]	;AN008;
	pop	si			;AN008;
	mov	dx, 512 		;AN008;start of data buffer
	add	cx, 10			;AN008;Signature + A word for the length itself
	mov	ah, 3fh 		;AN008;Read the data from the file.
	stc				;AN008;
	int	21h			;AN008;
	jc	SetDOSData_fail 	;AN008;
	cmp	ax, cx			;AN008;
	jne	SetDOSData_fail 	;AN008;

	mov	al, byte ptr ds:[si+2]	;save Data id for future use.
	mov	si, (512+8)		;SI-> data buffer + id tag field
	mov	cx, word ptr ds:[si]	;get the length of the file
	inc	cx			;Take care of a word for lenght of tab
	inc	cx			;itself.
	cmp	cx, (2048 - 512 - 8)	;Fit into the buffer?
	ja	SetDOSData_fail
	cmp	al, SetCountryInfo	;is the data for SetCountryInfo table?
	jne	SetDOSCntry_Mov 	;no, don't worry
	push	word ptr es:[di+ccMono_Ptr-ccCountryInfoLen]	;AN009;Cannot destroy ccMono_ptr address. Save them.
	push	word ptr es:[di+ccMono_Ptr-ccCountryInfoLen+2]	;AN009;At this time DI -> ccCountryInfoLen
	push	di			;save DI

	push	ax
	mov	ax,cs:CntryCodePage_Id	;Do not use the Code Page info in Country_Info
	mov	ds:[si+4], ax		;Use the saved one for this !!!!
	pop	ax

SetDOSCntry_Mov:
	rep	movsb			;copy the table into DOS
	cmp	al, SetCountryInfo	;was the ccMono_ptr saved?
	jne	SetDOSCntry_data_next
	pop	di			;restore DI
	pop	word ptr es:[di+ccMono_Ptr-ccCountryInfoLen+2]	 ;AN009;restore
	pop	word ptr es:[di+ccMono_Ptr-ccCountryInfoLen]	 ;AN009;

SetDOSCntry_data_next:
	pop	si			;restore control buffer pointer
	pop	cx			;restore # of entries left
	pop	di			;restore pointer to DSO_COUNTRY_CDPG
	add	si, word ptr ds:[si]	;try to get the next entry
	inc	si
	inc	si			;take a word of entry length itself
;	 loop	 SetDOSCntry_data
	dec	cx			;AN008;
	cmp	cx,0			;AN008;
	je	SetDOSCntry_OK		;AN008;
	jmp	SetDOSCntry_data	;AN008;
SetDOSCntry_OK: 			;AN008;
	ret
SetDOSCountryInfo	endp
;

GetCountryDestination	proc	near
;Get the destination address in the DOS country info table.
;Input: AL - Data ID
;	ES:DI -> DOS_COUNTRY_CDPG_INFO
;On return:
;	ES:DI -> Destination address of the matching data id
;	carry set if no matching data id found in DOS.

	push	cx
	add	di, ccNumber_of_entries ;skip the reserved area, syscodepage etc.
	mov	cx, word ptr es:[di]	;get the number of entries
	inc	di
	inc	di			;SI -> the first start entry id
GetCntryDest:
	cmp	byte ptr es:[di], al
	je	GetCntryDest_OK
	cmp	byte ptr es:[di], SetCountryInfo ;was it SetCountryInfo entry?
	je	GetCntryDest_1
	add	di, 5			;next data id
	jmp	short GetCntryDest_loop
GetCntryDest_1:
	add	di, NEW_COUNTRY_SIZE + 3 ;next data id
GetCntryDest_loop:
	loop	GetCntryDest
	stc
	jmp	short	GetCntryDest_exit
GetCntryDest_OK:
	cmp	al, SetCountryInfo	;select country info?
	jne	GetCntryDest_OK1
	inc	di			;now DI -> ccCountryInfoLen
	jmp	short	GetCntryDest_exit
GetCntryDest_OK1:
	les	di, dword ptr es:[di+1] ;get the destination in ES:DI
GetCntryDest_Exit:
	pop	cx
	ret
GetCountryDestination	endp

;
ReadInControlBuffer	proc	near
;Move file pointer to CX:DX
;Read AX bytes into the control buffer. (Should be less than 2 Kb)
;SI will be set to 0 hence DS:SI points to the control buffer.
;Entry:  CX,DX offset from the start of the file where the read/write pointer
;	 be moved.
;	 AX - # of bytes to read
;	 BX - file handle
;	 DS - buffer seg.
;Return: The control data information is read into DS:0 - DS:0200.
;	 CX,DX value destroyed.
;	 Carry set if error in Reading file.
;
	push	ax			;# of bytes to read
	mov	ax, 4200h
	stc
	int	21h			;move pointer
	pop	cx			;# of bytes to read
	jc	RICB_exit
	xor	dx,dx			;ds:dx -> control buffer
	xor	si,si
	mov	ah,3fh			;read into the buffer
	stc
	int	21h			;should be less than 1024 bytes.
RICB_exit:
	ret
ReadInControlBuffer	endp

;
SET_COUNTRY_PATH	proc	near
;In:  DS - SYSINITSEG, ES - CONFBOT, SI -> start of the asciiz path string
;     DOSINFO_EXT, CNTRY_DRV, CNTRY_ROOT, CNTRY_PATH
;     Assumes current directory is the ROOT directory.
;Out: DS:DI -> full path (CNTRY_DRV).
;     Set the CNTRY_DRV string from the COUNTRY=,,path command.
;     DS, ES, SI value saved.

	push	si
	push	ds			;switch ds, es
	push	es
	pop	ds
	pop	es			;now DS -> CONFBOT, ES -> SYSINITSEG

	call	chk_drive_letter	;current DS:[SI] is a drive letter?
	jc	SCP_Default_drv 	;no, use current default drive.
	mov	al, byte ptr DS:[SI]
	inc	si
	inc	si			;SI -> next char after ":"
	jmp	short SCP_SetDrv
SCP_Default_drv:
	mov	ah, 19h
	int	21h
	add	al, "A"                 ;convert it to a character.
SCP_SetDrv:
	mov	cs:CNTRY_DRV, al	;set the drive letter.
	mov	di, offset CNTRY_PATH
	mov	al, byte ptr DS:[SI]
	cmp	al, "\"
	je	SCP_Root_Dir
	cmp	al, cs:SWTCHR		;let's accept "/" as an directory delim
	je	SCP_Root_Dir
	jmp	short SCP_Path
SCP_Root_Dir:
	dec	di			;DI -> CNTRY_ROOT
SCP_Path:
	call	MOVE_ASCIIZ		;copy it
	mov	di, offset CNTRY_DRV
SCPath_Exit:
	push	ds			;switch ds, es
	push	es
	pop	ds
	pop	es			;DS, ES value restored
	pop	si
	RET
SET_COUNTRY_PATH	endp

;
CHK_DRIVE_LETTER	proc	near
;Check if DS:[SI] is a drive letter followed by ":".
;Assume that every alpha charater is already converted to UPPER CASE.
;Carry set if not.
;
	push	ax
	cmp	byte ptr ds:[si], "A"
	jb	CDLetter_NO
	cmp	byte ptr ds:[si], "Z"
	ja	CDLetter_NO
	cmp	byte ptr ds:[si+1], ":"
	jne	CDLetter_NO
	jmp	short CDLetter_exit
CDLetter_NO:
	stc
CDLetter_exit:
	pop	ax
	ret
CHK_DRIVE_LETTER	endp

;
MOVE_ASCIIZ	proc	near
;In: DS:SI -> source ES:DI -> target
;Out: copy the string until 0.
;Assumes there exists a 0.
MASCIIZ_loop:
	movsb
	cmp	byte ptr DS:[SI-1], 0	;Was it 0?
	jne	MASCIIZ_loop
	ret
MOVE_ASCIIZ	endp

;
;	DS:DX POINTS TO STRING TO OUTPUT (ASCIZ)
;
;	PRINTS <BADLD_PRE> <STRING> <BADLD_POST>
;
;
;
BADFIL:
	PUSH	CS
	POP	ES
	MOV	SI,DX
BADLOAD:
	MOV	DX,OFFSET BADLD_PRE	;WANT TO PRINT CONFIG ERROR
;	 MOV	 BX,OFFSET BADLD_POST
	mov	bx, offset CRLFM	;AN006;
PRNERR:
	PUSH	CS
	POP	DS
	call	Print
PRN1:	MOV	DL,ES:[SI]
	OR	DL,DL
	JZ	PRN2
	MOV	AH,STD_CON_OUTPUT
	INT	21H
	INC	SI
	JMP	PRN1
PRN2:	MOV	DX,BX
	call	Print
	cmp	DoNotShowNum, 1 	;AN000;  suppress line number when handling COMMAND.COM
	je	Prnexit
	call	Error_Line
PRNEXIT:
	return

PRINT:	MOV	AH,STD_CON_STRING_OUTPUT
	INT	21H
	return


	IF	NOEXEC
;
; LOAD NON EXE FILE CALLED [DS:DX] AT MEMORY LOCATION ES:BX
;
LDFIL:
	PUSH	AX
	PUSH	BX
	PUSH	CX
	PUSH	DX
	PUSH	SI
	PUSH	DS
	PUSH	BX
	XOR	AX,AX			;OPEN THE FILE
	MOV	AH,OPEN
	STC				;IN CASE OF INT 24
	INT	21H
	POP	DX			;Clean stack in case jump
	JC	LDRET
	PUSH	DX
	MOV	BX,AX			;Handle in BX
	XOR	CX,CX
	XOR	DX,DX
	MOV	AX,(LSEEK SHL 8) OR 2
	STC				;IN CASE OF INT 24
	INT	21H			; Get file size in DX:AX
	JC	LDCLSP
	OR	DX,DX
	JNZ	LDERRP			; File >64K
	POP	DX
	PUSH	DX
	MOV	CX,ES			; CX:DX is xaddr
	ADD	DX,AX			; Add file size to Xaddr
	JNC	DOSIZE
	ADD	CX,1000H		; ripple carry
DOSIZE:
	mov	ax,dx
	call	ParaRound
	mov	dx,ax

	ADD	CX,DX
	CMP	CX,[ALLOCLIM]
	JB	OKLD
	JMP	MEM_ERR

OKLD:
	XOR	CX,CX
	XOR	DX,DX
	MOV	AX,LSEEK SHL 8		;Reset pointer to beginning of file
	STC				;IN CASE OF INT 24
	INT	21H
	JC	LDCLSP
	POP	DX
	PUSH	ES			;READ THE FILE IN
	POP	DS			;Trans addr is DS:DX
	MOV	CX,0FF00H		; .COM files arn't any bigger than
					; 64k-100H
	MOV	AH,READ
	STC				;IN CASE OF INT 24
	INT	21H
	JC	LDCLS
	MOV	SI,DX			;CHECK FOR EXE FILE
	CMP	WORD PTR [SI],"ZM"
	CLC				; Assume OK
	JNZ	LDCLS			; Only know how to do .COM files
	STC
	JMP	SHORT LDCLS

LDERRP:
	STC
LDCLSP:
	POP	DX			;Clean stack
LDCLS:
	PUSHF
	MOV	AH,CLOSE		;CLOSE THE FILE
	STC
	INT	21H
	POPF

LDRET:	POP	DS
	POP	SI
	POP	DX
	POP	CX
	POP	BX
	POP	AX
	return
	ENDIF

;
;  OPEN DEVICE POINTED TO BY DX, AL HAS ACCESS CODE
;   IF UNABLE TO OPEN DO A DEVICE OPEN NULL DEVICE INSTEAD
;
OPEN_DEV:
	CALL	OPEN_FILE
	JNC	OPEN_DEV3
OPEN_DEV1:
	MOV	DX,OFFSET NULDEV
	CALL	OPEN_FILE
	return

OPEN_DEV3:
	MOV	BX,AX			; Handle from open to BX
	XOR	AX,AX			; GET DEVICE INFO
	MOV	AH,IOCTL
	INT	21H
	TEST	DL,10000000B
	retnz
	MOV	AH,CLOSE
	INT	21H
	JMP	OPEN_DEV1

OPEN_FILE:
	MOV	AH,OPEN
	STC
	INT	21H
	return

;J.K. TEST INT24. Return back to DOS with the fake user response of "FAIL"
INT24:
	mov	al, 3			;AN000; Fail the system call
	iret				;AN000; Return back to DOS.


;INT24:  ADD	 SP,6			 ;RESTORE MACHINE STATE
;	 POP	 AX
;	 POP	 BX
;	 POP	 CX
;	 POP	 DX
;	 POP	 SI
;	 POP	 DI
;	 POP	 BP
;	 POP	 DS
;	 POP	 ES
;	 PUSH	 AX
;	 MOV	 AH,GET_DEFAULT_DRIVE	 ;INITIALIZE DOS
;	 INT	 21H
;	 POP	 AX
;	 IRET				 ;BACK TO USER

	IF	ALTVECT
BOOTMES DB	13,10,"MS-DOS version "
	DB	MAJOR_VERSION + "0"
	DB	"."
	DB	(MINOR_VERSION / 10) + "0"
	DB	(MINOR_VERSION MOD 10) + "0"
	DB	13,10
	DB	"Copyright 1981,88 Microsoft Corp.",13,10,"$"
	ENDIF

include copyrigh.inc			;P1821; Copyright statement

NULDEV	DB	"NUL",0
CONDEV	DB	"CON",0
AUXDEV	DB	"AUX",0
PRNDEV	DB	"PRN",0

CONFIG	DB	"\CONFIG.SYS",0

CNTRY_DRV   DB	  "A:"
CNTRY_ROOT  DB	  "\"
CNTRY_PATH  DB	  "COUNTRY.SYS",0
	    DB	  52 DUP (0)

COUNTRY_FILE_SIGNATURE db 0FFh,'COUNTRY'

CntryCodePage_Id DW ?

COMMND	DB	"\COMMAND.COM",0
	DB	51 dup (0)

PathString db	64 dup (0)		;AN014;
LShare	db	"SHARE.EXE",0,"/NC",0Dh,0Ah ;AN014;AN015;To be used by Load/exec.
					;/NC parm will disable file sharing check.

COMTAB	LABEL	BYTE
;;;;	   DB	   8,"AVAILDEV",'A'     ; NO LONGER SUPPORTED
	DB	7,"BUFFERS",  'B'
	DB	5,"BREAK",    'C'
	DB	6,"DEVICE",   'D'
	DB	5,"FILES",    'F'
	DB	4,"FCBS",     'X'
	DB	9,"LASTDRIVE",'L'
	db     10,"MULTITRACK", 'M'     ;AN002;
	DB	8,"DRIVPARM", 'P'       ; RS for DOS 3.2
		IF     STACKSW
	DB	6,"STACKS",   'K'       ; BAS for DOS 3.2
		ENDIF
	DB	7,"COUNTRY",  'Q'
	DB	5,"SHELL",    'S'
	db	7,"INSTALL",  'I'       ;AN000;
	db	3,"IFS",      'J'       ;AN000;
	db	4,"CPSW",     'W'       ;AN000;
;;;;	   DB	   8,"SWITCHAR",'W'     ; NO LONGER SUPPORTED
	db	7,"COMMENT",  'Y'       ;AN000;
	db	3,"REM",      '0'       ;AN004;
	db	8,"SWITCHES", '1'       ;AN013;
	DB	0

public DeviceParameters
DeviceParameters a_DeviceParameters <0,DEV_3INCH720KB,0,80>

hlim	    dw	    2
slim	    dw	    9

public drive
drive	db	?

public switches
Switches    dw	0

;
; The following are the recommended BPBs for the media that we know of so
; far.

; 48 tpi diskettes

BPB48T	DW	512
	DB	2
	DW	1
	DB	2
	DW	112
	DW	2*9*40
	DB	0FDH
	DW	2
	DW	9
	DW	2
	DD	0
        DD      0

; 96tpi diskettes

BPB96T	DW	512
	DB	1
	DW	1
	DB	2
	DW	224
	DW	2*15*80
	DB	0F9H
	DW	7
	DW	15
	DW	2
	DD	0
        DD      0

; 3 1/2 inch diskette BPB

BPB35	DW	512
	DB	2
	DW	1
	DB	2
	DW	70h
	DW	2*9*80
	DB	0F9H
	DW	3
	DW	9
	DW	2
	DD	0
        DD      0
      
BPB35H	DW	0200H
	DB	01H
	DW	0001H
	DB	02H
	DW	0E0h
	DW	0B40H
	DB	0F0H
	DW	0009H
	DW	0012H
	DW	0002H
	DD	0
        DD      0

BPBTable    dw	    BPB48T		; 48tpi drives
	    dw	    BPB96T		; 96tpi drives
	    dw	    BPB35		; 3.5" drives
; The following are not supported, so default to 3.5" media layout
	    dw	    BPB35		; Not used - 8" drives
	    dw	    BPB35		; Not Used - 8" drives
	    dw	    BPB35		; Not Used - hard files
	    dw	    BPB35		; Not Used - tape drives
	    dw	    BPB35H		; 3-1/2" 1.44MB drive

switchlist  db	8,"FHSTDICN"         ; Preserve the positions of N and C.

; The following depend on the positions of the various letters in SwitchList

switchnum	equ 11111000B		; which switches require number

flagec35	equ 00000100B		; electrically compatible 3.5 inch disk drive
flagdrive	equ 00001000B
flagcyln	equ 00010000B
flagseclim	equ 00100000B
flagheads	equ 01000000B
flagff		equ 10000000B

SWTCHR	    EQU     "/"             ; switch follows this character

SYSINITSEG	ENDS
	END