From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/CMD/GRAPHICS/GRCOMMON.ASM | 858 +++++++++++++++++++++++++++++++++++++ 1 file changed, 858 insertions(+) create mode 100644 v4.0/src/CMD/GRAPHICS/GRCOMMON.ASM (limited to 'v4.0/src/CMD/GRAPHICS/GRCOMMON.ASM') diff --git a/v4.0/src/CMD/GRAPHICS/GRCOMMON.ASM b/v4.0/src/CMD/GRAPHICS/GRCOMMON.ASM new file mode 100644 index 0000000..56d1b08 --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRCOMMON.ASM @@ -0,0 +1,858 @@ + PAGE ,132 ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; +;; DOS - GRAPHICS Command +;; (c) Copyright 1988 Microsoft +;; ;AN000; +;; File Name: GRCOMMON.ASM ;AN000; +;; ---------- ;AN000; +;; ;AN000; +;; Description: ;AN000; +;; ------------ ;AN000; +;; ;AN000; +;; This file contains the modules common to the Print Screen ;AN000; +;; process of GRAPHICS.COM. ;AN000; +;; This file is included by both set of Print modules. ;AN000; +;; ;AN000; +;; This file MUST BE COMPILED WITH EACH SET OF MODULES since, ;AN000; +;; one set is relocated in memory at installation time; all ;AN000; +;; references to the common procedures must be resolved from ;AN000; +;; within each set of print modules. ;AN000; +;; ;AN000; +;; The set of common modules is relocated in memory along with ;AN000; +;; the selected set of print modules. ;AN000; +;; ;AN000; +;; Documentation Reference: ;AN000; +;; ------------------------ ;AN000; +;; OASIS High Level Design ;AN000; +;; OASIS GRAPHICS I1 Overview ;AN000; +;; ;AN000; +;; Procedures Contained in This File: ;AN000; +;; ---------------------------------- ;AN000; +;; READ_DOT ;AN000; +;; LOC_MODE_PRT_INFO ;AN000; +;; STORE_BOX ;AN000; +;; PRINT_BUFFER ;AN000; +;; GET_SCREEN_INFO ;AN000; +;; SETUP_PRT ;AN000; +;; RESTORE_PRT ;AN000; +;; NEW_PRT_LINE ;AN000; +;; PRINT_BYTE ;AN000; +;; DET_CUR_SCAN_LNE_LENGTH ;AN000; +;; ;AN000; +;; Include Files Required: ;AN000; +;; ----------------------- ;AN000; +;; none ;AN000; +;; ;AN000; +;; External Procedure References: ;AN000; +;; ------------------------------ ;AN000; +;; FROM FILE GRCTRL.ASM: ;AN000; +;; PRT_SCR - Main module for printing the screen. ;AN000; +;; FROM FILE GRBWPRT.ASM: ;AN000; +;; PRT_BW_APA - Main module for printing on BW printer. ;AN000; +;; FROM FILE GRCOLPRT.ASM: ;AN000; +;; PRINT_COLOR - Main module for printing on COLOR printer. ;AN000; +;; ;AN000; +;; Linkage Instructions: ;AN000; +;; -------------------- ;AN000; +;; ;AN000; +;; This file is included by both GRBWPRT.ASM and GRCOLPRT.ASM and is ;AN000; +;; compiled with each of them. However, only one copy is made resident. ;AN000; +;; ;AN000; +;; Change History: ;AN000; +;; --------------- ;AN000; +;; ;AN000; +;; ;AN000; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; + ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; LOC_MODE_PRT_INFO: LOCATE DISPLAYMODE PRINTER INFO. FOR THE CURRENT ;AN000; +; MODE ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: BP = Offset of the shared data area ;AN000; +; CUR_MODE = Current video mode ;AN000; +; ;AN000; +; OUTPUT: CUR_MODE_PTR = Absolute Offset of the ;AN000; +; current DISPLAYMODE INFO record. ;AN000; +; ;AN000; +; ERROR_CODE = DISPLAYMODE_INFO_NOT_FOUND if not found. ;AN000; +; ;AN000; +; CALLED BY: PRINT_COLOR ;AN000; +; PRINT_BW_APA ;AN000; +; ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: DISPLAYMODE_PTR is pointing to the first DISPLAYMODE ;AN000; +; INFO record within the Shared Data Area. ;AN000; +; ;AN000; +; This (chained) list of DISPLAYMODE records is scanned until the record ;AN000; +; for the current mode is found. ;AN000; +; ;AN000; +; Note: All pointers in the DISPLAYMODE records are relative to the beginning ;AN000; +; of the shared data area. Therefore, we must add the offset of the ;AN000; +; shared data area (in BP) in order to access the data these pointers ;AN000; +; are referencing. ;AN000; +; ;AN000; +; The CUR_MODE_PTR is relative to the segment and references the ;AN000; +; DISPLAYMODE record for the video mode currently set at print screen ;AN000; +; time. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; FOUND := FALSE ;AN000; +; DO UNTIL FOUND OR END_OF_LIST ;AN000; +; Get a display mode information record ;AN000; +; IF record.DISP_MODE = CUR_MODE ;AN000; +; THEN FOUND := TRUE ;AN000; +; ELSE ;AN000; +; CUR_MODE_PTR := record.NEXT_DISP_MODE ;AN000; +; ;AN000; +; ;AN000; + ;AN000; +LOC_MODE_PRT_INFO PROC NEAR ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + PUSH SI ;AN000; + ;AN000; + MOV BX,DS:[BP].DISPLAYMODE_PTR ; [BX] := Current DISPLAYMODE ;AN000; + ADD BX,BP ; record ;AN000; + MOV DL,CUR_MODE ; DL := Current mode ;AN000; + ;AN000; +SCAN_1_DISPLAYMODE_RECORD: ;AN000; + MOV SI,[BX].DISP_MODE_LIST_PTR ; [SI] : First mode covered ;AN000; + ADD SI,BP ; by this DISPLAYMODE record ;AN000; + MOV CL,[BX].NUM_DISP_MODE ; Scan each mode in the list ;AN000; + XOR CH,CH ;AN000; +SCAN_LIST_OF_MODES: ;AN000; + CMP CS:[SI],DL ; FOUND ? ;AN000; + JE FOUND ;AN000; + INC SI ; NO, get next mode in ;AN000; + LOOP SCAN_LIST_OF_MODES ; DISPLAYMODE record ;AN000; + ;AN000; + CMP [BX].NEXT_DISP_MODE,-1 ; END OF DISPLAYMODE LIST ? ;AN000; + JE NOT_FOUND ; Yes, this mode not supported ;AN000; +NEXT_RECORD: ; No, ;AN000; + MOV BX,[BX].NEXT_DISP_MODE ; [BX] := Next record ;AN000; + ADD BX,BP ; ;AN000; + JMP SHORT SCAN_1_DISPLAYMODE_RECORD ;AN000; + ;AN000; +FOUND: ; Found: ;AN000; + MOV CUR_MODE_PTR,BX ; Update pointer to current ;AN000; + JMP SHORT LOC_MODE_PRT_INFO_END ; DISPLAYMODE record. ;AN000; + ;AN000; +NOT_FOUND: ; Not found: ;AN000; + MOV ERROR_CODE,DISPLAYMODE_INFO_NOT_FOUND ; Return error condition ;AN000; + ;AN000; +LOC_MODE_PRT_INFO_END: ;AN000; + POP SI ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + RET ;AN000; +LOC_MODE_PRT_INFO ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; STORE_BOX : STORE ONE BOX IN THE PRINT BUFFER. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: SI = OFFSET OF THE BOX TO BE PRINTED ;AN000; +; BOX_W = BOX WIDTH IN BITS ;AN000; +; BOX_H = BOX HEIGHT IN BITS ;AN000; +; ;AN000; +; OUTPUT: PRT_BUF = THE PRINT BUFFER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: The print buffer is first shifted left in order to make ;AN000; +; room for the new box (Note: the MSB's are lost; they are assumed to ;AN000; +; have been printed), then the box is inserted in the low-order bits of ;AN000; +; the printer buffer. ;AN000; +; ;AN000; +PAGE ;AN000; +; EXAMPLE ;AN000; +; ------- ;AN000; +; BEFORE: AFTER: ;AN000; +; ;AN000; +; BOX: 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; 0 0 0 ;AN000; +; b1 b2 b3 ;AN000; +; b4 b5 b6 ;AN000; +; ;AN000; +; PRT_BUF: byte1 byte2 byte3 PRT_BUF: byte1 byte2 byte3 ;AN000; +; 0 1 0 1 1 1 ;AN000; +; 1 0 1 1 1 1 ;AN000; +; 1 1 1 1 1 1 ;AN000; +; 1 1 1 1 1 1 ;AN000; +; 1 1 1 1 1 1 ;AN000; +; 1 1 1 1 1 1 ;AN000; +; 1 1 1 b1 b2 b3 ;AN000; +; LSB --> 1 1 1 b4 b5 b6 ;AN000; +; ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; FOR each byte of the buffer (BOX_W) ;AN000; +; BEGIN ;AN000; +; Make room for the box to be inserted ;AN000; +; Insert the box ;AN000; +; END ;AN000; +; ;AN000; +STORE_BOX PROC NEAR ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DI ;AN000; + ;AN000; + MOV DI,OFFSET PRT_BUF ; DI := Offset of the Print buffer ;AN000; + XOR BX,BX ; BX := Byte index number ;AN000; + ;AN000; + MOV CL,BOX_H ; CL := Number of BITS to be shifted ;AN000; +; FOR each column (byte) of the box to be stored in the buffer: ;AN000; +STORE_1_BYTE: ;AN000; + SHL BYTE PTR [BX][DI],CL ; Make room for the bits to be inserted ;AN000; + MOV CH,[BX][SI] ; CH := column of the box to be inserted;AN000; + OR [BX][DI],CH ; Insert the box column in the buffer ;AN000; + INC BL ; Get next column (byte) of the box ;AN000; + CMP BL,BOX_W ; All columns (bytes) of box stored ? ;AN000; + JL STORE_1_BYTE ; No, store next one. ;AN000; + ;AN000; +STORE_BOX_END: ;AN000; + POP DI ;AN000; + POP CX ;AN000; + POP BX ;AN000; + RET ;AN000; +STORE_BOX ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PRINT_BUFFER : PRINT THE BUFFER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: PRT_BUF = BYTES TO BE PRINTED ;AN000; +; BOW_W = BOX WIDTH ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Prints BOX_W bytes. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; DO for each column in one pattern ;AN000; +; BEGIN ;AN000; +; Print one byte from the buffer ;AN000; +; END ;AN000; +; ;AN000; +PRINT_BUFFER PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + ;AN000; + MOV BX,OFFSET PRT_BUF ;AN000; + XOR CX,CX ;AN000; + MOV CL,BOX_W ;AN000; +PRINT_1_BUF_COLUMN: ;AN000; + MOV AL,[BX] ; Print one byte ;AN000; + CALL PRINT_BYTE ;AN000; + JC PRINT_BUFFER_END; If printer error, quit the loop ;AN000; + INC BX ; Get next byte ;AN000; + LOOP PRINT_1_BUF_COLUMN ;AN000; +PRINT_BUFFER_END: ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +PRINT_BUFFER ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; GET_SCREEN_INFO : GET INFORMATION ABOUT HOW TO READ THE SCREEN. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: SCREEN_HEIGHT = Number of pixel rows on the screen ;AN000; +; SCREEN_WIDTH = Number of pixel columns on screen ;AN000; +; CUR_MODE_PTR = Offset of the current DISPLAYMODE info rec. ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; SCAN_LINE_MAX_LENGTH = Maximum length of Screen scan line. ;AN000; +; NB_SCAN_LINES = Number of SCAN LINES on the screen ;AN000; +; CUR_ROW,CUR_COLUMN = Coordinates of the first pixel to be ;AN000; +; read on the screen ;AN000; +; NB_BOXES_PER_PRT_BUF = Number of boxes fitting in the Print ;AN000; +; buffer ;AN000; +; ;AN000; +; CALLED BY: PRINT_COLOR ;AN000; +; PRT_BW_APA ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: ;AN000; +; ;AN000; +; 1) Determine where to start reading the screen. ;AN000; +; For non-rotated printing, it should start with the top-left ;AN000; +; corner pixel. ;AN000; +; For rotated printing, it should start with the low-left corner ;AN000; +; pixel. ;AN000; +; ;AN000; +; 2) Determine the length of a scan line. ;AN000; +; For non-rotated printing, it is the WIDTH of the screen. ;AN000; +; For rotated printing, it is the HEIGHT of the screen. ;AN000; +; ;AN000; +; 3) Determine the number of scan lines on the screen. ;AN000; +; For non-rotated printing, it is the HEIGHT of the screen divided ;AN000; +; by the number of boxes fitting in the print buffer. ;AN000; +; For rotated printing, it is the WIDTH of the screen divided by ;AN000; +; the number of boxes fitting in the print buffer. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; CUR_COLUMN := 0 ;AN000; +; IF printing is sideways ;AN000; +; THEN ;AN000; +; CUR_ROW := SCREEN_HEIGHT - 1 ; Low-left pixel ;AN000; +; SCAN_LINE_MAX_LENGTH := SCREEN_HEIGHT ;AN000; +; NB_SCAN_LINES := SCREEN_WIDTH / NB_BOXES_PER_PRT_BUF ;AN000; +; ELSE ;AN000; +; CUR_ROW := 0 ; Top-left pixel ;AN000; +; SCAN_LINE_MAX_LENGTH := SCREEN_WIDTH ;AN000; +; NB_SCAN_LINES := SCREEN_HEIGHT / NB_BOXES_PER_PRT_BUF ;AN000; +; ;AN000; +; ;AN000; +GET_SCREEN_INFO PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ; Used for DIV ;AN000; + PUSH DX ; Used for DIV ;AN000; + ;AN000; + MOV BX,CUR_MODE_PTR ; BX := Offset DISPLAYMODE info record ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Calculate how many printer boxes fit in the print buffer: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AX,8 ; Num := 8 bits / Box heigth ;AN000; + MOV DL,[BX].BOX_HEIGHT ;AN000; + DIV DL ;AN000; + MOV NB_BOXES_PER_PRT_BUF,AL ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Determine where to start reading the screen: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV CUR_COLUMN,0 ; Reading always start from left of scr ;AN000; +.IF <[BX].PRINT_OPTIONS EQ ROTATE> ;AN000; +.THEN ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Printing is sideways; screen must be read starting in low-left corner. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AX,SCREEN_HEIGHT ;AN000; + MOV SCAN_LINE_MAX_LENGTH,AX ; Scan line length := screen height ;AN000; + DEC AX ;AN000; + MOV CUR_ROW,AX ; First row := screen height - 1 ;AN000; + ;AN000; +;-------Calculate the number of scan lines: ;AN000; + MOV AX,SCREEN_WIDTH ; DX AX = Screen width ;AN000; + CWD ; ;AN000; + XOR BX,BX ; BX = Number of boxes per print buf ;AN000; + MOV BL,NB_BOXES_PER_PRT_BUF ; ;AN000; + DIV BX ; Screen width / number boxes per buff ;AN000; + MOV NB_SCAN_LINES,AX ; Number of scan lines := result ;AN000; +.ELSE ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Printing is not sideways; screen must be read starting in top-left corner ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AX,SCREEN_WIDTH ;AN000; + MOV SCAN_LINE_MAX_LENGTH,AX ; Scan line length := screen width ;AN000; + MOV CUR_ROW,0 ; First row := 0 ;AN000; + ;AN000; +;-------Calculate the number of scan lines: ;AN000; + MOV AX,SCREEN_HEIGHT ; DX AX = Screen height ;AN000; + CWD ; ;AN000; + XOR BX,BX ; BX = Number of boxes per print buff ;AN000; + MOV BL,NB_BOXES_PER_PRT_BUF ; ;AN000; + DIV BX ; Screen height/number boxes per buff. ;AN000; + MOV NB_SCAN_LINES,AX ; Number of scan lines := result ;AN000; +.ENDIF ;AN000; + POP DX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +GET_SCREEN_INFO ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; DET_CUR_SCAN_LNE_LENGTH : Determine where is the last non-blank "scan line ;AN000; +; column" on the current scan line. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_ROW, ;AN000; +; CUR_COLUMN = Coordinates of the top pixel of the current ;AN000; +; scan line. ;AN000; +; XLT_TAB = Color translation table ;AN000; +; ;AN000; +; OUTPUT: CUR_SCAN_LNE_LENGTH = Number of "columns" of pixels from the ;AN000; +; beginning of the scan line up to ;AN000; +; the last non-blank pixel. ;AN000; +; ;AN000; +; DATA SCREEN_WIDTH, ;AN000; +; REFERENCED: SCREEN_HEIGHT = Dimensions of the screen in pels ;AN000; +; SCAN_LINE_MAX_LENGTH= Maximum length of the scan line ;AN000; +; ROTATE_SW = ON if printing is sideways ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Determine where is the last non-blank "column" by reading ;AN000; +; the scan line backwards, one column at a time. ;AN000; +; ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; ; Obtain coordinates for the top pixel of the last column on the current ;AN000; +; ; scan line: ;AN000; +; IF printing is sideways ;AN000; +; THEN ;AN000; +; CUR_ROW := 0 ;AN000; +; ELSE ;AN000; +; CUR_COLUMN := SCREEN_WIDTH - 1 ;AN000; +; ;AN000; +; CUR_SCAN_LNE_LENGTH := SCAN_LINE_MAX_LENGTH ;AN000; +; ; Read a column of pixels on the scan line until a non-blank is found: ;AN000; +; For each column on the screen ;AN000; +; CALL FILL_BUFF ;AN000; +; ; Check if PRT_BUF is empty ;AN000; +; IF buffer is empty ;AN000; +; THEN DEC CUR_SCAN_LNE_LENGTH ;AN000; +; ; Get next column ;AN000; +; IF printing sideways THEN DEC CUR_ROW ;AN000; +; ELSE DEC CUR_COLUMN ;AN000; +; ELSE quit the loop ;AN000; +; ;AN000; +DET_CUR_SCAN_LNE_LENGTH PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + PUSH SI ;AN000; + PUSH DI ;AN000; + PUSH CUR_COLUMN ;AN000; + PUSH CUR_ROW ;AN000; + ;AN000; + MOV BX,OFFSET XLT_TAB ; BX := Offset of XLT_TAB ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Obtain coordinates of the top pixel for the last column of the current ;AN000; +; scan line: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + .IF ; If printing sideways ;AN000; + .THEN ; then, ;AN000; + MOV CUR_ROW,0 ; CUR_ROW := 0 ;AN000; + .ELSE ; else, ;AN000; + MOV CX,SCREEN_WIDTH ; CUR_COLUMN := SCREEN_WIDTH - 1 ;AN000; + DEC CX ; ;AN000; + MOV CUR_COLUMN,CX ; ;AN000; + .ENDIF ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; Read the scan line backwards "column" by "column" until a non-blank is found: ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV CX,SCAN_LINE_MAX_LENGTH ; CX := current length ;AN000; +; ;AN000; +;-------For each "column" ;AN000; +CHECK_1_COLUMN: ;AN000; + MOV SI,CUR_ROW ; Save coordinates of the column ;AN000; + MOV DI,CUR_COLUMN ; in SI, DI ;AN000; + XOR DL,DL ; DL := Number of pixels verified in ;AN000; + ; one "column" ;AN000; +; ;AN000; +;-------For each pixel within that "column" ;AN000; +CHECK_1_PIXEL: ;AN000; + CALL READ_DOT ; AL := Index into translation table ;AN000; + XLAT XLT_TAB ; AL := Band mask or Intensity ;AN000; + ;AN000; +;-------Check if pixel will map to an empty box: ;AN000; + .IF ; If BLACK AND WHITE printer ;AN000; + .THEN ; then, check for intensity of white ;AN000; + CMP AL,WHITE_INT ; If curent pixel not blank ;AN000; + JNE DET_LENGTH_END ; THEN, LEAVE THE LOOP ;AN000; + .ELSE ; else, COLOR printer ;AN000; + OR AL,AL ; IF Band mask not blank ;AN000; + JNZ DET_LENGTH_END ; THEN, LEAVE THE LOOP ;AN000; + .ENDIF ;AN000; + ;AN000; +;-------All pixels so far on this "column" are blank, get next pixel: ;AN000; + .IF ; If printing sideways ;AN000; + .THEN ; ;AN000; + INC CUR_COLUMN ; then, increment column number ;AN000; + .ELSE ; ;AN000; + INC CUR_ROW ; else, increment row number ;AN000; + .ENDIF ; ;AN000; + INC DL ; One more pixel checked ;AN000; + CMP DL,NB_BOXES_PER_PRT_BUF ; All pixels for that column done ? ;AN000; + JL CHECK_1_PIXEL ; No, check next one. ;AN000; + ;AN000; +;-------Nothing to print for this column, get next column ;AN000; + .IF ; If printing sideways ;AN000; + .THEN ; then, ;AN000; + MOV CUR_COLUMN,DI ; Restore column number ;AN000; + INC CUR_ROW ; Get next row ;AN000; + .ELSE ; else, ;AN000; + MOV CUR_ROW,SI ; Restore row number ;AN000; + DEC CUR_COLUMN ; Get next column ;AN000; + .ENDIF ; ;AN000; + LOOP CHECK_1_COLUMN ; CX (length) := CX - 1 ;AN000; + ;AN000; +DET_LENGTH_END: ;AN000; + MOV CUR_SCAN_LNE_LENGTH,CX ; Get current length ;AN000; + ;AN000; + POP CUR_ROW ;AN000; + POP CUR_COLUMN ;AN000; + POP DI ;AN000; + POP SI ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +DET_CUR_SCAN_LNE_LENGTH ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; SETUP_PRT : SET UP THE PRINTER FOR PRINTING IN GRAPHIC MODE ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_MODE_PTR = Offset of the DISPLAYMODE information ;AN000; +; record for the current mode ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +; CALLED BY: PRINT_COLOR ;AN000; +; PRT_BW_APA ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Extract the SETUP escape sequence from the DISPLAYMODE ;AN000; +; information record; Send this escape sequence to the printer. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Number of bytes to print := CUR_MODE_PTR.NUM_SETUP_ESC ;AN000; +; ;AN000; +; Get the escape sequence: ;AN000; +; SI := CUR_MODE_PTR.SETUP_ESC_PTR ;AN000; +; ;AN000; +; FOR each byte to be printed ;AN000; +; PRINT_BYTE [SI] ; Send the byte to the printer ;AN000; +; INC SI ; Get the next byte ;AN000; +; ;AN000; +SETUP_PRT PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + ;AN000; + MOV BX,CUR_MODE_PTR ; BX := Displaymode info record. ;AN000; + ;AN000; + XOR CX,CX ; CX := Number of bytes to print ;AN000; + MOV CL,[BX].NUM_SETUP_ESC ; ;AN000; +.IF ; If there is at least one ;AN000; +.THEN ; byte to be printed: ;AN000; + MOV BX,[BX].SETUP_ESC_PTR ; BX := Offset sequence to send ;AN000; + ADD BX,BP ;AN000; + ;AN000; +SEND_1_SETUP_BYTE: ;AN000; + MOV AL,[BX] ; AL := byte to print ;AN000; + CALL PRINT_BYTE ; Send it to the printer ;AN000; + JC SETUP_PRT_END ; If printer error, quit the loop ;AN000; + INC BX ; Get next byte ;AN000; + LOOP SEND_1_SETUP_BYTE ;AN000; +.ENDIF ;AN000; +SETUP_PRT_END: ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +SETUP_PRT ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; RESTORE_PRT : RESTORE THE PRINTER TO ITS INITIAL STATUS ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_MODE_PTR = Offset of the DISPLAYMODE information ;AN000; +; record for the current mode ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +; CALLED BY: PRINT_COLOR ;AN000; +; PRT_BW_APA ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Extract the RESTORE escape sequence from the DISPLAYMODE ;AN000; +; information record; Send this escape sequence to the printer. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Number of bytes to print := CUR_MODE_PTR.NUM_RESTORE_ESC ;AN000; +; ;AN000; +; Get the escape sequence: ;AN000; +; SI := CUR_MODE_PTR.RESTORE_ESC_PTR ;AN000; +; FOR each byte to be printed ;AN000; +; PRINT_BYTE [SI] ; Send the byte to the printer ;AN000; +; INC SI ; Get the next byte ;AN000; +; ;AN000; +RESTORE_PRT PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + ;AN000; + MOV BX,CUR_MODE_PTR ; BX := Displaymode info record. ;AN000; + ;AN000; + XOR CX,CX ; CX := Number of bytes to print ;AN000; + MOV CL,[BX].NUM_RESTORE_ESC ;AN000; +.IF ; If there is at least one ;AN000; +.THEN ; byte to be printed: ;AN000; + MOV BX,[BX].RESTORE_ESC_PTR ; BX := Offset sequence to send ;AN000; + ADD BX,BP ;AN000; + ;AN000; +SEND_1_RESTORE_BYTE: ;AN000; + MOV AL,[BX] ; AL := byte to print ;AN000; + CALL PRINT_BYTE ; Send it to the printer ;AN000; + JC RESTORE_PRT_END ; If printer error, quit the loop ;AN000; + INC BX ; Get next byte ;AN000; + LOOP SEND_1_RESTORE_BYTE ;AN000; +.ENDIF ;AN000; +RESTORE_PRT_END: ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +RESTORE_PRT ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; NEW_PRT_LINE : INITIALIZE THE PRINTER FOR A GRAPHIC LINE ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_MODE_PTR = Offset of the DISPLAYMODE information ;AN000; +; record for the current mode ;AN000; +; CUR_SCAN_LNE_LENGTH = Number of bytes to send to the printer. ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ;AN000; +; CALLED BY: PRINT_BAND ;AN000; +; PRT_BW_APA ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Extract the GRAPHICS escape sequence from the DISPLAYMODE ;AN000; +; information record; Send this escape sequence to the printer. ;AN000; +; Then, send the number of bytes that will follow. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Number of bytes to print := CUR_MODE_PTR.NUM_GRAPHICS_ESC ;AN000; +; ;AN000; +; Get the escape sequence: ;AN000; +; Set up the 2 bytes containing the number of bytes to send in this sequence. ;AN000; +; SI := CUR_MODE_PTR.GRAPHICS_ESC_PTR ;AN000; +; ;AN000; +; FOR each byte to be printed ;AN000; +; PRINT_BYTE [SI] ; Send the byte to the printer ;AN000; +; INC SI ; Get the next byte ;AN000; +; ;AN000; +; Send the byte count ;AN000; +; ;AN000; + ;AN000; +NEW_PRT_LINE PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH BX ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + PUSH DI ;AN000; + ;AN000; + MOV BX,CUR_MODE_PTR ; BX := Displaymode info record. ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Set up the 2 bytes containing the number of bytes to send in the GRAPHICS seq.;AN000; +; NOTE: number of bytes to send is "CUR_SCAN_LNE_LENGTH * BOX_W" ;AN000; +;-------------------------------------------------------------------------------;AN000; + MOV AL,BOX_W ; cur_scan_lne_length * ;AN000; + CBW ; printer box width = nb bytes to send;AN000; + MUL CUR_SCAN_LNE_LENGTH ; (result in DX AX) ;AN000; + ; ;AN000; +;-------AX := Number of bytes to print ;AN000; + MOV DI,[BX].LOW_BYT_COUNT_PTR; DI := Offset of LOW byte of ;AN000; + ADD DI,BP ; byte count ;AN000; + MOV [DI],AL ; Store low byte ;AN000; + MOV DI,[BX].HGH_BYT_COUNT_PTR; DI := Offset of HIGH byte of ;AN000; + ADD DI,BP ; byte count ;AN000; + MOV [DI],AH ; Store high byte ;AN000; + ;AN000; +;-------------------------------------------------------------------------------;AN000; +; Send the GRAPHICS escape sequence to the printer: ;AN000; +;-------------------------------------------------------------------------------;AN000; + XOR CX,CX ; CX := Length of the escape seq;AN000; + MOV CL,[BX].NUM_GRAPHICS_ESC ;AN000; + MOV BX,[BX].GRAPHICS_ESC_PTR ; BX := Offset sequence to send ;AN000; + ADD BX,BP ;AN000; + ;AN000; +SEND_1_GRAPHICS_BYTE: ;AN000; + MOV AL,[BX] ; AL := byte to print ;AN000; + CALL PRINT_BYTE ; Send it to the printer ;AN000; + JC NEW_PRT_LINE_ENDP ; If printer error, quit the loop ;AN000; + INC BX ; Get next byte ;AN000; + LOOP SEND_1_GRAPHICS_BYTE ;AN000; + ;AN000; +NEW_PRT_LINE_ENDP: ;AN000; + POP DI ;AN000; + POP DX ;AN000; + POP CX ;AN000; + POP BX ;AN000; + POP AX ;AN000; + RET ;AN000; +NEW_PRT_LINE ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; PRINT_BYTE : SEND A BYTE TO THE PRINTER AT LPT1 ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: AL = Byte to be printed ;AN000; +; ;AN000; +; OUTPUT: PRINTER ;AN000; +; ERROR_CODE = PRINTER_ERROR if an error is detected. ;AN000; +; Carry flag is set in case of error. ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +PRINT_BYTE PROC NEAR ;AN000; + PUSH AX ;AN000; + PUSH DX ;AN000; + ;AN000; + MOV DX,0000 ; PRINTER NUMBER ;AN000; + MOV AH,00 ; REQUEST PRINT ;AN000; + INT 17H ; CALL BIOS : SEND THE CHARACTER ;AN000; + ;AN000; + AND AH,00101001B ; Test error code returned in AH for ;AN000; + ; "Out of paper", "I/O error" and "Time-out". ;AN000; + JNZ PRINT_BYTE_ERROR; Set the error code if error ;AN000; + JMP SHORT PRINT_BYTE_END ; else, return normally ;AN000; +PRINT_BYTE_ERROR: ;AN000; + MOV ERROR_CODE,PRINTER_ERROR ;AN000; + STC ; Set the carry flag to indicate ERROR ;AN000; +PRINT_BYTE_END: ;AN000; + POP DX ;AN000; + POP AX ;AN000; + RET ;AN000; +PRINT_BYTE ENDP ;AN000; +PAGE ;AN000; +;===============================================================================;AN000; +; ;AN000; +; READ_DOT: READ A PIXEL - RETURN A COLOR TRANSLATION TABLE INDEX ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; INPUT: CUR_MODE = Current video mode. ;AN000; +; CUR_ROW, ;AN000; +; CUR_COLUMN = Coordinates of the pixel to be read. ;AN000; +; CUR_PAGE = Active page number ;AN000; +; ;AN000; +; OUTPUT: AL = Index into COLOR TRANSLATION TABLE. ;AN000; +; ;AN000; +; DEPENDENCIES : COLOR TRANSLATION TABLE entries must be bytes ;AN000; +; ;AN000; +; ;AN000; +;-------------------------------------------------------------------------------;AN000; +; ;AN000; +; DESCRIPTION: Use VIDEO BIOS INTERRUPT 10H "READ DOT CALL". ;AN000; +; ;AN000; +; Depending on the video hardware, the dot returned by BIOS has ;AN000; +; different meanings. ;AN000; +; With an EGA it is an index into the Palette registers, ;AN000; +; With a CGA it is a number from 0 to 3, mapping to a specific color ;AN000; +; depending on the background color and the color palette currently ;AN000; +; selected. ;AN000; +; ;AN000; +; The Color Translation table has been set up to hold the correct color ;AN000; +; mapping for any "dot" in any mode. Therefore, the dot number returned ;AN000; +; by INT 10H can be used with any mode as a direct index within that ;AN000; +; table. ;AN000; +; ;AN000; +; With APA Monochrome mode 0FH there are 4 different dots: white, ;AN000; +; blinking white, high-intensity white, and black. ;AN000; +; ;AN000; +; For mode 0FH, the dot returned by interrupt 10 "read dot" call is a byte ;AN000; +; where only bits 0 and 2 are significant. These 2 bits must be appended ;AN000; +; together in order to obtain a binary number (from 0 to 3) that will be used ;AN000; +; as an index in the Color Translation table. ;AN000; +; ;AN000; +; For mode 11H, the dot is either 0 (for background color) or 7 (for the ;AN000; +; foreground color) only the LSB is returned. That is, we return either ;AN000; +; 0 or 1. ;AN000; +; ;AN000; +; LOGIC: ;AN000; +; ;AN000; +; Call VIDEO BIOS "READ DOT" ;AN000; +; IF CUR_MODE = 0FH ;AN000; +; THEN ;AN000; +; Append bits 1 and 3. ;AN000; +; IF CUR_MODE = 11H ;AN000; +; THEN ;AN000; +; Wipe out bits 1 and 2. ;AN000; +; ;AN000; +READ_DOT PROC NEAR ;AN000; + PUSH BX ; Save registers ;AN000; + PUSH CX ;AN000; + PUSH DX ;AN000; + ;AN000; + MOV BH,CUR_PAGE ;AN000; + MOV DX,CUR_ROW ;AN000; + MOV CX,CUR_COLUMN ;AN000; + MOV AH,READ_DOT_CALL ;AN000; + INT 10H ; Call BIOS: AL <-- Dot read ;AN000; + ;AN000; + CMP CUR_MODE,0FH ; Is it Mode 0fH ? ;AN000; + JNE MODE_11H? ; No, look for mode 11h. ;AN000; +;-------Mode 0Fh is the current mode: ;AN000; +;-------Convert bits 2 and 0 into a 2 bit number: ;AN000; + MOV BL,AL ; BL := AL = "Pixel read" ;AN000; + AND BL,00000100B ; Wipe off all bits but bit 2 in BL ;AN000; + AND AL,00000001B ; Wipe off all bits but bit 0 in AL ;AN000; + SHR BL,1 ; Move bit 2 to bit 1 in BL ;AN000; + OR AL,BL ; Append bit 1 and bit 0 ;AN000; + JMP SHORT READ_DOT_END ; Quit. ;AN000; + ;AN000; +MODE_11H?: ;AN000; + CMP CUR_MODE,11H ; Is it Mode 0fH ? ;AN000; + JNE READ_DOT_END ; No, quit ;AN000; + ;AN000; +;-------Mode 11H is the current mode: ;AN000; + AND AL,00000001B ; Keep only the Least significant bit ;AN000; + ;AN000; +READ_DOT_END: ;AN000; + POP DX ; Restore registers ;AN000; + POP CX ;AN000; + POP BX ;AN000; + RET ;AN000; +READ_DOT ENDP ;AN000; -- cgit v1.2.3