2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000;
3 ;; DOS - GRAPHICS Command
4 ;; (c) Copyright 1988 Microsoft
6 ;; File Name: GRCOMMON.ASM ;AN000;
9 ;; Description: ;AN000;
10 ;; ------------ ;AN000;
12 ;; This file contains the modules common to the Print Screen ;AN000;
13 ;; process of GRAPHICS.COM. ;AN000;
14 ;; This file is included by both set of Print modules. ;AN000;
16 ;; This file MUST BE COMPILED WITH EACH SET OF MODULES since, ;AN000;
17 ;; one set is relocated in memory at installation time; all ;AN000;
18 ;; references to the common procedures must be resolved from ;AN000;
19 ;; within each set of print modules. ;AN000;
21 ;; The set of common modules is relocated in memory along with ;AN000;
22 ;; the selected set of print modules. ;AN000;
24 ;; Documentation Reference: ;AN000;
25 ;; ------------------------ ;AN000;
26 ;; OASIS High Level Design ;AN000;
27 ;; OASIS GRAPHICS I1 Overview ;AN000;
29 ;; Procedures Contained in This File: ;AN000;
30 ;; ---------------------------------- ;AN000;
32 ;; LOC_MODE_PRT_INFO ;AN000;
34 ;; PRINT_BUFFER ;AN000;
35 ;; GET_SCREEN_INFO ;AN000;
37 ;; RESTORE_PRT ;AN000;
38 ;; NEW_PRT_LINE ;AN000;
40 ;; DET_CUR_SCAN_LNE_LENGTH ;AN000;
42 ;; Include Files Required: ;AN000;
43 ;; ----------------------- ;AN000;
46 ;; External Procedure References: ;AN000;
47 ;; ------------------------------ ;AN000;
48 ;; FROM FILE GRCTRL.ASM: ;AN000;
49 ;; PRT_SCR - Main module for printing the screen. ;AN000;
50 ;; FROM FILE GRBWPRT.ASM: ;AN000;
51 ;; PRT_BW_APA - Main module for printing on BW printer. ;AN000;
52 ;; FROM FILE GRCOLPRT.ASM: ;AN000;
53 ;; PRINT_COLOR - Main module for printing on COLOR printer. ;AN000;
55 ;; Linkage Instructions: ;AN000;
56 ;; -------------------- ;AN000;
58 ;; This file is included by both GRBWPRT.ASM and GRCOLPRT.ASM and is ;AN000;
59 ;; compiled with each of them. However, only one copy is made resident. ;AN000;
61 ;; Change History: ;AN000;
62 ;; --------------- ;AN000;
65 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000;
68 ;===============================================================================;AN000;
70 ; LOC_MODE_PRT_INFO: LOCATE DISPLAYMODE PRINTER INFO. FOR THE CURRENT ;AN000;
73 ;-------------------------------------------------------------------------------;AN000;
75 ; INPUT: BP = Offset of the shared data area ;AN000;
76 ; CUR_MODE = Current video mode ;AN000;
78 ; OUTPUT: CUR_MODE_PTR = Absolute Offset of the ;AN000;
79 ; current DISPLAYMODE INFO record. ;AN000;
81 ; ERROR_CODE = DISPLAYMODE_INFO_NOT_FOUND if not found. ;AN000;
83 ; CALLED BY: PRINT_COLOR ;AN000;
84 ; PRINT_BW_APA ;AN000;
87 ;-------------------------------------------------------------------------------;AN000;
89 ; DESCRIPTION: DISPLAYMODE_PTR is pointing to the first DISPLAYMODE ;AN000;
90 ; INFO record within the Shared Data Area. ;AN000;
92 ; This (chained) list of DISPLAYMODE records is scanned until the record ;AN000;
93 ; for the current mode is found. ;AN000;
95 ; Note: All pointers in the DISPLAYMODE records are relative to the beginning ;AN000;
96 ; of the shared data area. Therefore, we must add the offset of the ;AN000;
97 ; shared data area (in BP) in order to access the data these pointers ;AN000;
98 ; are referencing. ;AN000;
100 ; The CUR_MODE_PTR is relative to the segment and references the ;AN000;
101 ; DISPLAYMODE record for the video mode currently set at print screen ;AN000;
106 ; FOUND := FALSE ;AN000;
107 ; DO UNTIL FOUND OR END_OF_LIST ;AN000;
108 ; Get a display mode information record ;AN000;
109 ; IF record.DISP_MODE = CUR_MODE ;AN000;
110 ; THEN FOUND := TRUE ;AN000;
112 ; CUR_MODE_PTR := record.NEXT_DISP_MODE ;AN000;
116 LOC_MODE_PRT_INFO PROC
NEAR ;AN000;
122 MOV BX,DS:[BP].DISPLAYMODE_PTR
; [BX] := Current DISPLAYMODE ;AN000;
123 ADD BX,BP ; record ;AN000;
124 MOV DL,CUR_MODE
; DL := Current mode ;AN000;
126 SCAN_1_DISPLAYMODE_RECORD: ;AN000;
127 MOV SI,[BX].DISP_MODE_LIST_PTR
; [SI] : First mode covered ;AN000;
128 ADD SI,BP ; by this DISPLAYMODE record ;AN000;
129 MOV CL,[BX].NUM_DISP_MODE
; Scan each mode in the list ;AN000;
131 SCAN_LIST_OF_MODES: ;AN000;
132 CMP CS:[SI],DL ; FOUND ? ;AN000;
134 INC SI ; NO, get next mode in ;AN000;
135 LOOP SCAN_LIST_OF_MODES
; DISPLAYMODE record ;AN000;
137 CMP [BX].NEXT_DISP_MODE
,-1 ; END OF DISPLAYMODE LIST ? ;AN000;
138 JE NOT_FOUND
; Yes, this mode not supported ;AN000;
139 NEXT_RECORD: ; No, ;AN000;
140 MOV BX,[BX].NEXT_DISP_MODE
; [BX] := Next record ;AN000;
142 JMP SHORT SCAN_1_DISPLAYMODE_RECORD
;AN000;
144 FOUND: ; Found: ;AN000;
145 MOV CUR_MODE_PTR
,BX ; Update pointer to current ;AN000;
146 JMP SHORT LOC_MODE_PRT_INFO_END
; DISPLAYMODE record. ;AN000;
148 NOT_FOUND: ; Not found: ;AN000;
149 MOV ERROR_CODE
,DISPLAYMODE_INFO_NOT_FOUND
; Return error condition ;AN000;
151 LOC_MODE_PRT_INFO_END: ;AN000;
157 LOC_MODE_PRT_INFO ENDP
;AN000;
159 ;===============================================================================;AN000;
161 ; STORE_BOX : STORE ONE BOX IN THE PRINT BUFFER. ;AN000;
163 ;-------------------------------------------------------------------------------;AN000;
165 ; INPUT: SI = OFFSET OF THE BOX TO BE PRINTED ;AN000;
166 ; BOX_W = BOX WIDTH IN BITS ;AN000;
167 ; BOX_H = BOX HEIGHT IN BITS ;AN000;
169 ; OUTPUT: PRT_BUF = THE PRINT BUFFER ;AN000;
171 ;-------------------------------------------------------------------------------;AN000;
173 ; DESCRIPTION: The print buffer is first shifted left in order to make ;AN000;
174 ; room for the new box (Note: the MSB's are lost; they are assumed to ;AN000;
175 ; have been printed), then the box is inserted in the low-order bits of ;AN000;
176 ; the printer buffer. ;AN000;
181 ; BEFORE: AFTER: ;AN000;
192 ; PRT_BUF: byte1 byte2 byte3 PRT_BUF: byte1 byte2 byte3 ;AN000;
193 ; 0 1 0 1 1 1 ;AN000;
194 ; 1 0 1 1 1 1 ;AN000;
195 ; 1 1 1 1 1 1 ;AN000;
196 ; 1 1 1 1 1 1 ;AN000;
197 ; 1 1 1 1 1 1 ;AN000;
198 ; 1 1 1 1 1 1 ;AN000;
199 ; 1 1 1 b1 b2 b3 ;AN000;
200 ; LSB --> 1 1 1 b4 b5 b6 ;AN000;
205 ; FOR each byte of the buffer (BOX_W) ;AN000;
207 ; Make room for the box to be inserted ;AN000;
208 ; Insert the box ;AN000;
211 STORE_BOX PROC
NEAR ;AN000;
216 MOV DI,OFFSET PRT_BUF
; DI := Offset of the Print buffer ;AN000;
217 XOR BX,BX ; BX := Byte index number ;AN000;
219 MOV CL,BOX_H
; CL := Number of BITS to be shifted ;AN000;
220 ; FOR each column (byte) of the box to be stored in the buffer: ;AN000;
221 STORE_1_BYTE: ;AN000;
222 SHL BYTE PTR [BX][DI],CL ; Make room for the bits to be inserted ;AN000;
223 MOV CH,[BX][SI] ; CH := column of the box to be inserted;AN000;
224 OR [BX][DI],CH ; Insert the box column in the buffer ;AN000;
225 INC BL ; Get next column (byte) of the box ;AN000;
226 CMP BL,BOX_W
; All columns (bytes) of box stored ? ;AN000;
227 JL STORE_1_BYTE
; No, store next one. ;AN000;
229 STORE_BOX_END: ;AN000;
234 STORE_BOX ENDP
;AN000;
236 ;===============================================================================;AN000;
238 ; PRINT_BUFFER : PRINT THE BUFFER ;AN000;
240 ;-------------------------------------------------------------------------------;AN000;
242 ; INPUT: PRT_BUF = BYTES TO BE PRINTED ;AN000;
243 ; BOW_W = BOX WIDTH ;AN000;
245 ; OUTPUT: PRINTER ;AN000;
247 ;-------------------------------------------------------------------------------;AN000;
249 ; DESCRIPTION: Prints BOX_W bytes. ;AN000;
253 ; DO for each column in one pattern ;AN000;
255 ; Print one byte from the buffer ;AN000;
258 PRINT_BUFFER PROC
NEAR ;AN000;
263 MOV BX,OFFSET PRT_BUF
;AN000;
266 PRINT_1_BUF_COLUMN: ;AN000;
267 MOV AL,[BX] ; Print one byte ;AN000;
268 CALL PRINT_BYTE
;AN000;
269 JC PRINT_BUFFER_END
; If printer error, quit the loop ;AN000;
270 INC BX ; Get next byte ;AN000;
271 LOOP PRINT_1_BUF_COLUMN
;AN000;
272 PRINT_BUFFER_END: ;AN000;
277 PRINT_BUFFER ENDP
;AN000;
279 ;===============================================================================;AN000;
281 ; GET_SCREEN_INFO : GET INFORMATION ABOUT HOW TO READ THE SCREEN. ;AN000;
283 ;-------------------------------------------------------------------------------;AN000;
285 ; INPUT: SCREEN_HEIGHT = Number of pixel rows on the screen ;AN000;
286 ; SCREEN_WIDTH = Number of pixel columns on screen ;AN000;
287 ; CUR_MODE_PTR = Offset of the current DISPLAYMODE info rec. ;AN000;
289 ; OUTPUT: PRINTER ;AN000;
290 ; SCAN_LINE_MAX_LENGTH = Maximum length of Screen scan line. ;AN000;
291 ; NB_SCAN_LINES = Number of SCAN LINES on the screen ;AN000;
292 ; CUR_ROW,CUR_COLUMN = Coordinates of the first pixel to be ;AN000;
293 ; read on the screen ;AN000;
294 ; NB_BOXES_PER_PRT_BUF = Number of boxes fitting in the Print ;AN000;
297 ; CALLED BY: PRINT_COLOR ;AN000;
300 ;-------------------------------------------------------------------------------;AN000;
302 ; DESCRIPTION: ;AN000;
304 ; 1) Determine where to start reading the screen. ;AN000;
305 ; For non-rotated printing, it should start with the top-left ;AN000;
306 ; corner pixel. ;AN000;
307 ; For rotated printing, it should start with the low-left corner ;AN000;
310 ; 2) Determine the length of a scan line. ;AN000;
311 ; For non-rotated printing, it is the WIDTH of the screen. ;AN000;
312 ; For rotated printing, it is the HEIGHT of the screen. ;AN000;
314 ; 3) Determine the number of scan lines on the screen. ;AN000;
315 ; For non-rotated printing, it is the HEIGHT of the screen divided ;AN000;
316 ; by the number of boxes fitting in the print buffer. ;AN000;
317 ; For rotated printing, it is the WIDTH of the screen divided by ;AN000;
318 ; the number of boxes fitting in the print buffer. ;AN000;
322 ; CUR_COLUMN := 0 ;AN000;
323 ; IF printing is sideways ;AN000;
325 ; CUR_ROW := SCREEN_HEIGHT - 1 ; Low-left pixel ;AN000;
326 ; SCAN_LINE_MAX_LENGTH := SCREEN_HEIGHT ;AN000;
327 ; NB_SCAN_LINES := SCREEN_WIDTH / NB_BOXES_PER_PRT_BUF ;AN000;
329 ; CUR_ROW := 0 ; Top-left pixel ;AN000;
330 ; SCAN_LINE_MAX_LENGTH := SCREEN_WIDTH ;AN000;
331 ; NB_SCAN_LINES := SCREEN_HEIGHT / NB_BOXES_PER_PRT_BUF ;AN000;
334 GET_SCREEN_INFO PROC
NEAR ;AN000;
336 PUSH BX ; Used for DIV ;AN000;
337 PUSH DX ; Used for DIV ;AN000;
339 MOV BX,CUR_MODE_PTR
; BX := Offset DISPLAYMODE info record ;AN000;
340 ;-------------------------------------------------------------------------------;AN000;
342 ; Calculate how many printer boxes fit in the print buffer: ;AN000;
344 ;-------------------------------------------------------------------------------;AN000;
345 MOV AX,8 ; Num := 8 bits / Box heigth ;AN000;
346 MOV DL,[BX].BOX_HEIGHT
;AN000;
348 MOV NB_BOXES_PER_PRT_BUF
,AL ;AN000;
349 ;-------------------------------------------------------------------------------;AN000;
351 ; Determine where to start reading the screen: ;AN000;
353 ;-------------------------------------------------------------------------------;AN000;
354 MOV CUR_COLUMN
,0 ; Reading always start from left of scr ;AN000;
355 .IF <[BX].PRINT_OPTIONS
EQ ROTATE
> ;AN000;
357 ;-------------------------------------------------------------------------------;AN000;
359 ; Printing is sideways; screen must be read starting in low-left corner. ;AN000;
361 ;-------------------------------------------------------------------------------;AN000;
362 MOV AX,SCREEN_HEIGHT
;AN000;
363 MOV SCAN_LINE_MAX_LENGTH
,AX ; Scan line length := screen height ;AN000;
365 MOV CUR_ROW
,AX ; First row := screen height - 1 ;AN000;
367 ;-------Calculate the number of scan lines: ;AN000;
368 MOV AX,SCREEN_WIDTH
; DX AX = Screen width ;AN000;
370 XOR BX,BX ; BX = Number of boxes per print buf ;AN000;
371 MOV BL,NB_BOXES_PER_PRT_BUF
; ;AN000;
372 DIV BX ; Screen width / number boxes per buff ;AN000;
373 MOV NB_SCAN_LINES
,AX ; Number of scan lines := result ;AN000;
375 ;-------------------------------------------------------------------------------;AN000;
377 ; Printing is not sideways; screen must be read starting in top-left corner ;AN000;
379 ;-------------------------------------------------------------------------------;AN000;
380 MOV AX,SCREEN_WIDTH
;AN000;
381 MOV SCAN_LINE_MAX_LENGTH
,AX ; Scan line length := screen width ;AN000;
382 MOV CUR_ROW
,0 ; First row := 0 ;AN000;
384 ;-------Calculate the number of scan lines: ;AN000;
385 MOV AX,SCREEN_HEIGHT
; DX AX = Screen height ;AN000;
387 XOR BX,BX ; BX = Number of boxes per print buff ;AN000;
388 MOV BL,NB_BOXES_PER_PRT_BUF
; ;AN000;
389 DIV BX ; Screen height/number boxes per buff. ;AN000;
390 MOV NB_SCAN_LINES
,AX ; Number of scan lines := result ;AN000;
396 GET_SCREEN_INFO ENDP
;AN000;
398 ;===============================================================================;AN000;
400 ; DET_CUR_SCAN_LNE_LENGTH : Determine where is the last non-blank "scan line ;AN000;
401 ; column" on the current scan line. ;AN000;
403 ;-------------------------------------------------------------------------------;AN000;
405 ; INPUT: CUR_ROW, ;AN000;
406 ; CUR_COLUMN = Coordinates of the top pixel of the current ;AN000;
408 ; XLT_TAB = Color translation table ;AN000;
410 ; OUTPUT: CUR_SCAN_LNE_LENGTH = Number of "columns" of pixels from the ;AN000;
411 ; beginning of the scan line up to ;AN000;
412 ; the last non-blank pixel. ;AN000;
414 ; DATA SCREEN_WIDTH, ;AN000;
415 ; REFERENCED: SCREEN_HEIGHT = Dimensions of the screen in pels ;AN000;
416 ; SCAN_LINE_MAX_LENGTH= Maximum length of the scan line ;AN000;
417 ; ROTATE_SW = ON if printing is sideways ;AN000;
419 ;-------------------------------------------------------------------------------;AN000;
421 ; DESCRIPTION: Determine where is the last non-blank "column" by reading ;AN000;
422 ; the scan line backwards, one column at a time. ;AN000;
427 ; ; Obtain coordinates for the top pixel of the last column on the current ;AN000;
428 ; ; scan line: ;AN000;
429 ; IF printing is sideways ;AN000;
431 ; CUR_ROW := 0 ;AN000;
433 ; CUR_COLUMN := SCREEN_WIDTH - 1 ;AN000;
435 ; CUR_SCAN_LNE_LENGTH := SCAN_LINE_MAX_LENGTH ;AN000;
436 ; ; Read a column of pixels on the scan line until a non-blank is found: ;AN000;
437 ; For each column on the screen ;AN000;
438 ; CALL FILL_BUFF ;AN000;
439 ; ; Check if PRT_BUF is empty ;AN000;
440 ; IF buffer is empty ;AN000;
441 ; THEN DEC CUR_SCAN_LNE_LENGTH ;AN000;
442 ; ; Get next column ;AN000;
443 ; IF printing sideways THEN DEC CUR_ROW ;AN000;
444 ; ELSE DEC CUR_COLUMN ;AN000;
445 ; ELSE quit the loop ;AN000;
447 DET_CUR_SCAN_LNE_LENGTH PROC
NEAR ;AN000;
454 PUSH CUR_COLUMN
;AN000;
457 MOV BX,OFFSET XLT_TAB
; BX := Offset of XLT_TAB ;AN000;
458 ;-------------------------------------------------------------------------------;AN000;
460 ; Obtain coordinates of the top pixel for the last column of the current ;AN000;
463 ;-------------------------------------------------------------------------------;AN000;
464 .IF <ROTATE_SW
EQ ON> ; If printing sideways ;AN000;
465 .THEN
; then, ;AN000;
466 MOV CUR_ROW
,0 ; CUR_ROW := 0 ;AN000;
467 .ELSE ; else, ;AN000;
468 MOV CX,SCREEN_WIDTH
; CUR_COLUMN := SCREEN_WIDTH - 1 ;AN000;
470 MOV CUR_COLUMN
,CX ; ;AN000;
472 ;-------------------------------------------------------------------------------;AN000;
474 ; Read the scan line backwards "column" by "column" until a non-blank is found: ;AN000;
476 ;-------------------------------------------------------------------------------;AN000;
477 MOV CX,SCAN_LINE_MAX_LENGTH
; CX := current length ;AN000;
479 ;-------For each "column" ;AN000;
480 CHECK_1_COLUMN: ;AN000;
481 MOV SI,CUR_ROW
; Save coordinates of the column ;AN000;
482 MOV DI,CUR_COLUMN
; in SI, DI ;AN000;
483 XOR DL,DL ; DL := Number of pixels verified in ;AN000;
484 ; one "column" ;AN000;
486 ;-------For each pixel within that "column" ;AN000;
487 CHECK_1_PIXEL: ;AN000;
488 CALL READ_DOT
; AL := Index into translation table ;AN000;
489 XLAT XLT_TAB
; AL := Band mask or Intensity ;AN000;
491 ;-------Check if pixel will map to an empty box: ;AN000;
492 .IF <DS:[BP].PRINTER_TYPE
EQ BLACK_WHITE
> ; If BLACK AND WHITE printer ;AN000;
493 .THEN
; then, check for intensity of white ;AN000;
494 CMP AL,WHITE_INT
; If curent pixel not blank ;AN000;
495 JNE DET_LENGTH_END
; THEN, LEAVE THE LOOP ;AN000;
496 .ELSE ; else, COLOR printer ;AN000;
497 OR AL,AL ; IF Band mask not blank ;AN000;
498 JNZ DET_LENGTH_END
; THEN, LEAVE THE LOOP ;AN000;
501 ;-------All pixels so far on this "column" are blank, get next pixel: ;AN000;
502 .IF <ROTATE_SW
EQ ON> ; If printing sideways ;AN000;
504 INC CUR_COLUMN
; then, increment column number ;AN000;
506 INC CUR_ROW
; else, increment row number ;AN000;
508 INC DL ; One more pixel checked ;AN000;
509 CMP DL,NB_BOXES_PER_PRT_BUF
; All pixels for that column done ? ;AN000;
510 JL CHECK_1_PIXEL
; No, check next one. ;AN000;
512 ;-------Nothing to print for this column, get next column ;AN000;
513 .IF <ROTATE_SW
EQ ON> ; If printing sideways ;AN000;
514 .THEN
; then, ;AN000;
515 MOV CUR_COLUMN
,DI ; Restore column number ;AN000;
516 INC CUR_ROW
; Get next row ;AN000;
517 .ELSE ; else, ;AN000;
518 MOV CUR_ROW
,SI ; Restore row number ;AN000;
519 DEC CUR_COLUMN
; Get next column ;AN000;
521 LOOP CHECK_1_COLUMN
; CX (length) := CX - 1 ;AN000;
523 DET_LENGTH_END: ;AN000;
524 MOV CUR_SCAN_LNE_LENGTH
,CX ; Get current length ;AN000;
527 POP CUR_COLUMN
;AN000;
535 DET_CUR_SCAN_LNE_LENGTH ENDP
;AN000;
537 ;===============================================================================;AN000;
539 ; SETUP_PRT : SET UP THE PRINTER FOR PRINTING IN GRAPHIC MODE ;AN000;
541 ;-------------------------------------------------------------------------------;AN000;
543 ; INPUT: CUR_MODE_PTR = Offset of the DISPLAYMODE information ;AN000;
544 ; record for the current mode ;AN000;
546 ; OUTPUT: PRINTER ;AN000;
548 ; CALLED BY: PRINT_COLOR ;AN000;
551 ;-------------------------------------------------------------------------------;AN000;
553 ; DESCRIPTION: Extract the SETUP escape sequence from the DISPLAYMODE ;AN000;
554 ; information record; Send this escape sequence to the printer. ;AN000;
558 ; Number of bytes to print := CUR_MODE_PTR.NUM_SETUP_ESC ;AN000;
560 ; Get the escape sequence: ;AN000;
561 ; SI := CUR_MODE_PTR.SETUP_ESC_PTR ;AN000;
563 ; FOR each byte to be printed ;AN000;
564 ; PRINT_BYTE [SI] ; Send the byte to the printer ;AN000;
565 ; INC SI ; Get the next byte ;AN000;
567 SETUP_PRT PROC
NEAR ;AN000;
572 MOV BX,CUR_MODE_PTR
; BX := Displaymode info record. ;AN000;
574 XOR CX,CX ; CX := Number of bytes to print ;AN000;
575 MOV CL,[BX].NUM_SETUP_ESC
; ;AN000;
576 .IF <CL G
0> ; If there is at least one ;AN000;
577 .THEN
; byte to be printed: ;AN000;
578 MOV BX,[BX].SETUP_ESC_PTR
; BX := Offset sequence to send ;AN000;
581 SEND_1_SETUP_BYTE: ;AN000;
582 MOV AL,[BX] ; AL := byte to print ;AN000;
583 CALL PRINT_BYTE
; Send it to the printer ;AN000;
584 JC SETUP_PRT_END
; If printer error, quit the loop ;AN000;
585 INC BX ; Get next byte ;AN000;
586 LOOP SEND_1_SETUP_BYTE
;AN000;
588 SETUP_PRT_END: ;AN000;
593 SETUP_PRT ENDP
;AN000;
595 ;===============================================================================;AN000;
597 ; RESTORE_PRT : RESTORE THE PRINTER TO ITS INITIAL STATUS ;AN000;
599 ;-------------------------------------------------------------------------------;AN000;
601 ; INPUT: CUR_MODE_PTR = Offset of the DISPLAYMODE information ;AN000;
602 ; record for the current mode ;AN000;
604 ; OUTPUT: PRINTER ;AN000;
606 ; CALLED BY: PRINT_COLOR ;AN000;
608 ;-------------------------------------------------------------------------------;AN000;
610 ; DESCRIPTION: Extract the RESTORE escape sequence from the DISPLAYMODE ;AN000;
611 ; information record; Send this escape sequence to the printer. ;AN000;
615 ; Number of bytes to print := CUR_MODE_PTR.NUM_RESTORE_ESC ;AN000;
617 ; Get the escape sequence: ;AN000;
618 ; SI := CUR_MODE_PTR.RESTORE_ESC_PTR ;AN000;
619 ; FOR each byte to be printed ;AN000;
620 ; PRINT_BYTE [SI] ; Send the byte to the printer ;AN000;
621 ; INC SI ; Get the next byte ;AN000;
623 RESTORE_PRT PROC
NEAR ;AN000;
628 MOV BX,CUR_MODE_PTR
; BX := Displaymode info record. ;AN000;
630 XOR CX,CX ; CX := Number of bytes to print ;AN000;
631 MOV CL,[BX].NUM_RESTORE_ESC
;AN000;
632 .IF <CL G
0> ; If there is at least one ;AN000;
633 .THEN
; byte to be printed: ;AN000;
634 MOV BX,[BX].RESTORE_ESC_PTR
; BX := Offset sequence to send ;AN000;
637 SEND_1_RESTORE_BYTE: ;AN000;
638 MOV AL,[BX] ; AL := byte to print ;AN000;
639 CALL PRINT_BYTE
; Send it to the printer ;AN000;
640 JC RESTORE_PRT_END
; If printer error, quit the loop ;AN000;
641 INC BX ; Get next byte ;AN000;
642 LOOP SEND_1_RESTORE_BYTE
;AN000;
644 RESTORE_PRT_END: ;AN000;
649 RESTORE_PRT ENDP
;AN000;
651 ;===============================================================================;AN000;
653 ; NEW_PRT_LINE : INITIALIZE THE PRINTER FOR A GRAPHIC LINE ;AN000;
655 ;-------------------------------------------------------------------------------;AN000;
657 ; INPUT: CUR_MODE_PTR = Offset of the DISPLAYMODE information ;AN000;
658 ; record for the current mode ;AN000;
659 ; CUR_SCAN_LNE_LENGTH = Number of bytes to send to the printer. ;AN000;
661 ; OUTPUT: PRINTER ;AN000;
663 ; CALLED BY: PRINT_BAND ;AN000;
666 ;-------------------------------------------------------------------------------;AN000;
668 ; DESCRIPTION: Extract the GRAPHICS escape sequence from the DISPLAYMODE ;AN000;
669 ; information record; Send this escape sequence to the printer. ;AN000;
670 ; Then, send the number of bytes that will follow. ;AN000;
674 ; Number of bytes to print := CUR_MODE_PTR.NUM_GRAPHICS_ESC ;AN000;
676 ; Get the escape sequence: ;AN000;
677 ; Set up the 2 bytes containing the number of bytes to send in this sequence. ;AN000;
678 ; SI := CUR_MODE_PTR.GRAPHICS_ESC_PTR ;AN000;
680 ; FOR each byte to be printed ;AN000;
681 ; PRINT_BYTE [SI] ; Send the byte to the printer ;AN000;
682 ; INC SI ; Get the next byte ;AN000;
684 ; Send the byte count ;AN000;
687 NEW_PRT_LINE PROC
NEAR ;AN000;
694 MOV BX,CUR_MODE_PTR
; BX := Displaymode info record. ;AN000;
696 ;-------------------------------------------------------------------------------;AN000;
697 ; Set up the 2 bytes containing the number of bytes to send in the GRAPHICS seq.;AN000;
698 ; NOTE: number of bytes to send is "CUR_SCAN_LNE_LENGTH * BOX_W" ;AN000;
699 ;-------------------------------------------------------------------------------;AN000;
700 MOV AL,BOX_W
; cur_scan_lne_length * ;AN000;
701 CBW ; printer box width = nb bytes to send;AN000;
702 MUL CUR_SCAN_LNE_LENGTH
; (result in DX AX) ;AN000;
704 ;-------AX := Number of bytes to print ;AN000;
705 MOV DI,[BX].LOW_BYT_COUNT_PTR
; DI := Offset of LOW byte of ;AN000;
706 ADD DI,BP ; byte count ;AN000;
707 MOV [DI],AL ; Store low byte ;AN000;
708 MOV DI,[BX].HGH_BYT_COUNT_PTR
; DI := Offset of HIGH byte of ;AN000;
709 ADD DI,BP ; byte count ;AN000;
710 MOV [DI],AH ; Store high byte ;AN000;
712 ;-------------------------------------------------------------------------------;AN000;
713 ; Send the GRAPHICS escape sequence to the printer: ;AN000;
714 ;-------------------------------------------------------------------------------;AN000;
715 XOR CX,CX ; CX := Length of the escape seq;AN000;
716 MOV CL,[BX].NUM_GRAPHICS_ESC
;AN000;
717 MOV BX,[BX].GRAPHICS_ESC_PTR
; BX := Offset sequence to send ;AN000;
720 SEND_1_GRAPHICS_BYTE: ;AN000;
721 MOV AL,[BX] ; AL := byte to print ;AN000;
722 CALL PRINT_BYTE
; Send it to the printer ;AN000;
723 JC NEW_PRT_LINE_ENDP
; If printer error, quit the loop ;AN000;
724 INC BX ; Get next byte ;AN000;
725 LOOP SEND_1_GRAPHICS_BYTE
;AN000;
727 NEW_PRT_LINE_ENDP: ;AN000;
734 NEW_PRT_LINE ENDP
;AN000;
736 ;===============================================================================;AN000;
738 ; PRINT_BYTE : SEND A BYTE TO THE PRINTER AT LPT1 ;AN000;
740 ;-------------------------------------------------------------------------------;AN000;
742 ; INPUT: AL = Byte to be printed ;AN000;
744 ; OUTPUT: PRINTER ;AN000;
745 ; ERROR_CODE = PRINTER_ERROR if an error is detected. ;AN000;
746 ; Carry flag is set in case of error. ;AN000;
748 ;-------------------------------------------------------------------------------;AN000;
749 PRINT_BYTE PROC
NEAR ;AN000;
753 MOV DX,0000 ; PRINTER NUMBER ;AN000;
754 MOV AH,00 ; REQUEST PRINT ;AN000;
755 INT 17H
; CALL BIOS : SEND THE CHARACTER ;AN000;
757 AND AH,00101001B ; Test error code returned in AH for ;AN000;
758 ; "Out of paper", "I/O error" and "Time-out". ;AN000;
759 JNZ PRINT_BYTE_ERROR
; Set the error code if error ;AN000;
760 JMP SHORT PRINT_BYTE_END
; else, return normally ;AN000;
761 PRINT_BYTE_ERROR: ;AN000;
762 MOV ERROR_CODE
,PRINTER_ERROR
;AN000;
763 STC ; Set the carry flag to indicate ERROR ;AN000;
764 PRINT_BYTE_END: ;AN000;
768 PRINT_BYTE ENDP
;AN000;
770 ;===============================================================================;AN000;
772 ; READ_DOT: READ A PIXEL - RETURN A COLOR TRANSLATION TABLE INDEX ;AN000;
774 ;-------------------------------------------------------------------------------;AN000;
776 ; INPUT: CUR_MODE = Current video mode. ;AN000;
778 ; CUR_COLUMN = Coordinates of the pixel to be read. ;AN000;
779 ; CUR_PAGE = Active page number ;AN000;
781 ; OUTPUT: AL = Index into COLOR TRANSLATION TABLE. ;AN000;
783 ; DEPENDENCIES : COLOR TRANSLATION TABLE entries must be bytes ;AN000;
786 ;-------------------------------------------------------------------------------;AN000;
788 ; DESCRIPTION: Use VIDEO BIOS INTERRUPT 10H "READ DOT CALL". ;AN000;
790 ; Depending on the video hardware, the dot returned by BIOS has ;AN000;
791 ; different meanings. ;AN000;
792 ; With an EGA it is an index into the Palette registers, ;AN000;
793 ; With a CGA it is a number from 0 to 3, mapping to a specific color ;AN000;
794 ; depending on the background color and the color palette currently ;AN000;
797 ; The Color Translation table has been set up to hold the correct color ;AN000;
798 ; mapping for any "dot" in any mode. Therefore, the dot number returned ;AN000;
799 ; by INT 10H can be used with any mode as a direct index within that ;AN000;
802 ; With APA Monochrome mode 0FH there are 4 different dots: white, ;AN000;
803 ; blinking white, high-intensity white, and black. ;AN000;
805 ; For mode 0FH, the dot returned by interrupt 10 "read dot" call is a byte ;AN000;
806 ; where only bits 0 and 2 are significant. These 2 bits must be appended ;AN000;
807 ; together in order to obtain a binary number (from 0 to 3) that will be used ;AN000;
808 ; as an index in the Color Translation table. ;AN000;
810 ; For mode 11H, the dot is either 0 (for background color) or 7 (for the ;AN000;
811 ; foreground color) only the LSB is returned. That is, we return either ;AN000;
816 ; Call VIDEO BIOS "READ DOT" ;AN000;
817 ; IF CUR_MODE = 0FH ;AN000;
819 ; Append bits 1 and 3. ;AN000;
820 ; IF CUR_MODE = 11H ;AN000;
822 ; Wipe out bits 1 and 2. ;AN000;
824 READ_DOT PROC
NEAR ;AN000;
825 PUSH BX ; Save registers ;AN000;
829 MOV BH,CUR_PAGE
;AN000;
830 MOV DX,CUR_ROW
;AN000;
831 MOV CX,CUR_COLUMN
;AN000;
832 MOV AH,READ_DOT_CALL
;AN000;
833 INT 10H
; Call BIOS: AL <-- Dot read ;AN000;
835 CMP CUR_MODE
,0FH ; Is it Mode 0fH ? ;AN000;
836 JNE MODE_11H?
; No, look for mode 11h. ;AN000;
837 ;-------Mode 0Fh is the current mode: ;AN000;
838 ;-------Convert bits 2 and 0 into a 2 bit number: ;AN000;
839 MOV BL,AL ; BL := AL = "Pixel read" ;AN000;
840 AND BL,00000100B ; Wipe off all bits but bit 2 in BL ;AN000;
841 AND AL,00000001B ; Wipe off all bits but bit 0 in AL ;AN000;
842 SHR BL,1 ; Move bit 2 to bit 1 in BL ;AN000;
843 OR AL,BL ; Append bit 1 and bit 0 ;AN000;
844 JMP SHORT READ_DOT_END
; Quit. ;AN000;
847 CMP CUR_MODE
,11H
; Is it Mode 0fH ? ;AN000;
848 JNE READ_DOT_END
; No, quit ;AN000;
850 ;-------Mode 11H is the current mode: ;AN000;
851 AND AL,00000001B ; Keep only the Least significant bit ;AN000;
853 READ_DOT_END: ;AN000;
854 POP DX ; Restore registers ;AN000;
858 READ_DOT ENDP
;AN000;