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