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 ;; Identify ourself to Message retriever.;AN000; ;; Include messages ;AN000; MSG_SERVICES ;; ;AN000; MSG_SERVICES ;; ;AN000; MSG_SERVICES ;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 ; 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 > ; 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 ; 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 ; 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 AND ;AN000; .IF ;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 ; 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 ; 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 ;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 ; 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 ; 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 < EQ 0> AND ; IF the dynamic save are pointer is ;AN000; .IF < 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 < 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 ; 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 ; 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 ; 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 ; 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 ;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 ; IF first time installed ;AN000; .THEN ; THEN, ;AN000; MOV CX,LEN_OF_COLOR_MODULES ; Adjust END_OF_RESIDENT_CODE to ;AN000; .IF ; 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;