summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/GRAPHICS/GRINST.ASM
blob: cdb8b17ed2aad1024414a77a3f8cdeadd5ac40af (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
	PAGE	,132								;AN000;
	TITLE	DOS - GRAPHICS Command  -	Installation Modules		;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
;; DOS - GRAPHICS Command
;; (C) Copyright 1988 Microsoft
;;										;AN000;
;; File Name:  GRINST.ASM							;AN000;
;; ----------									;AN000;
;;										;AN000;
;; Description: 								;AN000;
;; ------------ 								;AN000;
;;	 This file contains the installation modules for the			;AN000;
;;	 GRAPHICS command.							;AN000;
;;										;AN000;
;;	 GRAPHICS_INSTALL is the main module.					;AN000;
;;										;AN000;
;;	 GRAPHICS_INSTALL calls modules in GRLOAD.ASM to load			;AN000;
;;	 the GRAPHICS profile and GRPARMS.ASM to parse the command line.	;AN000;
;;										;AN000;
;;										;AN000;
;; Documentation Reference:							;AN000;
;; ------------------------							;AN000;
;;	 OASIS High Level Design						;AN000;
;;	 OASIS GRAPHICS I1 Overview						;AN000;
;;	 DOS 3.3 Message Retriever Interface Supplement. 			;AN000;
;;	 TUPPER I0 Document - PARSER HIGH LEVEL DESIGN REVIEW			;AN000;
;;										;AN000;
;; Procedures Contained in This File:						;AN000;
;; ----------------------------------						;AN000;
;;	 GRAPHICS_INSTALL - Main installation module				;AN000;
;;	 CHAIN_INTERRUPTS - Chain interrupts 5, 2F, EGA Save Pointers		;AN000;
;;	 COPY_PRINT_MODULES - Throw away one set of print modules		;AN000;
;;										;AN000;
;;										;AN000;
;; Include Files Required:							;AN000;
;; -----------------------							;AN000;
;;	 GRLOAD.EXT   - Externals for profile load				;AN000;
;;	 GRLOAD2.EXT  - Externals for profile load				;AN000;
;;	 GRCTRL.EXT   - Externals for print screen control			;AN000;
;;	 GRPRINT.EXT  - Externals for print modules				;AN000;
;;	 GRCPSD.EXT   - Externals for COPY_SHARED_DATA module			;AN000;
;;	 GRPARMS.EXT  - External for GRAPHICS command line parsing		;AN000;
;;	 GRPARSE.EXT  - External for DOS parser 				;AN000;
;;	 GRBWPRT.EXT  - Externals for Black and white printing modules		;AN000;
;;	 GRCOLPRT.EXT - Externals for color printing modules			;AN000;
;;	 GRINT2FH.EXT - Externals for Interrupt 2Fh driver.			;AN000;
;;										;AN000;
;;	 GRMSG.EQU    - Equates for the GRAPHICS error messages 		;AN000;
;;	 SYSMSG.INC   - DOS message retriever					;AN000;
;;										;AN000;
;;	 GRSHAR.STR   - Shared Data Area Structure				;AN000;
;;										;AN000;
;;	 STRUC.INC    - Macros for using structured assembly language		;AN000;
;;										;AN000;
;; External Procedure References:						;AN000;
;; ------------------------------						;AN000;
;;	 FROM FILE  GRLOAD.ASM: 						;AN000;
;;	      LOAD_PROFILE - Main module for profile loading			;AN000;
;;	 SYSPARSE   - DOS system parser 					;AN000;
;;	 SYSDISPMSG - DOS message retriever					;AN000;
;;										;AN000;
;; Linkage Instructions:							;AN000;
;; -------------------- 							;AN000;
;;	 Refer to GRAPHICS.ASM							;AN000;
;;										;AN000;
;; Change History:								;AN000;
;; ---------------								;AN000;
;;										;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
CODE	SEGMENT PUBLIC 'CODE'          ;;                                       ;AN000;
	ASSUME	CS:CODE,DS:CODE        ;;					;AN000;
				       ;;					;AN000;
.XLIST				       ;;					;AN000;
	INCLUDE GRSHAR.STR	       ;; Include the Shared data area structure;AN000;
	INCLUDE SYSMSG.INC	       ;; Include DOS message retriever 	;AN000;
	INCLUDE STRUC.INC	       ;; Include macros - Structured Assembler ;AN000;
	INCLUDE GRLOAD.EXT	       ;; Bring in external declarations	;AN000;
	INCLUDE GRLOAD2.EXT	       ;;					;AN000;
	INCLUDE GRLOAD3.EXT	       ;;					;AN000;
	INCLUDE GRCTRL.EXT	       ;;					;AN000;
	INCLUDE GRBWPRT.EXT	       ;;					;AN000;
	INCLUDE GRCOLPRT.EXT	       ;;					;AN000;
	INCLUDE GRCPSD.EXT	       ;;					;AN000;
	INCLUDE GRINT2FH.EXT	       ;;					;AN000;
	INCLUDE GRCTRL.EXT	       ;;					;AN000;
	INCLUDE GRPARSE.EXT	       ;;					;AN000;
	INCLUDE GRPARMS.EXT	       ;;					;AN000;
	INCLUDE GRMSG.EQU	       ;;					;AN000;
				       ;;					;AN000;
MSG_UTILNAME <GRAPHICS> 	       ;; Identify ourself to Message retriever.;AN000;
				       ;; Include messages			;AN000;
MSG_SERVICES <MSGDATA>		       ;;					;AN000;
MSG_SERVICES <LOADmsg,DISPLAYmsg,CHARmsg,NUMmsg>  ;;				;AN000;
MSG_SERVICES <GRAPHICS.CL1,GRAPHICS.CL2,GRAPHICS.CLA,GRAPHICS.CLB,GRAPHICS.CLC> ;AN000;
.LIST				       ;;					;AN000;
				       ;;					;AN000;
PUBLIC GRAPHICS_INSTALL 	       ;;					;AN000;
PUBLIC TEMP_SHARED_DATA_PTR	       ;;					;AN000;
PUBLIC PRINTER_TYPE_PARM	       ;;					;AN000;
PUBLIC PRINTER_TYPE_LENGTH	       ;;					;AN000;
PUBLIC PROFILE_PATH		       ;;					;AN000;
PUBLIC PRINTBOX_ID_PTR		       ;;					;AN000;
PUBLIC PRINTBOX_ID_LENGTH	       ;;					;AN000;
PUBLIC DEFAULT_BOX		       ;;					;AN000;
PUBLIC LCD_BOX			       ;;					;AN000;
PUBLIC NB_FREE_BYTES		       ;;					;AN000;
PUBLIC SYSDISPMSG		       ;;					;AN000;
PUBLIC DISP_ERROR		       ;;					;AN000;
PUBLIC INSTALLED		       ;;					;AN000;
PUBLIC ERROR_DEVICE		       ;;					;AN000;
PUBLIC STDERR			       ;;					;AN000;
PUBLIC STDOUT			       ;;					;AN000;
PUBLIC RESIDENT_SHARED_DATA_SIZE       ;;					;AN000;
				       ;;					;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
;;										;AN000;
;; Install Variables								;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
NO		      EQU   0	       ;;					;AN000;
YES		      EQU   1	       ;;					;AN000;
INSTALLED	      DB    NO	       ;; YES if GRAPHICS already installed	;AN000;
				       ;;					;AN000;
				       ;;					;AN000;
BYTES_AVAIL_PSP_OFF   EQU   6	       ;; Word number 6 of the PSP is the	;AN000;
				       ;;  number of bytes available in the	;AN000;
				       ;;   current segment			;AN000;
				       ;;					;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
;;										;AN000;
;; GRLOAD (PROFILE LOADING) INPUT PARMS:					;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
PRINTER_TYPE_PARM    DB    "GRAPHICS",9 DUP(0) ; Printer type                   ;AN000;
				       ;;  (default=GRAPHICS)			;AN000;
PRINTER_TYPE_LENGTH  DB    17	       ;; Printer type maximum length of ASCIIZ ;AN000;
PROFILE_PATH	     DB    128 DUP(0)  ;;  Profile name with full path		;AN000;
				       ;;   (Max size for ASCIIZ is 128)	;AN000;
PRINTBOX_ID_PTR      DW    DEFAULT_BOX ;;  Offset of ASCIIZ string containing	;AN000;
DEFAULT_BOX	     DB    "STD",14 DUP(0);  the printbox id. (DEFAULT = STD)   ;AN000;
LCD_BOX 	     DB    "LCD",14 DUP(0); ASCIIZ string for the LCD printboxID;AN000;
PRINTBOX_ID_LENGTH   DB    17	       ;;  Max. length for the printbox id.	;AN000;
				       ;;   ASCIIZ string			;AN000;
NB_FREE_BYTES	     DW    ?	       ;;  Number of bytes available in our	;AN000;
				       ;;   resident segment			;AN000;
RESIDENT_SHARED_DATA_SIZE  DW ?        ;;  Size in bytes of the RESIDENT Shared ;AN000;
				       ;;   data area (if GRAPHICS already	;AN000;
				       ;;    installed).			;AN000;
END_OF_RESIDENT_CODE DW    ?	       ;; Offset of the end of the code that	;AN000;
				       ;;  has to be made resident.		;AN000;
TEMP_SHARED_DATA_PTR DW    ?	       ;; Offset of the temporary Shared area	;AN000;
				       ;;					;AN000;
ERROR_DEVICE   DW   STDERR	       ;; Device DISP_ERROR will output 	;AN000;
				       ;;  messages to (STDERR or STDOUT)	;AN000;
PAGE										;AN000;
;===============================================================================;AN000;
;										;AN000;
; GRAPHICS_INSTALL : INSTALL GRAPHICS.COM					;AN000;
;										;AN000;
;-------------------------------------------------------------------------------;AN000;
;										;AN000;
;  INPUT:   Command line parameters						;AN000;
;	    GRAPHICS profile - A file describing printer characteristics and	;AN000;
;			       attributes.					;AN000;
;										;AN000;
;  OUTPUT:  If first time invoked:						;AN000;
;	      INT 5 VECTOR and INT 2FH VECTOR are replaced; only the required	;AN000;
;	      code for printing the screen is made resident.			;AN000;
;	    else,								;AN000;
;	      The resident code is updated to reflect changes in printing	;AN000;
;	      options.								;AN000;
;										;AN000;
;-------------------------------------------------------------------------------;AN000;
;;										;AN000;
;; DESCRIPTION: 								;AN000;
;;										;AN000;
;;   This module intalls GRAPHICS code and data.				;AN000;
;;										;AN000;
;;   An INT 2FH driver is also installed.					;AN000;
;;										;AN000;
;;   If this driver is already present then, we assume GRAPHICS was installed	;AN000;
;;   and do not install it again but, simply update the resident code.		;AN000;
;;										;AN000;
;;   The resident code contains ONLY the code and data needed for Printing	;AN000;
;;   the screen. The code needed is determined according to the command line	;AN000;
;;   parameters and the information extracted from the printer profile. 	;AN000;
;;										;AN000;
;;   The printer profile is parsed according to the current hardware setting	;AN000;
;;   and also to the command line options. The information extracted from	;AN000;
;;   the profile is stored in a Data area shared between the installation	;AN000;
;;   process and the Print Screen process.					;AN000;
;;										;AN000;
;;   A temporary Shared Data Area is FIRST built at the end of the .COM file	;AN000;
;;   Before building it, we verify that there is				;AN000;
;;   enough memory left in the current segment.  If not, the installation	;AN000;
;;   process is aborted.							;AN000;
;;										;AN000;
;;   This temporary Data area when completed will be copied over the		;AN000;
;;   installation code. Therefore, the file comprising GRAPHICS must be 	;AN000;
;;   linked in a specific order with the installation modules being last.	;AN000;
;;										;AN000;
;;   These modules will be overwritten by the Shared Data area and the EGA	;AN000;
;;   dynamic save area before we exit and stay resident.			;AN000;
;;										;AN000;
;;   The end of the resident code is the end of the Shared Data area, anything	;AN000;
;;   else beyond that is not made resident.					;AN000;
;;										;AN000;
;;   The pointer to the resident Shared Data area is declared within the	;AN000;
;;   Interrupt 2Fh driver. This pointer is initialized by the installation	;AN000;
;;   process and points to the shared data area at Print Screen time.		;AN000;
;;										;AN000;
;;   Depending on the type of printer attached (i.e., Black and white or Color) ;AN000;
;;   only one set of modules is made resident during the installation.		;AN000;
;;										;AN000;
;;   The set of print modules required is copied over the previous one at	;AN000;
;;   location "PRINT_MODULE_START". This location is declared within            ;AN000;
;;   GRCOLPRT which must be linked before GRBWPRT				;AN000;
;;										;AN000;
;;   When copying one of the 2 sets of print modules we reserve enough space	;AN000;
;;   for the larger of them. Therefore, if GRAPHICS is already installed but	;AN000;
;;   is reinvoked with a different printer type which needs a bigger set of	;AN000;
;;   modules: this new set of modules is simply recopied over the existing	;AN000;
;;   one in the resident code.							;AN000;
;;										;AN000;
;;   The Shared Data area is copied rigth after the set of modules that we keep ;AN000;
;;   that is, over the unused set of modules.					;AN000;
;;										;AN000;
;;										;AN000;
;-------------------------------------------------------------------------------;AN000;
;;										;AN000;
;; Register Conventions:							;AN000;
;;   BP - points to start of Temp Shared Data (Transiant code)			;AN000;
;;										;AN000;
;; Called By:									;AN000;
;;   Entry point for GRAPHICS command processing.				;AN000;
;;										;AN000;
;; External Calls:								;AN000;
;;   INT 2FH, LOAD_MESSAGES, LOAD_PROFILE, PARSE_PARMS				;AN000;
;;   CHAIN_INTERRUPTS, COPY_SHARED_DATA, DISPLAY_MESSAGE			;AN000;
;;   COPY_PRINT_MODULES 							;AN000;
;;										;AN000;
;-------------------------------------------------------------------------------;AN000;
;;										;AN000;
;; LOGIC:									;AN000;
;;   Load the message retriever 						;AN000;
;;   IF carry flag is set (incorrect DOS version) THEN				;AN000;
;;	Issue message (COMMON1) 						;AN000;
;;	Exit									;AN000;
;;   ENDIF									;AN000;
;;										;AN000;
;;   Get number of bytes available in the segment from PSP (word 6)		;AN000;
;;   /* This is needed since we construct a temporary Shared data area at the	;AN000;
;;   of the .COM file */							;AN000;
;;										;AN000;
;;   /* Build Shared Data in temporary area */					;AN000;
;;   END_OF_RESIDENT_CODE := (end of .COM file) 				;AN000;
;;   NB_FREE_BYTES    := Number of bytes availables				;AN000;
;;										;AN000;
;;   CALL PARSE_PARMS								;AN000;
;;   IF error THEN	/* PARSE_PARMS will issue messages */			;AN000;
;;	Exit									;AN000;
;;   ENDIF									;AN000;
;;										;AN000;
;;   CALL LOAD_PROFILE								;AN000;
;;   IF profile errors THEN							;AN000;
;;	Exit		/* LOAD_PROFILE will issue messages */			;AN000;
;;   ENDIF									;AN000;
;;										;AN000;
;;   Issue INT 2FH Install Check call (AX=1500H)				;AN000;
;;   /* INT 2FH returns ES:[DI] pointing to the shared data area */		;AN000;
;;   IF already installed THEN							;AN000;
;;   THEN									;AN000;
;;	Move NO to PRINT_SCREEN_ALLOWED in resident Shared Data 		;AN000;
;;	SHARED_DATA_AREA_PTR := DI						;AN000;
;;   ELSE									;AN000;
;;	MOV PRINT_SCREEN_ALLOWED,NO						;AN000;
;;	CALL CHAIN_INTERRUPTS	/* Install INT 5 and INT 2FH vectors */ 	;AN000;
;;	ES := Our segment							;AN000;
;;   ENDIF									;AN000;
;;   /* Keep only Print Black and White or Print Color: */			;AN000;
;;   CALL COPY_PRINT_MODULES							;AN000;
;;	/* COPY_SHARED_DATA will terminate & stay resident */			;AN000;
;;	Set up registers for copy & terminate call				;AN000;
;;	/* reserve enough memory to handle any printer in the profile*/ 	;AN000;
;;	jump to COPY_SHARED_DATA module 					;AN000;
;;   ELSE									;AN000;
;;	/* Shared Data has been built in place */				;AN000;
;;	move YES to PRINT_SCREEN_ALLOWED					;AN000;
;;	Return to DOS								;AN000;
;;   ENDIF									;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
GRAPHICS_INSTALL     PROC NEAR		;					;AN000;
										;AN000;
;-------------------------------------------------------------------------------;AN000;
; Load the error messages							;AN000;
;-------------------------------------------------------------------------------;AN000;
   CALL    SYSLOADMSG		    ; Load messages				;AN000;
  .IF C 			    ; If error when loading messages		;AN000;
  .THEN 			    ; then,					;AN000;
     MOV     CX,0		    ;	CX := No substitution in message	;AN000;
     MOV     AX,1		    ;	AX := msg nb. for "Invalid DOS version" ;AN000;
     CALL DISP_ERROR		    ;	Display error message			;AN000;
     JMP     ERROR_EXIT 	    ;	 and quit				;AN000;
  .ENDIF									;AN000;
										;AN000;
;-------------------------------------------------------------------------------;AN000;
; Get offset of where to build the TEMPORARY Shared Data area (always built)	;AN000;
;-------------------------------------------------------------------------------;AN000;
   MOV	   BP,OFFSET LIMIT	     ; Build it at the end of this .COM file	;AN000;
				     ;	(LIMIT = the offset of the last byte	;AN000;
				     ;	  of the last .OBJ file linked with	;AN000;
				     ;	   GRAPHICS)				;AN000;
   MOV	   TEMP_SHARED_DATA_PTR,BP   ;						;AN000;
										;AN000;
;-------------------------------------------------------------------------------;AN000;
; Determine if GRAPHICS is already installed; get the resident segment value	;AN000;
;-------------------------------------------------------------------------------;AN000;
    MOV     AH,PRT_SCR_2FH_NUMBER    ; Call INT 2FH (the Multiplex interrupt)	;AN000;
    XOR     AL,AL		     ;	for Print Screen handler		;AN000;
    INT     2FH 		     ;						;AN000;
										;AN000;
   .IF <AH EQ 0FFH>		     ; IF already installed			;AN000;
   .THEN			     ; then,					;AN000;
   ;----------------------------------------------------------------------------;AN000;
   ; GRAPHICS is already installed: Get pointer to the EXISTING Shared Data area;AN000;
   ;----------------------------------------------------------------------------;AN000;
      MOV     INSTALLED,YES	    ;	Say it's installed                      ;AN000;
      MOV     AX,ES		    ;	Get the segment and offset of the	;AN000;
      MOV     SHARED_DATA_AREA_PTR,DI;	 resident Shared Data area.		;AN000;
      MOV     RESIDENT_CODE_SEG,AX  ;	  (returned in ES:DI)			;AN000;
				    ;	Disable print screen because we will	;AN000;
      MOV     ES:PRINT_SCREEN_ALLOWED,NO ; be updating the resident code.	;AN000;
   .ELSE			    ; ELSE, not installed:			;AN000;
   ;------------------------------------------------------------------------	;AN000;
   ; GRAPHICS is NOT installed: RESIDENT shared data area is in OUR segment	;AN000;
   ;------------------------------------------------------------------------	;AN000;
      PUSH    CS		    ; The Shared Data area will be in our	;AN000;
      POP     RESIDENT_CODE_SEG     ;  segment. 				;AN000;
   .ENDIF									;AN000;
										;AN000;
;-------------------------------------------------------------------------------;AN000;
; Determine in AX how many bytes are available for building the TEMPORARY SHARED;AN000;
; DATA AREA:									;AN000;
;-------------------------------------------------------------------------------;AN000;
    MOV     AX,ES:BYTES_AVAIL_PSP_OFF;AX := Number of bytes availables in	;AN000;
				    ;  the current segment (as indicated in PSP);AN000;
   .IF	<AX B <OFFSET LIMIT>>	    ; If there is no bytes available past	;AN000;
   .THEN			    ;	the end of our .COM file		;AN000;
      XOR     AX,AX		    ; then, AX := 0 bytes available		;AN000;
   .ELSE			    ;						;AN000;
      SUB     AX,OFFSET LIMIT	    ; else,  AX := Number of FREE bytes 	;AN000;
   .ENDIF			    ;	     in this segment			;AN000;
										;AN000;
;---AX = Number of bytes in our segment available for building the Temp Shared	;AN000;
;---data area.									;AN000;
;---IF ALREADY INSTALLED: Get the size of the existing Shared data area.	;AN000;
;---Since the temporary shared data area will be copied over the resident	;AN000;
;---shared data area, we do not want to build it any bigger than the one	;AN000;
;---it will overwrite. Therefore we do not give to LOAD_PROFILE more space	;AN000;
;---than the size of the existing Shared data area.				;AN000;
   .IF <INSTALLED EQ YES>	    ; If already installed then,		;AN000;
   .THEN									;AN000;
      PUSH CS:RESIDENT_CODE_SEG     ; ES:[DI] := Resident Shared data area	;AN000;
      POP  ES			    ;						;AN000;
      MOV  DI,SHARED_DATA_AREA_PTR  ;						;AN000;
      MOV  CX,ES:[DI].SD_TOTAL_SIZE ; CX := Size of the existing Shared area	;AN000;
      MOV  RESIDENT_SHARED_DATA_SIZE,CX ; Save size for LOAD_PROFILE		;AN000;
     .IF <AX A CX>		    ; If AX > size of existing SDA		;AN000;
	MOV AX,CX		    ; then, AX := Size of existing Shared area	;AN000;
     .ENDIF			    ;						;AN000;
   .ENDIF									;AN000;
				    ;  NB_FREE_BYTES := Number of bytes 	;AN000;
    MOV     NB_FREE_BYTES,AX	    ;	available for				;AN000;
				    ;	 building the TEMPORARY shared area	;AN000;
;-------------------------------------------------------------------------------;AN000;
; Parse the command line parameters						;AN000;
;-------------------------------------------------------------------------------;AN000;
   MOV	   BYTE PTR CS:[BP].SWITCHES,0 ; Init. the command line switches	;AN000;
   PUSH    CS			   ; Set ES to segment containing the PSP	;AN000;
   POP	   ES									;AN000;
   CALL    PARSE_PARMS		   ; Set switches in the Temp. Shared Area	;AN000;
  .IF C 			   ; If error when parsing the command		;AN000;
    .THEN			   ; line then, EXIT				;AN000;
     JMP     ERROR_EXIT 							;AN000;
  .ENDIF									;AN000;
										;AN000;
;-------------------------------------------------------------------------------;AN000;
; Parse the printer profile - Build the temporary Shared data area		;AN000;
;-------------------------------------------------------------------------------;AN000;
    CALL  LOAD_PROFILE		    ;  Builds profile info in Temporary Shared	;AN000;
				    ;	Data					;AN000;
   .IF C			    ; If error when loading the profile 	;AN000;
   .THEN			    ; then, EXIT				;AN000;
      JMP     ERROR_EXIT							;AN000;
   .ENDIF									;AN000;
										;AN000;
;-------------------------------------------------------------------------------;AN000;
; Check if /B was specified with a BLACK and WHITE printer:(invalid combination);AN000;
;-------------------------------------------------------------------------------;AN000;
   .IF <CS:[BP].PRINTER_TYPE EQ BLACK_WHITE> AND				;AN000;
   .IF <BIT CS:[BP].SWITCHES NZ BACKGROUND_SW>					;AN000;
   .THEN									;AN000;
      MOV     AX,INVALID_B_SWITCH     ; Error := /B invalid with B&W prt.	;AN000;
      MOV     CX,0		      ; No substitution 			;AN000;
      CALL    DISP_ERROR	      ; Display error message			;AN000;
      JMP     ERROR_EXIT	      ;  and quit				;AN000;
   .ENDIF									;AN000;
										;AN000;
;-------------------------------------------------------------------------------;AN000;
;										;AN000;
; RELOCATE THE TEMPORARY SHARED DATA AREA AND THE SET OF REQUIRED PRINT MODULES ;AN000;
;										;AN000;
; (Discard the set of print modules not needed with the printer attached and	;AN000;
;  discard all the code not used at print screen time). 			;AN000;
;										;AN000;
; If GRAPHICS is already installed then, we copy the				;AN000;
; Shared Data area and the print modules over the previous ones installed in	;AN000;
; resident memory.								;AN000;
;										;AN000;
; If we are installed for the first time then, we copy those over the		;AN000;
; installation modules before we exit and stay resident.			;AN000;
;										;AN000;
; A temporaty Shared Data area is always created even if a resident one 	;AN000;
; already exist (it is then, copied over), a set of print modules is recopied	;AN000;
; only if needed.								;AN000;
;										;AN000;
; NOTE: END_OF_RESIDENT_CODE points to the first location over which code	;AN000;
;	may be relocated.  After data or code is relocated, END_OF_RESIDENT_CODE;AN000;
;	is updated and points to the next available location for copying code	;AN000;
;	that will stay resident.						;AN000;
;-------------------------------------------------------------------------------;AN000;
;-------------------------------------------------------------------------------;AN000;
; Initialize the pointer to the next available location for resident code:	;AN000;
;-------------------------------------------------------------------------------;AN000;
   .IF <INSTALLED EQ NO>	    ; If not installed				;AN000;
   .THEN			    ; then,					;AN000;
      MOV     END_OF_RESIDENT_CODE,OFFSET PRINT_MODULE_START			;AN000;
   .ENDIF			    ;	we make everything up to the print	;AN000;
				    ;	 modules resident code. 		;AN000;
;-------------------------------------------------------------------------------;AN000;
; Keep only the set of print modules that is needed:				;AN000;
;-------------------------------------------------------------------------------;AN000;
    CALL    COPY_PRINT_MODULES	    ; Updates END_OF_RESIDENT_CODE		;AN000;
;-------------------------------------------------------------------------------;AN000;
; Replace the interrupt vectors and install the EGA dynamic area (if needed)	;AN000;
;-------------------------------------------------------------------------------;AN000;
   .IF <INSTALLED EQ NO>	    ; If not already installed			;AN000;
   .THEN			    ; then,					;AN000;
;------Release evironment vector						;AN002;
      CALL RELEASE_ENVIRONMENT	    ;	release unneeded environment vector	;AN002;
;------Replace the interrupt vectors						;AN000;
      MOV   PRINT_SCREEN_ALLOWED,NO ;	Disable Print Screen			;AN000;
      CALL  CHAIN_INTERRUPTS	    ;	Replace the interrupt vectors		;AN000;
				    ;	 (END_OF_RESIDENT_CODE is updated)	;AN000;
      CALL  DET_HW_CONFIG	    ;	Find what display adapter we got	;AN000;
     .IF <CS:[BP].HARDWARE_CONFIG EQ EGA>;If EGA is present			;AN000;
     .THEN			    ;	then,					;AN000;
	 CALL INST_EGA_SAVE_AREA    ;	  Install the EGA dynamic save area	;AN000;
     .ENDIF			    ;	  (END_OF_RESIDENT_CODE is updated)	;AN000;
;------Calculate the size of the resident code					;AN000;
      MOV   DX,END_OF_RESIDENT_CODE ; DX := End of resident code		;AN000;
      ADD   DX,CS:[BP].SD_TOTAL_SIZE; Add size of Shared Data area		;AN000;
      MOV   CL,4		    ;						;AN000;
      SHR   DX,CL		    ; convert to paragraphs			;AN000;
      INC   DX			    ;  and add 1				;AN000;
;------Set AX to DOS exit function call - (COPY_SHARED_DATA will exit to DOS)	;AN000;
      MOV   AH,31H		    ; Function call to terminate but stay	;AN000;
      XOR   AL,AL		    ;	resident				;AN000;
   .ELSE									;AN000;
      MOV   AH,4CH		    ; Function call to terminate		;AN000;
      XOR   AL,AL		    ; (EXIT to calling process) 		;AN000;
   .ENDIF									;AN000;
										;AN000;
;-------------------------------------------------------------------------------;AN000;
; Copy the temporary shared data area in the resident code			;AN000;
;-------------------------------------------------------------------------------;AN000;
    MOV     CX,CS:[BP].SD_TOTAL_SIZE; CX := MOVSB count for COPY_SHARED_DATA	;AN000;
    MOV     SI,BP		    ; DS:SI := Temporary Shared data area	;AN000;
    PUSH    RESIDENT_CODE_SEG	    ; ES:DI := Resident Shared data area:	;AN000;
    POP     ES			    ;						;AN000;
   .IF <INSTALLED EQ NO>	    ; If not installed				;AN000;
   .THEN			    ; then,					;AN000;
      MOV     DI,END_OF_RESIDENT_CODE;	 DI := End of resident code		;AN000;
      MOV     BP,DI		    ;	BP := New resident Shared data area	;AN000;
      MOV     SHARED_DATA_AREA_PTR,DI;	 Update pointer to resident Shar. area	;AN000;
   .ELSE			    ; else,					;AN000;
      MOV     DI,SHARED_DATA_AREA_PTR ;   DI := Existing Shared data area	;AN000;
      MOV     BP,DI		    ;	BP = DI:= Existing Shared data area	;AN000;
   .ENDIF									;AN000;
      JMP   COPY_SHARED_DATA	    ; Jump to proc that copies area in new	;AN000;
				    ;  part of memory and exits to DOS		;AN000;
ERROR_EXIT:									;AN000;
   .IF <INSTALLED EQ YES>	    ; If we are already installed, re-enable	;AN000;
      MOV   ES,RESIDENT_CODE_SEG    ;  print screens				;AN000;
      MOV   ES:PRINT_SCREEN_ALLOWED,YES 					;AN000;
   .ENDIF			    ;						;AN000;
				    ;						;AN000;
    MOV     AH,4CH		    ; Function call to terminate		;AN000;
    MOV     AL,1		    ; (EXIT to calling process) 		;AN000;
    INT     21H 								;AN000;
GRAPHICS_INSTALL     ENDP							;AN000;
										;AN000;
PAGE										;AN000;
;===============================================================================;AN000;
;										;AN000;
; INST_EGA_SAVE_AREA : INSTALL A DYNAMIC SAVE AREA FOR THE EGA PALETTE REGISTERS;AN000;
;										;AN000;
;-------------------------------------------------------------------------------;AN000;
;										;AN000;
; INPUT:   DS			= Data segment for our code			;AN000;
;	   END_OF_RESIDENT_CODE = Offset of the end of the resident code	;AN000;
;										;AN000;
; OUTPUT:  END_OF_RESIDENT_CODE is updated to point to the end of the code	;AN000;
;				   that will stay resident.			;AN000;
;	   SAVE_AREA_PTR in BIOS segment is updated.				;AN000;
;										;AN000;
;-------------------------------------------------------------------------------;AN000;
;;										;AN000;
;; Data Structures Referenced:							;AN000;
;;   Shared Data Area								;AN000;
;;										;AN000;
;; Description: 								;AN000;
;;   ************* The EGA Dynamic Save Area will be built over top		;AN000;
;;   **  NOTE	** of the profile loading modules (file GRLOAD.ASM)		;AN000;
;;   ************* to avoid having to relocate this area just before		;AN000;
;;   terminating.  This is safe since the maximum memory used is		;AN000;
;;   288 bytes and the profile loading modules are MUCH larger than		;AN000;
;;   this.  So GRLOAD.ASM MUST be linked before GRINST.ASM and after		;AN000;
;;   GRPRINT.ASM.								;AN000;
;;										;AN000;
;; BIOS will update the dynamic save area whenener it's aware the palette       ;AN000;
;; registers have been updated. 						;AN000;
;;										;AN000;
;; BIOS 4A8H		BIOS SAVE	       EGA DYNAMIC			;AN000;
;; POINTER:		POINTER TABLE	       SAVE AREA			;AN000;
;; ��������Ŀ		������������Ŀ	       (16 first bytes are the 16	;AN000;
;; �   *���������������>�	     �		EGA palette registers)		;AN000;
;; ����������		������������Ĵ	       �����������Ŀ			;AN000;
;;			�     *���������������>�����������Ĵ			;AN000;
;;			������������Ĵ	       �����������Ĵ			;AN000;
;;			�	     �	       �����������Ĵ			;AN000;
;;			������������Ĵ		     .				;AN000;
;;			�	     �		     .				;AN000;
;;			������������Ĵ		     .	    256 bytes		;AN000;
;;			�	     �		     .				;AN000;
;;			������������Ĵ		     .				;AN000;
;;			�	     �	       �����������Ĵ			;AN000;
;;			������������Ĵ	       �����������Ĵ			;AN000;
;;			�	     �	       �����������Ĵ			;AN000;
;;			������������Ĵ	       �����������Ĵ			;AN000;
;;			�	     �	       �����������Ĵ			;AN000;
;;			��������������	       �������������			;AN000;
;;										;AN000;
;; Called By:									;AN000;
;;   GRAPHICS_INSTALL								;AN000;
;;										;AN000;
;; External Calls:								;AN000;
;;										;AN000;
;; Logic:									;AN000;
;;   IF EGA Dynamic Save Area NOT established THEN				;AN000;
;;	  /* Required since default table is in ROM */				;AN000;
;;	  IF Save Table is in ROM						;AN000;
;;	     Replicate all the Save Area Table in resident RAM just before	;AN000;
;;	      the Shared Data Area						;AN000;
;;	  ENDIF 								;AN000;
;;	  Allocate 256 bytes for EGA Dynamic Save Area just before the		;AN000;
;;	  Shared Data Area							;AN000;
;;	  Update END_OF_RESIDENT_CODE						;AN000;
;;     ENDIF									;AN000;
;;   RETURN									;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
BIOS_SAVE_PTR	     EQU    4A8H       ;; Offset of the BIOS Save Ptr area	;AN000;
SAVE_AREA_LEN	     EQU    8*4        ;; There are 8 pointers in the Save area ;AN000;
EGA_DYNAMIC_LEN      EQU    256        ;; Length of the EGA dynamic save area	;AN000;
; Standard default colours for the Enhanced Graphics Adapter: (rgbRGB values)	;AN000;
; The following table is necessary in order to initialize the EGA DYNAMIC	;AN000;
; SAVE AREA when creating it.							;AN000;
EGA_DEFAULT_COLORS   DB     00h        ;; Black 				;AN000;
		     DB     01h        ;; Blue					;AN000;
		     DB     02h        ;; Green 				;AN000;
		     DB     03h        ;; Cyan					;AN000;
		     DB     04h        ;; Red					;AN000;
		     DB     05h        ;; Magenta				;AN000;
		     DB     14h        ;; Brown 				;AN000;
		     DB     07h        ;; White 				;AN000;
		     DB     38h        ;; Dark Grey				;AN000;
		     DB     39h        ;; Light Blue				;AN000;
		     DB     3Ah        ;; Light Green				;AN000;
		     DB     3Bh        ;; Light Cyan				;AN000;
		     DB     3Ch        ;; Light Red				;AN000;
		     DB     3Dh        ;; Light Magenta 			;AN000;
		     DB     3Eh        ;; Yellow				;AN000;
		     DB     3Fh        ;; Bright white				;AN000;
		     DB     00h        ;; OVERSCAN register			;AN000;
										;AN000;
INST_EGA_SAVE_AREA PROC NEAR							;AN000;
PUSH	AX									;AN000;
PUSH	CX									;AN000;
PUSH	DX									;AN000;
PUSH	SI									;AN000;
PUSH	DI									;AN000;
PUSH	ES									;AN000;
;-------------------------------------------------------------------------------;AN000;
; Get the BIOS save pointer table						;AN000;
;-------------------------------------------------------------------------------;AN000;
XOR	AX,AX			      ; ES := segment 0 			;AN000;
MOV	ES,AX									;AN000;
LES	SI,ES:DWORD PTR BIOS_SAVE_PTR ; ES:[SI] =Current BIOS save table	;AN000;
.IF <<WORD PTR ES:[SI]+4> EQ 0> AND   ; IF the dynamic save are pointer is	;AN000;
.IF <<WORD PTR ES:[SI]+6> EQ 0>       ;  null then, it's not defined            ;AN000;
.THEN				      ;   and we have to define it:		;AN000;
    ;---------------------------------------------------------------------------;AN000;
    ; The Dynamic EGA save area is NOT DEFINED: 				;AN000;
    ;---------------------------------------------------------------------------;AN000;
     MOV   BYTE PTR ES:[SI]+4,0FFH    ; Try to write a byte in the table	;AN000;
     PUSH  AX			      ; (PUSH AX, POP AX used to create a	;AN000;
     POP   AX			      ;  small delay)				;AN000;
    .IF <<WORD PTR ES:[SI]+4> NE 0FFH>;If we can't read our byte back then,     ;AN000;
    .THEN			      ;  the Save Ptrs table is in ROM		;AN000;
       ;------------------------------------------------------------------------;AN000;
       ; The Save pointer table is in ROM;					;AN000;
       ; Copy the BIOS save pointer table from ROM to within our .COM file	;AN000;
       ;------------------------------------------------------------------------;AN000;
	PUSH  ES		      ; DS:SI := Offset of BIOS save ptrs table ;AN000;
	POP   DS		      ; 					;AN000;
	PUSH  CS		      ; ES:DI := The next available location	;AN000;
	POP   ES		      ; 	  for installing resident code	;AN000;
	MOV   DI,CS:END_OF_RESIDENT_CODE ;	   within our .COM file 	;AN000;
	MOV   CS:OUR_SAVE_TAB_OFF,DI  ; 					;AN000;
	MOV   CX,SAVE_AREA_LEN	      ;     CX := Length of the table to copy	;AN000;
	REP   MOVSB		      ;  Replicate the Save Table		;AN000;
	PUSH  CS								;AN000;
	POP   DS		      ; Reestablish our data segment		;AN000;
       ;------------------------------------------------------------------------;AN000;
       ; Adjust END_OF_RESIDENT_CODE to the next offset available for copying	;AN000;
       ; resident code and data.						;AN000;
       ;------------------------------------------------------------------------;AN000;
	ADD   END_OF_RESIDENT_CODE,SAVE_AREA_LEN				;AN000;
       ;------------------------------------------------------------------------;AN000;
       ; Set the pointer in OUR Save ptr table to our EGA dynamic save area	;AN000;
       ; which we create right after the Save pointer table.			;AN000;
       ;------------------------------------------------------------------------;AN000;
	MOV	DI,OUR_SAVE_TAB_OFF    ; DS:[DI] := Our BIOS save ptr tab	;AN000;
	MOV	AX,END_OF_RESIDENT_CODE; Store its offset			;AN000;
	MOV	DS:[DI]+4,AX	       ;					;AN000;
	MOV	WORD PTR DS:[DI]+6,DS  ; Store its segment			;AN000;
       ;------------------------------------------------------------------------;AN000;
       ; Initialize our DYNAMIC SAVE AREA with the 16 standard EGA colors	;AN000;
       ;------------------------------------------------------------------------;AN000;
										;AN000;
	LEA  SI,EGA_DEFAULT_COLORS	; DS:[SI] := EGA 16 Default colors	;AN000;
	MOV  DI,END_OF_RESIDENT_CODE	; ES:[DI] := DYNAMIC SAVE AREA		;AN000;
	MOV  CX,17			; CX := Number of colors		;AN000;
	REP  MOVSB			; Initialize the Dynamic save area	;AN000;
       ;------------------------------------------------------------------------;AN000;
       ; Set the BIOS Save Pointer to our table of Save pointers:		;AN000;
       ;------------------------------------------------------------------------;AN000;
	CLI									;AN000;
	XOR	AX,AX		       ; ES:BIOS_SAVE_PTR := Our save table:	;AN000;
	MOV	ES,AX								;AN000;
	MOV	AX,OUR_SAVE_TAB_OFF						;AN000;
	MOV	ES:BIOS_SAVE_PTR,AX						;AN000;
	MOV	ES:BIOS_SAVE_PTR+2,DS						;AN000;
	STI									;AN000;
    .ELSE			       ; ELSE save pointer table is in RAM	;AN000;
       ;------------------------------------------------------------------------;AN000;
       ; ELSE, the BIOS save pointer table is in RAM:				;AN000;
       ;------------------------------------------------------------------------;AN000;
       ;------------------------------------------------------------------------;AN000;
       ; Set the pointer in THEIR Save ptr table to OUR EGA dynamic save area	;AN000;
       ;------------------------------------------------------------------------;AN000;
	MOV   WORD PTR ES:[SI]+6,DS    ; ES:[SI] = The existing table in RAM	;AN000;
	MOV   AX,END_OF_RESIDENT_CODE						;AN000;
	MOV   ES:[SI]+4,AX							;AN000;
    .ENDIF			       ; ENDIF save pointer table is in ROM	;AN000;
  ;-----------------------------------------------------------------------------;AN000;
  ; Adjust END_OF_RESIDENT_CODE to the next offset available for copying	;AN000;
  ; resident code and data.							;AN000;
  ;-----------------------------------------------------------------------------;AN000;
   ADD	END_OF_RESIDENT_CODE,EGA_DYNAMIC_LEN					;AN000;
.ENDIF										;AN000;
POP	 ES									;AN000;
POP	 DI									;AN000;
POP	 SI									;AN000;
POP	 DX									;AN000;
POP	 CX									;AN000;
POP	 AX									;AN000;
										;AN000;
RET										;AN000;
OUR_SAVE_TAB_OFF DW	?							;AN000;
INST_EGA_SAVE_AREA ENDP 							;AN000;
PAGE										;AN000;
;===============================================================================;AN000;
;										;AN000;
; CHAIN_INTERRUPTS : INSTALL INT 5 AND INT 2FH VECTORS				;AN000;
;										;AN000;
;-------------------------------------------------------------------------------;AN000;
;										;AN000;
; INPUT:   DS			= Data segment for our code			;AN000;
;	   END_OF_RESIDENT_CODE = Offset of the end of the resident code	;AN000;
;										;AN000;
; OUTPUT:  OLD_INT_2FH		  (within INT_2FH_DRIVER)			;AN000;
;	   BIOS_INT_5H		  (within PRT_SCR module)			;AN000;
;	   END_OF_RESIDENT_CODE is updated to point to the end of the code	;AN000;
;				   that will stay resident.			;AN000;
;	   SAVE_AREA_PTR in BIOS segment is updated if an EGA adapter is found	;AN000;
;										;AN000;
;-------------------------------------------------------------------------------;AN000;
;;										;AN000;
;; Data Structures Referenced:							;AN000;
;;   Shared Data Area								;AN000;
;;										;AN000;
;; Description: 								;AN000;
;;   Install Interrupts 5 and 2FH. The old vectors are saved.			;AN000;
;;										;AN000;
;; Called By:									;AN000;
;;   GRAPHICS_INSTALL								;AN000;
;;										;AN000;
;; External Calls:								;AN000;
;;   DOS INT 21H Replace vector AH=25h						;AN000;
;;   DOS INT 21H Get vector AH=35h						;AN000;
;;										;AN000;
;; Logic:									;AN000;
;;   Save interrupt 5 vector in BIOS_INT_5H					;AN000;
;;   Point interrupt 5 to PRT_SCR module					;AN000;
;;   Save interrupt 2FH vector in BIOS_INT_2FH					;AN000;
;;   Point interrupt 2FH to INT_2FH_DRIVER module				;AN000;
;;   RETURN									;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
				       ;;					;AN000;
CHAIN_INTERRUPTS  PROC NEAR	       ;;					;AN000;
	PUSH	ES								;AN000;
	PUSH	BX								;AN000;
										;AN000;
;-------------------------------------------------------------------------------;AN000;
; Replace INTERRUPT 5 vector							;AN000;
;-------------------------------------------------------------------------------;AN000;
	MOV	AH,35H			; Get vector for			;AN000;
	MOV	AL,5			;  interrupt 5 request			;AN000;
	INT	21H			; Call DOS				;AN000;
										;AN000;
	MOV	BIOS_INT_5H,BX		; Save the old vector			;AN000;
	MOV	BIOS_INT_5H+2,ES						;AN000;
										;AN000;
	MOV	DX,OFFSET PRT_SCR	; DS:DX := Offset of our Print Screen	;AN000;
										;AN000;
	MOV	AH,25H			; Replace vector for			;AN000;
	MOV	AL,5			;  interrupt 5 request			;AN000;
	INT	21H			; Call DOS				;AN000;
										;AN000;
;-------------------------------------------------------------------------------;AN000;
; Replace INTERRUPT 2FH vector							;AN000;
;-------------------------------------------------------------------------------;AN000;
	MOV	AH,35H			; Get vector for			;AN000;
	MOV	AL,2FH			;  interrupt 2FH request		;AN000;
	INT	21H			; Call DOS				;AN000;
										;AN000;
	MOV	WORD PTR OLD_INT_2FH,BX ; Save the old vector			;AN000;
	MOV	WORD PTR OLD_INT_2FH+2,ES					;AN000;
										;AN000;
	MOV	DX,OFFSET INT_2FH_DRIVER; DS:DX := Offset of our 2FH handler	;AN000;
										;AN000;
	MOV	AH,25H			; Replace vector for			;AN000;
	MOV	AL,2FH			;  interrupt 2FH request		;AN000;
	INT	21H			; Call DOS				;AN000;
										;AN000;
	POP	BX								;AN000;
	POP	ES								;AN000;
	RET									;AN000;
CHAIN_INTERRUPTS  ENDP								;AN000;
										;AN000;
;===============================================================================;AN000;
;										;AN000;
; COPY_PRINT_MODULES: COPY THE SET OF PRINT MODULES NEEDED OVER THE PREVIOUS ONE;AN000;
;										;AN000;
;-------------------------------------------------------------------------------;AN000;
;										;AN000;
; INPUT:  BP		       = Offset of the temporary Shared Data area	;AN000;
;	  END_OF_RESIDENT_CODE = Location of the set of COLOR modules		;AN000;
;				 (if first time installed)			;AN000;
;	  CS:[BP].PRINTER_TYPE = Printer type NEEDED				;AN000;
;	  RESIDENT_CODE_SEG    = Segment containing the resident code		;AN000;
;										;AN000;
; OUTPUT: END_OF_RESIDENT_CODE = End of the print modules IS UPDATED		;AN000;
;				 (If first time installed)			;AN000;
;										;AN000;
;-------------------------------------------------------------------------------;AN000;
;;										;AN000;
;; Data Structures Referenced:							;AN000;
;;   Control Variables								;AN000;
;;   Shared Data Area								;AN000;
;;										;AN000;
;; Description: 								;AN000;
;;   This module trashes one set of print modules (Color or Black & White)	;AN000;
;;   depending on the type of printer attached.  Since the Shared Data		;AN000;
;;   (resident version) will reside immediately after the print modules,	;AN000;
;;   END_OF_RESIDENT_CODE will be set by this modules.				;AN000;
;;										;AN000;
;;   The set of COLOR modules is already at the rigth located when installing	;AN000;
;;   GRAPHICS for the first time. This is true since, the color modules are	;AN000;
;;   linked before the black and white modules. 				;AN000;
;;										;AN000;
;;   Therefore, if we are installing GRAPHICS for the first time and we need	;AN000;
;;   the color modules then, we do not need to relocate any print modules.	;AN000;
;;										;AN000;
;;   When installing GRAPHICS again we first check what is the resident set,	;AN000;
;;   we recopy a new set only if needed.					;AN000;
;;										;AN000;
;; Called By:									;AN000;
;;   GRAPHICS_INSTALL								;AN000;
;;										;AN000;
;; Logic:									;AN000;
;;   IF color printer THEN							;AN000;
;;	SI := Offset of BW_PRINT_MODULES					;AN000;
;;   ELSE									;AN000;
;;	SI := Offset of COLOR_PRINT_MODULES					;AN000;
;;   ENDIF									;AN000;
;;   REP MOVSB		; Copy the set of modules				;AN000;
;;   END_OF_RESIDENT_CODE := end of the set of modules				;AN000;
;;   RETURN									;AN000;
;;										;AN000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;					;AN000;
COPY_PRINT_MODULES  PROC NEAR							;AN000;
	PUSH	AX								;AN000;
	PUSH	BX								;AN000;
	PUSH	CX								;AN000;
	PUSH	SI								;AN000;
	PUSH	DI								;AN000;
	PUSH	ES								;AN000;
										;AN000;
;-------------------------------------------------------------------------------;AN000;
; Determine if we need to relocate the set of print modules, if so, set the	;AN000;
; source address (DS:SI), the destination address (ES:DI) and the number of	;AN000;
; bytes to copy (CX).								;AN000;
;-------------------------------------------------------------------------------;AN000;
   PUSH    CS:RESIDENT_CODE_SEG 	; ES := Segment containing the resident ;AN000;
   POP	   ES				;	 code  (Where to copy modules)	;AN000;
   MOV	   DI,OFFSET PRINT_MODULE_START ; ES:[DI] := Resident print modules	;AN000;
										;AN000;
  .IF <INSTALLED EQ NO> 		; IF not installed			;AN000;
  .THEN 				; THEN, 				;AN000;
					;   We relocate the print modules	;AN000;
					;    at the end of the resident code:	;AN000;
					;     (this is where the color set is)	;AN000;
     .IF <CS:[BP].PRINTER_TYPE EQ BLACK_WHITE> ; IF we don't want the color set ;AN000;
     .THEN				;   THEN,				;AN000;
	MOV NEED_NEW_PRINT_MODULES,YES	;     Say we need new modules		;AN000;
	MOV SI,OFFSET PRINT_BW_APA	;     DS:[SI] := Black and white modules;AN000;
	MOV CX,LEN_OF_BW_MODULES	;     CX      := Length of B&W modules	;AN000;
     .ENDIF				;					;AN000;
										;AN000;
  .ELSE 				; ELSE, (We are already installed)	;AN000;
      MOV     BX,SHARED_DATA_AREA_PTR	;   BX := Offset of Shared Data area	;AN000;
      MOV     AL,ES:[BX].PRINTER_TYPE	;   AL := Type of the resident set	;AN000;
     .IF <AL NE CS:[BP].PRINTER_TYPE>	;   IF resident set is not the one	;AN000;
     .THEN				;   we need THEN,			;AN000;
	MOV NEED_NEW_PRINT_MODULES,YES	;     Say we need a new set.		;AN000;
       .IF <CS:[BP].PRINTER_TYPE EQ COLOR>;   IF its color we need then,	;AN000;
	  MOV SI,OFFSET PRINT_COLOR	;	DS:[SI] := Color set		;AN000;
	  MOV CX,LEN_OF_COLOR_MODULES	;	CX	:= Length of color mod. ;AN000;
       .ELSE				;     ELSE				;AN000;
	  MOV SI,OFFSET PRINT_BW_APA	;	DS:[SI] := B&W set		;AN000;
	  MOV CX,LEN_OF_BW_MODULES	;	CX	:= Length of B&W mod.	;AN000;
       .ENDIF				;     ENDIF we need the color set	;AN000;
     .ENDIF				;   ENDIF we need a new set		;AN000;
  .ENDIF				; ENDIF we are not installed		;AN000;
										;AN000;
										;AN000;
;-------------------------------------------------------------------------------;AN000;
; If needed: Copy the required set of print modules				;AN000;
;-------------------------------------------------------------------------------;AN000;
  .IF <NEED_NEW_PRINT_MODULES EQ YES>						;AN000;
  .THEN 									;AN000;
     CLD			       ; Clear the direction flag		;AN000;
     REP     MOVSB		       ; Copy the set of print modules		;AN000;
  .ENDIF			       ; ENDIF needs to copy the print modules	;AN000;
										;AN000;
;-------------------------------------------------------------------------------;AN000;
; Set END_OF_RESIDENT_CODE pointer to the end of the print modules:		;AN000;
; (Reserve enough space to store the larger set of modules on a 		;AN000;
;  subsequent install)								;AN000;
;-------------------------------------------------------------------------------;AN000;
  .IF <INSTALLED EQ NO> 		; IF first time installed		;AN000;
  .THEN 				; THEN, 				;AN000;
     MOV     CX,LEN_OF_COLOR_MODULES	;   Adjust END_OF_RESIDENT_CODE to	;AN000;
    .IF <CX G LEN_OF_BW_MODULES>	;   contains the larger set of modules. ;AN000;
    .THEN				;					;AN000;
       ADD     END_OF_RESIDENT_CODE,LEN_OF_COLOR_MODULES			;AN000;
    .ELSE									;AN000;
       ADD     END_OF_RESIDENT_CODE,LEN_OF_BW_MODULES				;AN000;
    .ENDIF				;					;AN000;
  .ENDIF									;AN000;
										;AN000;
	POP ES									;AN000;
	POP DI									;AN000;
	POP SI									;AN000;
	POP CX									;AN000;
	POP BX									;AN000;
	POP AX									;AN000;
	RET									;AN000;
NEED_NEW_PRINT_MODULES DB   NO		; True if print modules needed must be	;AN000;
					;  copied over the other set of print	;AN000;
					;   modules				;AN000;
COPY_PRINT_MODULES  ENDP							;AN000;
										;AN002;
PAGE										;AN002;
;===============================================================================;AN002;
;										;AN002;
; PROCEDURE_NAME: RELEASE_ENVIRONMENT						;AN002;
;										;AN002;
; INPUT:  None. 								;AN002;
;										;AN002;
; OUTPUT: Environment vector released.						;AN002;
;										;AN002;
;-------------------------------------------------------------------------------;AN002;
RELEASE_ENVIRONMENT PROC NEAR							;AN002;
	PUSH	AX			; save regs				;AN002;
	PUSH	BX								;AN002;
	PUSH	ES								;AN002;
	MOV	AH,62H			; function for get the PSP segment	;AN002;
	INT	21H			; invoke INT 21h			;AN002;
	MOV	ES,BX			; BX contains PSP segment - put in ES	;AN002;
	MOV	BX,WORD PTR ES:[2CH]	; get segment of environmental vector	;AN002;
	MOV	ES,BX			; place segment in ES for Free Memory	;AN002;
	MOV	AH,49H			; Free Allocated Memory function call	;AN002;
	INT	21H			; invoke INT 21h			;AN002;
	POP	ES			; restore regs				;AN002;
	POP	BX								;AN002;
	POP	AX								;AN002;
	RET									;AN002;
RELEASE_ENVIRONMENT ENDP							;AN002;
										;AN000;
PAGE										;AN000;
;===============================================================================;AN000;
;										;AN000;
; PROCEDURE_NAME: DISP_ERROR							;AN000;
;										;AN000;
; INPUT:  AX := GRAPHICS message number (documented in GRMSG.EQU)		;AN000;
;	  CX := Number of substitutions (Needed by SYSDISPMSG)			;AN000;
;	  DS:[SI] := Substitution list (needed only if CX <> 0) 		;AN000;
;										;AN000;
; OUTPUT: Error message is displayed on STANDARD ERROR OUTPUT (STDERR)		;AN000;
;										;AN000;
;-------------------------------------------------------------------------------;AN000;
DISP_ERROR    PROC   NEAR							;AN000;
	PUSH	BX								;AN000;
	PUSH	DI								;AN000;
	PUSH	SI								;AN000;
	PUSH	BP								;AN000;
										;AN000;
	MOV	BX,ERROR_DEVICE    ; Issue message to standard error		;AN000;
	XOR	DL,DL		   ; No input					;AN000;
	MOV	DH,UTILITY_MSG_CLASS;It's one of our messages                   ;AN000;
	CALL	SYSDISPMSG	   ; display error message			;AN000;
										;AN000;
	POP	BP								;AN000;
	POP	SI								;AN000;
	POP	DI								;AN000;
	POP	BX								;AN000;
	RET									;AN000;
DISP_ERROR    ENDP								;AN000;

include msgdcl.inc										;AN000;
										;AN000;
CODE   ENDS									;AN000;
       END									;AN000;