summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/GRAPHICS/GRCOMMON.ASM
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/CMD/GRAPHICS/GRCOMMON.ASM
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/CMD/GRAPHICS/GRCOMMON.ASM')
-rw-r--r--v4.0/src/CMD/GRAPHICS/GRCOMMON.ASM858
1 files changed, 858 insertions, 0 deletions
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 @@
1 PAGE ,132 ;AN000;
2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000;
3;; DOS - GRAPHICS Command
4;; (c) Copyright 1988 Microsoft
5;; ;AN000;
6;; File Name: GRCOMMON.ASM ;AN000;
7;; ---------- ;AN000;
8;; ;AN000;
9;; Description: ;AN000;
10;; ------------ ;AN000;
11;; ;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;
15;; ;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;
20;; ;AN000;
21;; The set of common modules is relocated in memory along with ;AN000;
22;; the selected set of print modules. ;AN000;
23;; ;AN000;
24;; Documentation Reference: ;AN000;
25;; ------------------------ ;AN000;
26;; OASIS High Level Design ;AN000;
27;; OASIS GRAPHICS I1 Overview ;AN000;
28;; ;AN000;
29;; Procedures Contained in This File: ;AN000;
30;; ---------------------------------- ;AN000;
31;; READ_DOT ;AN000;
32;; LOC_MODE_PRT_INFO ;AN000;
33;; STORE_BOX ;AN000;
34;; PRINT_BUFFER ;AN000;
35;; GET_SCREEN_INFO ;AN000;
36;; SETUP_PRT ;AN000;
37;; RESTORE_PRT ;AN000;
38;; NEW_PRT_LINE ;AN000;
39;; PRINT_BYTE ;AN000;
40;; DET_CUR_SCAN_LNE_LENGTH ;AN000;
41;; ;AN000;
42;; Include Files Required: ;AN000;
43;; ----------------------- ;AN000;
44;; none ;AN000;
45;; ;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;
54;; ;AN000;
55;; Linkage Instructions: ;AN000;
56;; -------------------- ;AN000;
57;; ;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;
60;; ;AN000;
61;; Change History: ;AN000;
62;; --------------- ;AN000;
63;; ;AN000;
64;; ;AN000;
65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000;
66 ;AN000;
67PAGE ;AN000;
68;===============================================================================;AN000;
69; ;AN000;
70; LOC_MODE_PRT_INFO: LOCATE DISPLAYMODE PRINTER INFO. FOR THE CURRENT ;AN000;
71; MODE ;AN000;
72; ;AN000;
73;-------------------------------------------------------------------------------;AN000;
74; ;AN000;
75; INPUT: BP = Offset of the shared data area ;AN000;
76; CUR_MODE = Current video mode ;AN000;
77; ;AN000;
78; OUTPUT: CUR_MODE_PTR = Absolute Offset of the ;AN000;
79; current DISPLAYMODE INFO record. ;AN000;
80; ;AN000;
81; ERROR_CODE = DISPLAYMODE_INFO_NOT_FOUND if not found. ;AN000;
82; ;AN000;
83; CALLED BY: PRINT_COLOR ;AN000;
84; PRINT_BW_APA ;AN000;
85; ;AN000;
86; ;AN000;
87;-------------------------------------------------------------------------------;AN000;
88; ;AN000;
89; DESCRIPTION: DISPLAYMODE_PTR is pointing to the first DISPLAYMODE ;AN000;
90; INFO record within the Shared Data Area. ;AN000;
91; ;AN000;
92; This (chained) list of DISPLAYMODE records is scanned until the record ;AN000;
93; for the current mode is found. ;AN000;
94; ;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;
99; ;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;
102; time. ;AN000;
103; ;AN000;
104; LOGIC: ;AN000;
105; ;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;
111; ELSE ;AN000;
112; CUR_MODE_PTR := record.NEXT_DISP_MODE ;AN000;
113; ;AN000;
114; ;AN000;
115 ;AN000;
116LOC_MODE_PRT_INFO PROC NEAR ;AN000;
117 PUSH BX ;AN000;
118 PUSH CX ;AN000;
119 PUSH DX ;AN000;
120 PUSH SI ;AN000;
121 ;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;
125 ;AN000;
126SCAN_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;
130 XOR CH,CH ;AN000;
131SCAN_LIST_OF_MODES: ;AN000;
132 CMP CS:[SI],DL ; FOUND ? ;AN000;
133 JE FOUND ;AN000;
134 INC SI ; NO, get next mode in ;AN000;
135 LOOP SCAN_LIST_OF_MODES ; DISPLAYMODE record ;AN000;
136 ;AN000;
137 CMP [BX].NEXT_DISP_MODE,-1 ; END OF DISPLAYMODE LIST ? ;AN000;
138 JE NOT_FOUND ; Yes, this mode not supported ;AN000;
139NEXT_RECORD: ; No, ;AN000;
140 MOV BX,[BX].NEXT_DISP_MODE ; [BX] := Next record ;AN000;
141 ADD BX,BP ; ;AN000;
142 JMP SHORT SCAN_1_DISPLAYMODE_RECORD ;AN000;
143 ;AN000;
144FOUND: ; Found: ;AN000;
145 MOV CUR_MODE_PTR,BX ; Update pointer to current ;AN000;
146 JMP SHORT LOC_MODE_PRT_INFO_END ; DISPLAYMODE record. ;AN000;
147 ;AN000;
148NOT_FOUND: ; Not found: ;AN000;
149 MOV ERROR_CODE,DISPLAYMODE_INFO_NOT_FOUND ; Return error condition ;AN000;
150 ;AN000;
151LOC_MODE_PRT_INFO_END: ;AN000;
152 POP SI ;AN000;
153 POP DX ;AN000;
154 POP CX ;AN000;
155 POP BX ;AN000;
156 RET ;AN000;
157LOC_MODE_PRT_INFO ENDP ;AN000;
158PAGE ;AN000;
159;===============================================================================;AN000;
160; ;AN000;
161; STORE_BOX : STORE ONE BOX IN THE PRINT BUFFER. ;AN000;
162; ;AN000;
163;-------------------------------------------------------------------------------;AN000;
164; ;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;
168; ;AN000;
169; OUTPUT: PRT_BUF = THE PRINT BUFFER ;AN000;
170; ;AN000;
171;-------------------------------------------------------------------------------;AN000;
172; ;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;
177; ;AN000;
178PAGE ;AN000;
179; EXAMPLE ;AN000;
180; ------- ;AN000;
181; BEFORE: AFTER: ;AN000;
182; ;AN000;
183; BOX: 0 0 0 ;AN000;
184; 0 0 0 ;AN000;
185; 0 0 0 ;AN000;
186; 0 0 0 ;AN000;
187; 0 0 0 ;AN000;
188; 0 0 0 ;AN000;
189; b1 b2 b3 ;AN000;
190; b4 b5 b6 ;AN000;
191; ;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;
201; ;AN000;
202; ;AN000;
203; LOGIC: ;AN000;
204; ;AN000;
205; FOR each byte of the buffer (BOX_W) ;AN000;
206; BEGIN ;AN000;
207; Make room for the box to be inserted ;AN000;
208; Insert the box ;AN000;
209; END ;AN000;
210; ;AN000;
211STORE_BOX PROC NEAR ;AN000;
212 PUSH BX ;AN000;
213 PUSH CX ;AN000;
214 PUSH DI ;AN000;
215 ;AN000;
216 MOV DI,OFFSET PRT_BUF ; DI := Offset of the Print buffer ;AN000;
217 XOR BX,BX ; BX := Byte index number ;AN000;
218 ;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;
221STORE_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;
228 ;AN000;
229STORE_BOX_END: ;AN000;
230 POP DI ;AN000;
231 POP CX ;AN000;
232 POP BX ;AN000;
233 RET ;AN000;
234STORE_BOX ENDP ;AN000;
235PAGE ;AN000;
236;===============================================================================;AN000;
237; ;AN000;
238; PRINT_BUFFER : PRINT THE BUFFER ;AN000;
239; ;AN000;
240;-------------------------------------------------------------------------------;AN000;
241; ;AN000;
242; INPUT: PRT_BUF = BYTES TO BE PRINTED ;AN000;
243; BOW_W = BOX WIDTH ;AN000;
244; ;AN000;
245; OUTPUT: PRINTER ;AN000;
246; ;AN000;
247;-------------------------------------------------------------------------------;AN000;
248; ;AN000;
249; DESCRIPTION: Prints BOX_W bytes. ;AN000;
250; ;AN000;
251; LOGIC: ;AN000;
252; ;AN000;
253; DO for each column in one pattern ;AN000;
254; BEGIN ;AN000;
255; Print one byte from the buffer ;AN000;
256; END ;AN000;
257; ;AN000;
258PRINT_BUFFER PROC NEAR ;AN000;
259 PUSH AX ;AN000;
260 PUSH BX ;AN000;
261 PUSH CX ;AN000;
262 ;AN000;
263 MOV BX,OFFSET PRT_BUF ;AN000;
264 XOR CX,CX ;AN000;
265 MOV CL,BOX_W ;AN000;
266PRINT_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;
272PRINT_BUFFER_END: ;AN000;
273 POP CX ;AN000;
274 POP BX ;AN000;
275 POP AX ;AN000;
276 RET ;AN000;
277PRINT_BUFFER ENDP ;AN000;
278PAGE ;AN000;
279;===============================================================================;AN000;
280; ;AN000;
281; GET_SCREEN_INFO : GET INFORMATION ABOUT HOW TO READ THE SCREEN. ;AN000;
282; ;AN000;
283;-------------------------------------------------------------------------------;AN000;
284; ;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;
288; ;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;
295; buffer ;AN000;
296; ;AN000;
297; CALLED BY: PRINT_COLOR ;AN000;
298; PRT_BW_APA ;AN000;
299; ;AN000;
300;-------------------------------------------------------------------------------;AN000;
301; ;AN000;
302; DESCRIPTION: ;AN000;
303; ;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;
308; pixel. ;AN000;
309; ;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;
313; ;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;
319; ;AN000;
320; LOGIC: ;AN000;
321; ;AN000;
322; CUR_COLUMN := 0 ;AN000;
323; IF printing is sideways ;AN000;
324; THEN ;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;
328; ELSE ;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;
332; ;AN000;
333; ;AN000;
334GET_SCREEN_INFO PROC NEAR ;AN000;
335 PUSH AX ;AN000;
336 PUSH BX ; Used for DIV ;AN000;
337 PUSH DX ; Used for DIV ;AN000;
338 ;AN000;
339 MOV BX,CUR_MODE_PTR ; BX := Offset DISPLAYMODE info record ;AN000;
340;-------------------------------------------------------------------------------;AN000;
341; ;AN000;
342; Calculate how many printer boxes fit in the print buffer: ;AN000;
343; ;AN000;
344;-------------------------------------------------------------------------------;AN000;
345 MOV AX,8 ; Num := 8 bits / Box heigth ;AN000;
346 MOV DL,[BX].BOX_HEIGHT ;AN000;
347 DIV DL ;AN000;
348 MOV NB_BOXES_PER_PRT_BUF,AL ;AN000;
349;-------------------------------------------------------------------------------;AN000;
350; ;AN000;
351; Determine where to start reading the screen: ;AN000;
352; ;AN000;
353;-------------------------------------------------------------------------------;AN000;
354 MOV CUR_COLUMN,0 ; Reading always start from left of scr ;AN000;
355.IF <[BX].PRINT_OPTIONS EQ ROTATE> ;AN000;
356.THEN ;AN000;
357;-------------------------------------------------------------------------------;AN000;
358; ;AN000;
359; Printing is sideways; screen must be read starting in low-left corner. ;AN000;
360; ;AN000;
361;-------------------------------------------------------------------------------;AN000;
362 MOV AX,SCREEN_HEIGHT ;AN000;
363 MOV SCAN_LINE_MAX_LENGTH,AX ; Scan line length := screen height ;AN000;
364 DEC AX ;AN000;
365 MOV CUR_ROW,AX ; First row := screen height - 1 ;AN000;
366 ;AN000;
367;-------Calculate the number of scan lines: ;AN000;
368 MOV AX,SCREEN_WIDTH ; DX AX = Screen width ;AN000;
369 CWD ; ;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;
374.ELSE ;AN000;
375;-------------------------------------------------------------------------------;AN000;
376; ;AN000;
377; Printing is not sideways; screen must be read starting in top-left corner ;AN000;
378; ;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;
383 ;AN000;
384;-------Calculate the number of scan lines: ;AN000;
385 MOV AX,SCREEN_HEIGHT ; DX AX = Screen height ;AN000;
386 CWD ; ;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;
391.ENDIF ;AN000;
392 POP DX ;AN000;
393 POP BX ;AN000;
394 POP AX ;AN000;
395 RET ;AN000;
396GET_SCREEN_INFO ENDP ;AN000;
397PAGE ;AN000;
398;===============================================================================;AN000;
399; ;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;
402; ;AN000;
403;-------------------------------------------------------------------------------;AN000;
404; ;AN000;
405; INPUT: CUR_ROW, ;AN000;
406; CUR_COLUMN = Coordinates of the top pixel of the current ;AN000;
407; scan line. ;AN000;
408; XLT_TAB = Color translation table ;AN000;
409; ;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;
413; ;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;
418; ;AN000;
419;-------------------------------------------------------------------------------;AN000;
420; ;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;
423; ;AN000;
424; ;AN000;
425; LOGIC: ;AN000;
426; ;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;
430; THEN ;AN000;
431; CUR_ROW := 0 ;AN000;
432; ELSE ;AN000;
433; CUR_COLUMN := SCREEN_WIDTH - 1 ;AN000;
434; ;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;
446; ;AN000;
447DET_CUR_SCAN_LNE_LENGTH PROC NEAR ;AN000;
448 PUSH AX ;AN000;
449 PUSH BX ;AN000;
450 PUSH CX ;AN000;
451 PUSH DX ;AN000;
452 PUSH SI ;AN000;
453 PUSH DI ;AN000;
454 PUSH CUR_COLUMN ;AN000;
455 PUSH CUR_ROW ;AN000;
456 ;AN000;
457 MOV BX,OFFSET XLT_TAB ; BX := Offset of XLT_TAB ;AN000;
458;-------------------------------------------------------------------------------;AN000;
459; ;AN000;
460; Obtain coordinates of the top pixel for the last column of the current ;AN000;
461; scan line: ;AN000;
462; ;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;
469 DEC CX ; ;AN000;
470 MOV CUR_COLUMN,CX ; ;AN000;
471 .ENDIF ;AN000;
472;-------------------------------------------------------------------------------;AN000;
473; ;AN000;
474; Read the scan line backwards "column" by "column" until a non-blank is found: ;AN000;
475; ;AN000;
476;-------------------------------------------------------------------------------;AN000;
477 MOV CX,SCAN_LINE_MAX_LENGTH ; CX := current length ;AN000;
478; ;AN000;
479;-------For each "column" ;AN000;
480CHECK_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;
485; ;AN000;
486;-------For each pixel within that "column" ;AN000;
487CHECK_1_PIXEL: ;AN000;
488 CALL READ_DOT ; AL := Index into translation table ;AN000;
489 XLAT XLT_TAB ; AL := Band mask or Intensity ;AN000;
490 ;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;
499 .ENDIF ;AN000;
500 ;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;
503 .THEN ; ;AN000;
504 INC CUR_COLUMN ; then, increment column number ;AN000;
505 .ELSE ; ;AN000;
506 INC CUR_ROW ; else, increment row number ;AN000;
507 .ENDIF ; ;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;
511 ;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;
520 .ENDIF ; ;AN000;
521 LOOP CHECK_1_COLUMN ; CX (length) := CX - 1 ;AN000;
522 ;AN000;
523DET_LENGTH_END: ;AN000;
524 MOV CUR_SCAN_LNE_LENGTH,CX ; Get current length ;AN000;
525 ;AN000;
526 POP CUR_ROW ;AN000;
527 POP CUR_COLUMN ;AN000;
528 POP DI ;AN000;
529 POP SI ;AN000;
530 POP DX ;AN000;
531 POP CX ;AN000;
532 POP BX ;AN000;
533 POP AX ;AN000;
534 RET ;AN000;
535DET_CUR_SCAN_LNE_LENGTH ENDP ;AN000;
536PAGE ;AN000;
537;===============================================================================;AN000;
538; ;AN000;
539; SETUP_PRT : SET UP THE PRINTER FOR PRINTING IN GRAPHIC MODE ;AN000;
540; ;AN000;
541;-------------------------------------------------------------------------------;AN000;
542; ;AN000;
543; INPUT: CUR_MODE_PTR = Offset of the DISPLAYMODE information ;AN000;
544; record for the current mode ;AN000;
545; ;AN000;
546; OUTPUT: PRINTER ;AN000;
547; ;AN000;
548; CALLED BY: PRINT_COLOR ;AN000;
549; PRT_BW_APA ;AN000;
550; ;AN000;
551;-------------------------------------------------------------------------------;AN000;
552; ;AN000;
553; DESCRIPTION: Extract the SETUP escape sequence from the DISPLAYMODE ;AN000;
554; information record; Send this escape sequence to the printer. ;AN000;
555; ;AN000;
556; LOGIC: ;AN000;
557; ;AN000;
558; Number of bytes to print := CUR_MODE_PTR.NUM_SETUP_ESC ;AN000;
559; ;AN000;
560; Get the escape sequence: ;AN000;
561; SI := CUR_MODE_PTR.SETUP_ESC_PTR ;AN000;
562; ;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;
566; ;AN000;
567SETUP_PRT PROC NEAR ;AN000;
568 PUSH AX ;AN000;
569 PUSH BX ;AN000;
570 PUSH CX ;AN000;
571 ;AN000;
572 MOV BX,CUR_MODE_PTR ; BX := Displaymode info record. ;AN000;
573 ;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;
579 ADD BX,BP ;AN000;
580 ;AN000;
581SEND_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;
587.ENDIF ;AN000;
588SETUP_PRT_END: ;AN000;
589 POP CX ;AN000;
590 POP BX ;AN000;
591 POP AX ;AN000;
592 RET ;AN000;
593SETUP_PRT ENDP ;AN000;
594PAGE ;AN000;
595;===============================================================================;AN000;
596; ;AN000;
597; RESTORE_PRT : RESTORE THE PRINTER TO ITS INITIAL STATUS ;AN000;
598; ;AN000;
599;-------------------------------------------------------------------------------;AN000;
600; ;AN000;
601; INPUT: CUR_MODE_PTR = Offset of the DISPLAYMODE information ;AN000;
602; record for the current mode ;AN000;
603; ;AN000;
604; OUTPUT: PRINTER ;AN000;
605; ;AN000;
606; CALLED BY: PRINT_COLOR ;AN000;
607; PRT_BW_APA ;AN000;
608;-------------------------------------------------------------------------------;AN000;
609; ;AN000;
610; DESCRIPTION: Extract the RESTORE escape sequence from the DISPLAYMODE ;AN000;
611; information record; Send this escape sequence to the printer. ;AN000;
612; ;AN000;
613; LOGIC: ;AN000;
614; ;AN000;
615; Number of bytes to print := CUR_MODE_PTR.NUM_RESTORE_ESC ;AN000;
616; ;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;
622; ;AN000;
623RESTORE_PRT PROC NEAR ;AN000;
624 PUSH AX ;AN000;
625 PUSH BX ;AN000;
626 PUSH CX ;AN000;
627 ;AN000;
628 MOV BX,CUR_MODE_PTR ; BX := Displaymode info record. ;AN000;
629 ;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;
635 ADD BX,BP ;AN000;
636 ;AN000;
637SEND_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;
643.ENDIF ;AN000;
644RESTORE_PRT_END: ;AN000;
645 POP CX ;AN000;
646 POP BX ;AN000;
647 POP AX ;AN000;
648 RET ;AN000;
649RESTORE_PRT ENDP ;AN000;
650PAGE ;AN000;
651;===============================================================================;AN000;
652; ;AN000;
653; NEW_PRT_LINE : INITIALIZE THE PRINTER FOR A GRAPHIC LINE ;AN000;
654; ;AN000;
655;-------------------------------------------------------------------------------;AN000;
656; ;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;
660; ;AN000;
661; OUTPUT: PRINTER ;AN000;
662; ;AN000;
663; CALLED BY: PRINT_BAND ;AN000;
664; PRT_BW_APA ;AN000;
665; ;AN000;
666;-------------------------------------------------------------------------------;AN000;
667; ;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;
671; ;AN000;
672; LOGIC: ;AN000;
673; ;AN000;
674; Number of bytes to print := CUR_MODE_PTR.NUM_GRAPHICS_ESC ;AN000;
675; ;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;
679; ;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;
683; ;AN000;
684; Send the byte count ;AN000;
685; ;AN000;
686 ;AN000;
687NEW_PRT_LINE PROC NEAR ;AN000;
688 PUSH AX ;AN000;
689 PUSH BX ;AN000;
690 PUSH CX ;AN000;
691 PUSH DX ;AN000;
692 PUSH DI ;AN000;
693 ;AN000;
694 MOV BX,CUR_MODE_PTR ; BX := Displaymode info record. ;AN000;
695 ;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;
703 ; ;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;
711 ;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;
718 ADD BX,BP ;AN000;
719 ;AN000;
720SEND_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;
726 ;AN000;
727NEW_PRT_LINE_ENDP: ;AN000;
728 POP DI ;AN000;
729 POP DX ;AN000;
730 POP CX ;AN000;
731 POP BX ;AN000;
732 POP AX ;AN000;
733 RET ;AN000;
734NEW_PRT_LINE ENDP ;AN000;
735PAGE ;AN000;
736;===============================================================================;AN000;
737; ;AN000;
738; PRINT_BYTE : SEND A BYTE TO THE PRINTER AT LPT1 ;AN000;
739; ;AN000;
740;-------------------------------------------------------------------------------;AN000;
741; ;AN000;
742; INPUT: AL = Byte to be printed ;AN000;
743; ;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;
747; ;AN000;
748;-------------------------------------------------------------------------------;AN000;
749PRINT_BYTE PROC NEAR ;AN000;
750 PUSH AX ;AN000;
751 PUSH DX ;AN000;
752 ;AN000;
753 MOV DX,0000 ; PRINTER NUMBER ;AN000;
754 MOV AH,00 ; REQUEST PRINT ;AN000;
755 INT 17H ; CALL BIOS : SEND THE CHARACTER ;AN000;
756 ;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;
761PRINT_BYTE_ERROR: ;AN000;
762 MOV ERROR_CODE,PRINTER_ERROR ;AN000;
763 STC ; Set the carry flag to indicate ERROR ;AN000;
764PRINT_BYTE_END: ;AN000;
765 POP DX ;AN000;
766 POP AX ;AN000;
767 RET ;AN000;
768PRINT_BYTE ENDP ;AN000;
769PAGE ;AN000;
770;===============================================================================;AN000;
771; ;AN000;
772; READ_DOT: READ A PIXEL - RETURN A COLOR TRANSLATION TABLE INDEX ;AN000;
773; ;AN000;
774;-------------------------------------------------------------------------------;AN000;
775; ;AN000;
776; INPUT: CUR_MODE = Current video mode. ;AN000;
777; CUR_ROW, ;AN000;
778; CUR_COLUMN = Coordinates of the pixel to be read. ;AN000;
779; CUR_PAGE = Active page number ;AN000;
780; ;AN000;
781; OUTPUT: AL = Index into COLOR TRANSLATION TABLE. ;AN000;
782; ;AN000;
783; DEPENDENCIES : COLOR TRANSLATION TABLE entries must be bytes ;AN000;
784; ;AN000;
785; ;AN000;
786;-------------------------------------------------------------------------------;AN000;
787; ;AN000;
788; DESCRIPTION: Use VIDEO BIOS INTERRUPT 10H "READ DOT CALL". ;AN000;
789; ;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;
795; selected. ;AN000;
796; ;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;
800; table. ;AN000;
801; ;AN000;
802; With APA Monochrome mode 0FH there are 4 different dots: white, ;AN000;
803; blinking white, high-intensity white, and black. ;AN000;
804; ;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;
809; ;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;
812; 0 or 1. ;AN000;
813; ;AN000;
814; LOGIC: ;AN000;
815; ;AN000;
816; Call VIDEO BIOS "READ DOT" ;AN000;
817; IF CUR_MODE = 0FH ;AN000;
818; THEN ;AN000;
819; Append bits 1 and 3. ;AN000;
820; IF CUR_MODE = 11H ;AN000;
821; THEN ;AN000;
822; Wipe out bits 1 and 2. ;AN000;
823; ;AN000;
824READ_DOT PROC NEAR ;AN000;
825 PUSH BX ; Save registers ;AN000;
826 PUSH CX ;AN000;
827 PUSH DX ;AN000;
828 ;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;
834 ;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;
845 ;AN000;
846MODE_11H?: ;AN000;
847 CMP CUR_MODE,11H ; Is it Mode 0fH ? ;AN000;
848 JNE READ_DOT_END ; No, quit ;AN000;
849 ;AN000;
850;-------Mode 11H is the current mode: ;AN000;
851 AND AL,00000001B ; Keep only the Least significant bit ;AN000;
852 ;AN000;
853READ_DOT_END: ;AN000;
854 POP DX ; Restore registers ;AN000;
855 POP CX ;AN000;
856 POP BX ;AN000;
857 RET ;AN000;
858READ_DOT ENDP ;AN000;