diff options
| author | 2024-04-25 21:24:10 +0100 | |
|---|---|---|
| committer | 2024-04-25 22:32:27 +0000 | |
| commit | 2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch) | |
| tree | 80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/CMD/GRAPHICS/GRBWPRT.ASM | |
| parent | Merge pull request #430 from jpbaltazar/typoptbr (diff) | |
| download | ms-dos-main.tar.gz ms-dos-main.tar.xz ms-dos-main.zip | |
Diffstat (limited to 'v4.0/src/CMD/GRAPHICS/GRBWPRT.ASM')
| -rw-r--r-- | v4.0/src/CMD/GRAPHICS/GRBWPRT.ASM | 631 |
1 files changed, 631 insertions, 0 deletions
diff --git a/v4.0/src/CMD/GRAPHICS/GRBWPRT.ASM b/v4.0/src/CMD/GRAPHICS/GRBWPRT.ASM new file mode 100644 index 0000000..7b09ffd --- /dev/null +++ b/v4.0/src/CMD/GRAPHICS/GRBWPRT.ASM | |||
| @@ -0,0 +1,631 @@ | |||
| 1 | PAGE ,132 ;AN000; | ||
| 2 | TITLE DOS GRAPHICS Command - Black and White printing modules | ||
| 3 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; | ||
| 4 | ;; DOS - GRAPHICS Command | ||
| 5 | ;; (c) Copyright 1988 Microsoft | ||
| 6 | ;; ;AN000; | ||
| 7 | ;; File Name: GRBWPRT.ASM ;AN000; | ||
| 8 | ;; ---------- ;AN000; | ||
| 9 | ;; ;AN000; | ||
| 10 | ;; Description: ;AN000; | ||
| 11 | ;; ------------ ;AN000; | ||
| 12 | ;; This file contains the code for printing a GRAPHICS screen on a ;AN000; | ||
| 13 | ;; BLACK and WHITE printer. ;AN000; | ||
| 14 | ;; ;AN000; | ||
| 15 | ;; Documentation Reference: ;AN000; | ||
| 16 | ;; ------------------------ ;AN000; | ||
| 17 | ;; OASIS High Level Design ;AN000; | ||
| 18 | ;; OASIS GRAPHICS I1 Overview ;AN000; | ||
| 19 | ;; ;AN000; | ||
| 20 | ;; Procedures Contained in This File: ;AN000; | ||
| 21 | ;; ---------------------------------- ;AN000; | ||
| 22 | ;; ;AN000; | ||
| 23 | ;; PRINT_BW_APA ;AN000; | ||
| 24 | ;; FILL_BUFFER ;AN000; | ||
| 25 | ;; INT2PAT ;AN000; | ||
| 26 | ;; PAT2BOX ;AN000; | ||
| 27 | ;; ;AN000; | ||
| 28 | ;; ;AN000; | ||
| 29 | ;; Include Files Required: ;AN000; | ||
| 30 | ;; ----------------------- ;AN000; | ||
| 31 | ;; GRCTRL.EXT - Externals for print screen control ;AN000; | ||
| 32 | ;; GRCTRL.STR - Structures and equates for print screen control ;AN000; | ||
| 33 | ;; GRPATTRN.STR - Structures for the printer patterns. ;AN000; | ||
| 34 | ;; ;AN000; | ||
| 35 | ;; GRSHAR.STR - Shared Data Area Structure ;AN000; | ||
| 36 | ;; ;AN000; | ||
| 37 | ;; STRUC.INC - Macros for using structured assembly language ;AN000; | ||
| 38 | ;; ;AN000; | ||
| 39 | ;; ;AN000; | ||
| 40 | ;; External Procedure References: ;AN000; | ||
| 41 | ;; ------------------------------ ;AN000; | ||
| 42 | ;; FROM FILE GRCTRL.ASM: ;AN000; | ||
| 43 | ;; PRT_SCR - Main module for printing the screen. ;AN000; | ||
| 44 | ;; TO FILE GRCOMMON.ASM ;AN000; | ||
| 45 | ;; Common modules - tools for printing a screen. ;AN000; | ||
| 46 | ;; ;AN000; | ||
| 47 | ;; Linkage Instructions: ;AN000; | ||
| 48 | ;; -------------------- ;AN000; | ||
| 49 | ;; This file is included by GRCTRL.ASM ;AN000; | ||
| 50 | ;; ;AN000; | ||
| 51 | ;; Change History: ;AN000; | ||
| 52 | ;; --------------- ;AN000; | ||
| 53 | ;; ;AN000; | ||
| 54 | ;; ;AN000; | ||
| 55 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000; | ||
| 56 | PAGE ;AN000; | ||
| 57 | CODE SEGMENT PUBLIC 'CODE' ;AN000; | ||
| 58 | ASSUME CS:CODE,DS:CODE ;AN000; | ||
| 59 | ;AN000; | ||
| 60 | PUBLIC PRINT_BW_APA ;AN000; | ||
| 61 | PUBLIC LEN_OF_BW_MODULES ;AN000; | ||
| 62 | ;AN000; | ||
| 63 | .XLIST ;AN000; | ||
| 64 | INCLUDE GRCTRL.STR ; Stuctures needed ;AN000; | ||
| 65 | INCLUDE GRSHAR.STR ; for both set of print modules ;AN000; | ||
| 66 | INCLUDE GRPATTRN.STR ; ;AN000; | ||
| 67 | INCLUDE GRCTRL.EXT ; Externals from PRT_SCR control module ;AN000; | ||
| 68 | INCLUDE STRUC.INC ; ;AN000; | ||
| 69 | ;AN000; | ||
| 70 | PUBLIC PRINT_BW_APA ; Black and white modules, ;AN000; | ||
| 71 | .LIST ;AN000; | ||
| 72 | ;===============================================================================;AN000; | ||
| 73 | ; ;AN000; | ||
| 74 | ; PRINT_BW_APA : PRINT A GRAPHIC MODE SCREEN ON A BLACK AND WHITE PRINTER ;AN000; | ||
| 75 | ; ;AN000; | ||
| 76 | ;-------------------------------------------------------------------------------;AN000; | ||
| 77 | ; ;AN000; | ||
| 78 | ; INPUT: BP = Offset of the shared data area ;AN000; | ||
| 79 | ; XLT_TAB = Color translation table ;AN000; | ||
| 80 | ; BIOS_INT_5H = Pointer to BIOS int 5h ;AN000; | ||
| 81 | ; ;AN000; | ||
| 82 | ; OUTPUT: PRINTER ;AN000; | ||
| 83 | ; ;AN000; | ||
| 84 | ;-------------------------------------------------------------------------------;AN000; | ||
| 85 | ; ;AN000; | ||
| 86 | ; DESCRIPTION: This procedure maps each pixel of the screen to a box ;AN000; | ||
| 87 | ; of dots on the printer. The box size depends on the screen resolution ;AN000; | ||
| 88 | ; and the number of bytes per printer line. It is chosen in order to ;AN000; | ||
| 89 | ; respect the screen ratio and is documented in each printer profile. ;AN000; | ||
| 90 | ; ;AN000; | ||
| 91 | ; For efficiency and space considerations, the print buffer does not ;AN000; | ||
| 92 | ; hold a full print line. Bytes representing pixels are printed as soon ;AN000; | ||
| 93 | ; as they are ready to be printed. However, the print buffer is wide ;AN000; | ||
| 94 | ; enough to hold complete boxes. ;AN000; | ||
| 95 | ; ;AN000; | ||
| 96 | ; The order for reading pixels off the screen is driven by the ;AN000; | ||
| 97 | ; order bytes are expected by the printer. To print the screen in its ;AN000; | ||
| 98 | ; original orientation we must begin reading it from the top left corner ;AN000; | ||
| 99 | ; and send the pixels line by line; to print it sideways, reading will ;AN000; | ||
| 100 | ; start from the bottom left corner and a "LINE" will now be a vertical ;AN000; | ||
| 101 | ; screen column read from bottom to top. ;AN000; | ||
| 102 | ; ;AN000; | ||
| 103 | ; There is more to it however, the printer head is printing a ;AN000; | ||
| 104 | ; vertical column of 8 dots at a time and each pixel read is mapped to ;AN000; | ||
| 105 | ; a box of dots that is less than 8 dots high (e.g., 2 cols x 1 row) ;AN000; | ||
| 106 | ; therefore, many boxes must be stored in the bytes sent to the printer. ;AN000; | ||
| 107 | ; ;AN000; | ||
| 108 | ; These boxes represent pixels that are one above each other on the ;AN000; | ||
| 109 | ; screen. We must read enough pixels on one column of the screen to use ;AN000; | ||
| 110 | ; all 8 bits of the vertical printer head (e.g., if the box size is 2x1 ;AN000; | ||
| 111 | ; then 8 pixels must be read and 2 bytes of the print buffer will be ;AN000; | ||
| 112 | ; filled). ;AN000; | ||
| 113 | ; ;AN000; | ||
| 114 | ; The PRINT BUFFER for any box size will be 8 bits high by "BOX ;AN000; | ||
| 115 | ; WIDTH" bits wide. ;AN000; | ||
| 116 | ; ;AN000; | ||
| 117 | ; After the buffer is filled, it is printed and the next "column" ;AN000; | ||
| 118 | ; of 8 pixels is read. Therefore, the screen is read "line by line" ;AN000; | ||
| 119 | ; where a line is 8 pixels high for a 2x1 box (4 pixels high for a 3x2 ;AN000; | ||
| 120 | ; box). ONE SUCH LINE IS CALLED A SCAN LINE. ;AN000; | ||
| 121 | ; ;AN000; | ||
| 122 | PAGE ;AN000; | ||
| 123 | ; ;AN000; | ||
| 124 | ; A 350X200 screen mapping to a 3x2 box is read in the following order: ;AN000; | ||
| 125 | ; ;AN000; | ||
| 126 | ; SCREEN: ;AN000; | ||
| 127 | ; ;AN000; | ||
| 128 | ; column column . . . column ;AN000; | ||
| 129 | ; no. 0 no. 1 no. 349 ;AN000; | ||
| 130 | ; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ;AN000; | ||
| 131 | ; scan º1(0,0) 5(0,1) 1397(0,349)º ;AN000; | ||
| 132 | ; line º2(1,0) 6(1,1) . . . . . . . 1398(1,349)º ;AN000; | ||
| 133 | ; no. 1 º3(2,0) 7(2,1) 1399(2,349)º ;AN000; | ||
| 134 | ; º4(3,0) 8(3,1) 1400(3,349)º ;AN000; | ||
| 135 | ; º º ;AN000; | ||
| 136 | ; scan º1401(4,0) 1405(4,1) º LEGEND: n(X,Y) ;AN000; | ||
| 137 | ; line º1402(5,0) etc, º ;AN000; | ||
| 138 | ; no. 2 º1403(6,0) . . . . . º n = READ RANK ;AN000; | ||
| 139 | ; º1404(7,0) º X = ROW NUMBER ;AN000; | ||
| 140 | ; º . º Y = COLUMN NUMBER ;AN000; | ||
| 141 | ; etc, º . º ;AN000; | ||
| 142 | ; º . 70000(199,349)º ;AN000; | ||
| 143 | ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ;AN000; | ||
| 144 | ; ;AN000; | ||
| 145 | ; ;AN000; | ||
| 146 | ; LOGIC : ;AN000; | ||
| 147 | ; ;AN000; | ||
| 148 | ; Initialize printer and local variables. ;AN000; | ||
| 149 | ; CALL LOC_MODE_PRT_INFO ; Get printer info related to current mode. ;AN000; | ||
| 150 | ; CALL GET_SCREEN_INFO ; Get info. about how to read the screen ;AN000; | ||
| 151 | ; CALL SETUP_PRT ; Set up the printer (Line spacing, etc) ;AN000; | ||
| 152 | ; ;AN000; | ||
| 153 | ; FOR each scan line on the screen (NB_SCAN_LINES) ;AN000; | ||
| 154 | ; (Note: One scan line maps to one print line) ;AN000; | ||
| 155 | ; BEGIN ;AN000; | ||
| 156 | ; CALL DET_CUR_SCAN_LNE_LENGTH ; Determine length in pels of the current ;AN000; | ||
| 157 | ; ; scan line. ;AN000; | ||
| 158 | ; IF CUR_SCAN_LNE_LENGTH NE 0 THEN ;AN000; | ||
| 159 | ; CALL NEW_PRT_LINE ; Initialize a new printer line ;AN000; | ||
| 160 | ; DO CUR_SCAN_LNE_LENGTH times ; For each column ;AN000; | ||
| 161 | ; BEGIN ;AN000; | ||
| 162 | ; CALL FILL_BUFFER ; Read top-down enough pels to fill the buffer ;AN000; | ||
| 163 | ; CALL PRINT_BUFFER ; Print the buffer ;AN000; | ||
| 164 | ; IF printing sideways THEN INC CUR_ROW ; Get coordinates of next ;AN000; | ||
| 165 | ; ELSE INC CUR_COLUMN ; "column" (vertical chunk of ;AN000; | ||
| 166 | ; END (for each column) ; a scan line). ;AN000; | ||
| 167 | ; PRINT_BYTE CR ; Print a CR and a LF ;AN000; | ||
| 168 | ; PRINT_BYTE LF ;AN000; | ||
| 169 | ; ; Get coordinates of next scan line: ;AN000; | ||
| 170 | ; IF printing sideways THEN ;AN000; | ||
| 171 | ; ADD CUR_COLUMN,NB_BOXES_PER_PRT_BUF ;AN000; | ||
| 172 | ; MOV CUR_ROW,SCREEN_HEIGHT - 1 ;AN000; | ||
| 173 | ; ELSE ;AN000; | ||
| 174 | ; ADD CUR_ROW,NB_BOXES_PER_PRT_BUF ;AN000; | ||
| 175 | ; MOV CUR_COLUMN,0 ;AN000; | ||
| 176 | ; END (for each scan line) ;AN000; | ||
| 177 | ; ;AN000; | ||
| 178 | PRINT_BW_APA PROC NEAR ;AN000; | ||
| 179 | PUSH AX ;AN000; | ||
| 180 | PUSH BX ;AN000; | ||
| 181 | PUSH CX ;AN000; | ||
| 182 | ;AN000; | ||
| 183 | ;-------------------------------------------------------------------------------;AN000; | ||
| 184 | ; ;AN000; | ||
| 185 | ; INITIALIZATION: ;AN000; | ||
| 186 | ; ;AN000; | ||
| 187 | ; 1) Locate and extract printer DISPLAYMODE information from ;AN000; | ||
| 188 | ; the shared data area, calculate the number of boxes fitting ;AN000; | ||
| 189 | ; in the printer buffer. ;AN000; | ||
| 190 | ; 2) Determine where to start reading the screen: ;AN000; | ||
| 191 | ; If printing sideways, start in LOW LEFT corner. ;AN000; | ||
| 192 | ; If normal printing, start in TOP LEFT corner. ;AN000; | ||
| 193 | ; Determine the maximum length for a scan line: ;AN000; | ||
| 194 | ; If printing sideways, it is the height of the screen. ;AN000; | ||
| 195 | ; For normal printing, it is the width of the screen. ;AN000; | ||
| 196 | ; Determine the number of scan lines on the screen. ;AN000; | ||
| 197 | ; 3) Set up the Printer for printing Graphics. ;AN000; | ||
| 198 | ; ;AN000; | ||
| 199 | ;-------------------------------------------------------------------------------;AN000; | ||
| 200 | CALL LOC_MODE_PRT_INFO ; Get printer info related to curr. mode;AN000; | ||
| 201 | ; ;AN000; | ||
| 202 | ;-------Test if DISPLAYMODE info record was found: ;AN000; | ||
| 203 | .IF <ERROR_CODE EQ DISPLAYMODE_INFO_NOT_FOUND> ;AN000; | ||
| 204 | .THEN ;AN000; | ||
| 205 | MOV ERROR_CODE,UNABLE_TO_PRINT ; IF no record found, ;AN000; | ||
| 206 | JMP PRINT_BW_APA_END ; then, return error code ;AN000; | ||
| 207 | .ENDIF ; and quit procedure ;AN000; | ||
| 208 | ; ;AN000; | ||
| 209 | ;-------Get the box size from the DISPLAYMODE info record: ;AN000; | ||
| 210 | MOV BX,CUR_MODE_PTR ; BX := Offset current DISPLAYMODE info.;AN000; | ||
| 211 | MOV AH,[BX].BOX_WIDTH ; Take local copy of the box size. ;AN000; | ||
| 212 | MOV BOX_W,AH ; in BOX_W and BOX_H ;AN000; | ||
| 213 | MOV AL,[BX].BOX_HEIGHT ;AN000; | ||
| 214 | MOV BOX_H,AL ;AN000; | ||
| 215 | ; ;AN000; | ||
| 216 | ;-------Verify if the box size obtained from DISPLAYMODE info. is valid ;AN000; | ||
| 217 | .IF <ZERO AL> OR ; IF height of the box is 0 ;AN000; | ||
| 218 | .IF <ZERO AH> ; OR width of the box is 0 ;AN000; | ||
| 219 | .THEN ; THEN we can't print: ;AN000; | ||
| 220 | MOV ERROR_CODE,UNABLE_TO_PRINT ; return error code ;AN000; | ||
| 221 | JMP PRINT_BW_APA_END ; and quit ;AN000; | ||
| 222 | .ENDIF ;AN000; | ||
| 223 | ; ;AN000; | ||
| 224 | ;-------Get the Print Orientation from the DISPLAYMODE info record ;AN000; | ||
| 225 | .IF <[BX].PRINT_OPTIONS EQ ROTATE>; If printing sideways ;AN000; | ||
| 226 | .THEN ; then: ;AN000; | ||
| 227 | MOV ROTATE_SW,ON ; Rotate switch := "ON" ;AN000; | ||
| 228 | .ENDIF ;AN000; | ||
| 229 | ;AN000; | ||
| 230 | ; ;AN000; | ||
| 231 | ;-------Initialize print variables and the printer: ;AN000; | ||
| 232 | CALL GET_SCREEN_INFO ; Get info. about how to read the screen;AN000; | ||
| 233 | CALL SETUP_PRT ; Set up the printer (Line spacing, etc);AN000; | ||
| 234 | .IF <BIT ERROR_CODE NZ PRINTER_ERROR> ;AN000; | ||
| 235 | .THEN ; A printer error occurred: quit ;AN000; | ||
| 236 | JMP PRINT_BW_APA_END ; ;AN000; | ||
| 237 | .ENDIF ;AN000; | ||
| 238 | ;AN000; | ||
| 239 | MOV CX,NB_SCAN_LINES ;AN000; | ||
| 240 | ;-------------------------------------------------------------------------------;AN000; | ||
| 241 | ; ;AN000; | ||
| 242 | ; FOR EACH SCAN LINE ON THE SCREEN: ;AN000; | ||
| 243 | ; ;AN000; | ||
| 244 | ;-------------------------------------------------------------------------------;AN000; | ||
| 245 | PRINT_1_SCAN_LINE: ;AN000; | ||
| 246 | CALL DET_CUR_SCAN_LNE_LENGTH ; Determine how many non-blanks on line ;AN000; | ||
| 247 | .IF <CUR_SCAN_LNE_LENGTH NE 0> ; If line is not empty ;AN000; | ||
| 248 | .THEN ; then, ;AN000; | ||
| 249 | CALL NEW_PRT_LINE ; Send escape sequence to the printer ;AN000; | ||
| 250 | .IF <BIT ERROR_CODE NZ PRINTER_ERROR> ; for starting a new line. ;AN000; | ||
| 251 | .THEN ; If a printer error occurred: ;AN000; | ||
| 252 | JMP PRINT_BW_APA_END ; Quit ! ;AN000; | ||
| 253 | .ENDIF ;AN000; | ||
| 254 | ;AN000; | ||
| 255 | PUSH CX ; Save scan line counter ;AN000; | ||
| 256 | MOV CX,CUR_SCAN_LNE_LENGTH ;AN000; | ||
| 257 | ;-------------------------------------------------------------------------------;AN000; | ||
| 258 | ; ;AN000; | ||
| 259 | ; FOR each column on the current scan line (up to the last non-blank): ;AN000; | ||
| 260 | ; ;AN000; | ||
| 261 | ;-------------------------------------------------------------------------------;AN000; | ||
| 262 | PRINT_1_SCAN_COLUMN: ;AN000; | ||
| 263 | CALL FILL_BUFFER ; Read all pixels on this column, ;AN000; | ||
| 264 | ; convert each to a printer box, ;AN000; | ||
| 265 | ; store boxes in the print buffer ;AN000; | ||
| 266 | ; (a buffer contains one "column" ;AN000; | ||
| 267 | ; of pixels). ;AN000; | ||
| 268 | CALL PRINT_BUFFER ; Print the buffer. ;AN000; | ||
| 269 | .IF <BIT ERROR_CODE NZ PRINTER_ERROR> ;AN000; | ||
| 270 | .THEN ; A printer error occurred: ;AN000; | ||
| 271 | POP CX ; Restore scan line counter and quit ;AN000; | ||
| 272 | JMP PRINT_BW_APA_END ; ;AN000; | ||
| 273 | .ENDIF ;AN000; | ||
| 274 | ;AN000; | ||
| 275 | ;AN000; | ||
| 276 | ;-------Get coordinates of next "column": ;AN000; | ||
| 277 | .IF <ROTATE_SW EQ ON> ; If printing sideways ;AN000; | ||
| 278 | .THEN ; ;AN000; | ||
| 279 | DEC CUR_ROW ; then, get row above on screen ;AN000; | ||
| 280 | .ELSE ; ;AN000; | ||
| 281 | INC CUR_COLUMN ; else, get column next right ;AN000; | ||
| 282 | .ENDIF ; ;AN000; | ||
| 283 | ;AN000; | ||
| 284 | LOOP PRINT_1_SCAN_COLUMN ; Print next column ;AN000; | ||
| 285 | ;AN000; | ||
| 286 | POP CX ; Restore scan line counter ;AN000; | ||
| 287 | .ENDIF ; Endif line is not empty ;AN000; | ||
| 288 | ;-------------------------------------------------------------------------------;AN000; | ||
| 289 | ; ;AN000; | ||
| 290 | ; Print a carriage return and a line feed: ;AN000; | ||
| 291 | ; ;AN000; | ||
| 292 | ;-------------------------------------------------------------------------------;AN000; | ||
| 293 | MOV AL,CR ;AN000; | ||
| 294 | CALL PRINT_BYTE ; Send CR ;AN000; | ||
| 295 | JC PRINT_BW_APA_END ; If printer error, leave ;AN000; | ||
| 296 | MOV AL,LF ;AN000; | ||
| 297 | CALL PRINT_BYTE ; Send LF ;AN000; | ||
| 298 | JC PRINT_BW_APA_END ; If printer error, leave ;AN000; | ||
| 299 | ;-------------------------------------------------------------------------------;AN000; | ||
| 300 | ; ;AN000; | ||
| 301 | ; Get coordinates of next scan line: ;AN000; | ||
| 302 | ; ;AN000; | ||
| 303 | ;-------------------------------------------------------------------------------;AN000; | ||
| 304 | .IF <ROTATE_SW EQ ON> ; If printing sideways ;AN000; | ||
| 305 | .THEN ; then: ;AN000; | ||
| 306 | MOV AL,NB_BOXES_PER_PRT_BUF ; AX := Numbers of pels read on row ;AN000; | ||
| 307 | CBW ; ;AN000; | ||
| 308 | ADD CUR_COLUMN,AX ; CUR_COLUMN + Number of pels read ;AN000; | ||
| 309 | MOV AX,SCREEN_HEIGHT ; CUR_ROW := SCREEN_HEIGHT - 1 ;AN000; | ||
| 310 | DEC AX ; ;AN000; | ||
| 311 | MOV CUR_ROW,AX ; ;AN000; | ||
| 312 | .ELSE ; else, printing NOT rotated: ;AN000; | ||
| 313 | MOV AL,NB_BOXES_PER_PRT_BUF ; AX := Number of pels read on colum;AN000; | ||
| 314 | CBW ; ;AN000; | ||
| 315 | ADD CUR_ROW,AX ; CUR_ROW + Number of pels read ;AN000; | ||
| 316 | MOV CUR_COLUMN,0 ; CUR_COLUMN := 0 ;AN000; | ||
| 317 | .ENDIF ; ;AN000; | ||
| 318 | LOOP PRINT_1_SCAN_LINE ; ;AN000; | ||
| 319 | ;AN000; | ||
| 320 | ;-------------------------------------------------------------------------------;AN000; | ||
| 321 | ; ;AN000; | ||
| 322 | ; Restore the printer. ;AN000; | ||
| 323 | ; ;AN000; | ||
| 324 | ;-------------------------------------------------------------------------------;AN000; | ||
| 325 | CALL RESTORE_PRT ;AN000; | ||
| 326 | PRINT_BW_APA_END: ;AN000; | ||
| 327 | POP CX ;AN000; | ||
| 328 | POP BX ;AN000; | ||
| 329 | POP AX ;AN000; | ||
| 330 | RET ;AN000; | ||
| 331 | PRINT_BW_APA ENDP ;AN000; | ||
| 332 | PAGE ;AN000; | ||
| 333 | ;===============================================================================;AN000; | ||
| 334 | ; ;AN000; | ||
| 335 | ; FILL_BUFFER : READS ENOUGH PIXELS TO FILL UP THE PRINT BUFFER. ;AN000; | ||
| 336 | ; THESE PIXELS ARE MAPPED TO A PRINTER DOT BOX. ;AN000; | ||
| 337 | ; ;AN000; | ||
| 338 | ;-------------------------------------------------------------------------------;AN000; | ||
| 339 | ; ;AN000; | ||
| 340 | ; INPUT: CUR_COLUMN, ;AN000; | ||
| 341 | ; CUR_ROW = Coordinates of the first pixel to be read ;AN000; | ||
| 342 | ; BOXES_PER_PRT_BUF = Number of boxes fitting in the print ;AN000; | ||
| 343 | ; buffer ;AN000; | ||
| 344 | ; XLT_TAB = Color translation table ;AN000; | ||
| 345 | ; ;AN000; | ||
| 346 | ; OUTPUT: PRT_BUF = PRINT BUFFER ;AN000; | ||
| 347 | ; ;AN000; | ||
| 348 | ;-------------------------------------------------------------------------------;AN000; | ||
| 349 | ; ;AN000; | ||
| 350 | ; DESCRIPTION: ;AN000; | ||
| 351 | ; ;AN000; | ||
| 352 | ; 1) Pixels are read one by one vertically from top to bottom in ;AN000; | ||
| 353 | ; the current column of the screen scan line. ;AN000; | ||
| 354 | ; NOTE: What is called here a 'column' can actually be a line ;AN000; | ||
| 355 | ; on the physical display. ;AN000; | ||
| 356 | ; 2) Each pixel is mapped to a printer dot box. ;AN000; | ||
| 357 | ; 3) Each Dot box is stored in the printer buffer. ;AN000; | ||
| 358 | ; 4) The coordinates in input are those of the "top" pixel ;AN000; | ||
| 359 | ; and restored when leaving this procedure. ;AN000; | ||
| 360 | ; ;AN000; | ||
| 361 | ; ;AN000; | ||
| 362 | ; LOGIC: ;AN000; | ||
| 363 | ; ;AN000; | ||
| 364 | ; Save coordinates of the current "column" (slice of a screen scan line) ;AN000; | ||
| 365 | ; DO for BOXES_PER_PRT_BUF (8 / BOX_H) ;AN000; | ||
| 366 | ; BEGIN ;AN000; | ||
| 367 | ; CALL READ_DOT ; Read a pixel, get index in XLT_TAB ;AN000; | ||
| 368 | ; Get pixel intensity from XLT_TAB ;AN000; | ||
| 369 | ; CALL INT2PAT ; Locate pattern corresponding to int. ;AN000; | ||
| 370 | ; CALL PAT2BOX ; Extract box from pattern ;AN000; | ||
| 371 | ; CALL STORE_BOX ; Store the box in the printer buffer ;AN000; | ||
| 372 | ; ; Get coordinates of next pixel below: ;AN000; | ||
| 373 | ; IF printing is sideways THEN INC CUR_COLUMN ;AN000; | ||
| 374 | ; ELSE INC CUR_ROW ;AN000; | ||
| 375 | ; END ;AN000; | ||
| 376 | ; Restore initial coordinates. ;AN000; | ||
| 377 | ; ;AN000; | ||
| 378 | FILL_BUFFER PROC NEAR ;AN000; | ||
| 379 | PUSH AX ;AN000; | ||
| 380 | PUSH BX ;AN000; | ||
| 381 | PUSH CX ;AN000; | ||
| 382 | PUSH SI ;AN000; | ||
| 383 | PUSH DI ;AN000; | ||
| 384 | ;AN000; | ||
| 385 | ;-------------------------------------------------------------------------------;AN000; | ||
| 386 | ; ;AN000; | ||
| 387 | ; Save initial coordinates: ;AN000; | ||
| 388 | ; ;AN000; | ||
| 389 | ;-------------------------------------------------------------------------------;AN000; | ||
| 390 | PUSH CUR_ROW ;AN000; | ||
| 391 | PUSH CUR_COLUMN ;AN000; | ||
| 392 | ;AN000; | ||
| 393 | ;-------Clear the print buffer: ;AN000; | ||
| 394 | XOR BX,BX ; For each byte in the PRT_BUF: ;AN000; | ||
| 395 | CLEAR_PRT_BUF: ;AN000; | ||
| 396 | MOV PRT_BUF[BX],0 ; Initialize byte to blanks ;AN000; | ||
| 397 | INC BX ; Get next byte ;AN000; | ||
| 398 | CMP BL,BOX_W ; All bytes cleared ? ;AN000; | ||
| 399 | JL CLEAR_PRT_BUF ; No, clear next one. ;AN000; | ||
| 400 | ;AN000; | ||
| 401 | MOV BX,OFFSET XLT_TAB ; BX := Offset of XLT_TAB ;AN000; | ||
| 402 | ;AN000; | ||
| 403 | ;-------Fill the print buffer with one box for each pixel read: ;AN000; | ||
| 404 | XOR CX,CX ; CL := Number of pixels to read ;AN000; | ||
| 405 | MOV CL,NB_BOXES_PER_PRT_BUF ;AN000; | ||
| 406 | ;-------------------------------------------------------------------------------;AN000; | ||
| 407 | ; ;AN000; | ||
| 408 | ; For each pixel within the current column of the scan line: ;AN000; | ||
| 409 | ; ;AN000; | ||
| 410 | ;-------------------------------------------------------------------------------;AN000; | ||
| 411 | READ_AND_STORE_1_PIXEL: ;AN000; | ||
| 412 | CALL READ_DOT ; AL := Index into translation table ;AN000; | ||
| 413 | XLAT XLT_TAB ; AL := Intensity ;AN000; | ||
| 414 | CALL INT2PAT ; SI := Offset of matching Pattern ;AN000; | ||
| 415 | CALL PAT2BOX ; Extract CUR_BOX from the pattern. ;AN000; | ||
| 416 | MOV SI,OFFSET CUR_BOX ; Store it in the PRT_BUF ;AN000; | ||
| 417 | CALL STORE_BOX ;AN000; | ||
| 418 | ;AN000; | ||
| 419 | ;-------Get coordinates of next pixel: ;AN000; | ||
| 420 | .IF <ROTATE_SW EQ ON> ; If printing sideways ;AN000; | ||
| 421 | .THEN ; ;AN000; | ||
| 422 | INC CUR_COLUMN ; then, increment column number ;AN000; | ||
| 423 | .ELSE ; ;AN000; | ||
| 424 | INC CUR_ROW ; else, increment row number ;AN000; | ||
| 425 | .ENDIF ; ;AN000; | ||
| 426 | LOOP READ_AND_STORE_1_PIXEL ;AN000; | ||
| 427 | ;AN000; | ||
| 428 | ;-------------------------------------------------------------------------------;AN000; | ||
| 429 | ; ;AN000; | ||
| 430 | ; Restore initial coordinates: ;AN000; | ||
| 431 | ; ;AN000; | ||
| 432 | ;-------------------------------------------------------------------------------;AN000; | ||
| 433 | POP CUR_COLUMN ;AN000; | ||
| 434 | POP CUR_ROW ;AN000; | ||
| 435 | ;AN000; | ||
| 436 | POP DI ;AN000; | ||
| 437 | POP SI ;AN000; | ||
| 438 | POP CX ;AN000; | ||
| 439 | POP BX ;AN000; | ||
| 440 | POP AX ;AN000; | ||
| 441 | RET ;AN000; | ||
| 442 | FILL_BUFFER ENDP ;AN000; | ||
| 443 | PAGE ;AN000; | ||
| 444 | ;===============================================================================;AN000; | ||
| 445 | ; ;AN000; | ||
| 446 | ; INT2PAT : MAP AN INTENSITY TO A PATTERN. ;AN000; | ||
| 447 | ; ;AN000; | ||
| 448 | ;-------------------------------------------------------------------------------;AN000; | ||
| 449 | ; ;AN000; | ||
| 450 | ; INPUT: AL = GREY INTENSITY (0 - 63 = BLACK to WHITE) ;AN000; | ||
| 451 | ; BOX_W = Number of columns in a box ;AN000; | ||
| 452 | ; CUR_MODE_PTR = Offset of current DISPLAYMODE info record ;AN000; | ||
| 453 | ; ;AN000; | ||
| 454 | ; OUTPUT: SI = OFFSET OF THE PATTERN MATCHING THE INTENSITY ;AN000; | ||
| 455 | ; ;AN000; | ||
| 456 | ;-------------------------------------------------------------------------------;AN000; | ||
| 457 | ; ;AN000; | ||
| 458 | ; DESCRIPTION: Performs a sequential search in the table of patterns ;AN000; | ||
| 459 | ; until the proper pattern is found. ;AN000; | ||
| 460 | ; ;AN000; | ||
| 461 | ; ;AN000; | ||
| 462 | ; SI = 0 ; FOUND = FALSE ;AN000; | ||
| 463 | ; DO UNTIL FOUND = TRUE ;AN000; | ||
| 464 | ; BEGIN ;AN000; | ||
| 465 | ; IF AL <= Maximum intensity of the current pattern in the table ;AN000; | ||
| 466 | ; THEN ;AN000; | ||
| 467 | ; FOUND = TRUE ;AN000; | ||
| 468 | ; ELSE ;AN000; | ||
| 469 | ; SI = SI + (BOX_W * 2) ;AN000; | ||
| 470 | ; END ;AN000; | ||
| 471 | ; ;AN000; | ||
| 472 | INT2PAT PROC NEAR ;AN000; | ||
| 473 | PUSH AX ;AN000; | ||
| 474 | PUSH BX ;AN000; | ||
| 475 | PUSH DX ;AN000; | ||
| 476 | ;AN000; | ||
| 477 | ;-------Calculate the size in bytes of one pattern STRUCTURE: (see GRPATTRN.STR);AN000; | ||
| 478 | MOV DL,BOX_W ; DX := Number of columns in the box ;AN000; | ||
| 479 | XOR DH,DH ;AN000; | ||
| 480 | SHL DL,1 ; (DX * 2) = Number of columns in the pattern ;AN000; | ||
| 481 | INC DL ; DL := Size in bytes of one pattern ;AN000; | ||
| 482 | ; (includes intensity field) ;AN000; | ||
| 483 | MOV BX,CUR_MODE_PTR ; BX := Offset of current mode ;AN000; | ||
| 484 | ; SI := Offset of the first pattern ;AN000; | ||
| 485 | MOV SI,[BX].PATTERN_TAB_PTR ;AN000; | ||
| 486 | ADD SI,BP ;AN000; | ||
| 487 | ;AN000; | ||
| 488 | COMPARE_INTENSITY: ;AN000; | ||
| 489 | CMP AL,[SI] ; Within the range of this pattern ? ;AN000; | ||
| 490 | JLE FOUND_PATTERN ; Yes, use this pattern. ;AN000; | ||
| 491 | ; No, look at next pattern: ;AN000; | ||
| 492 | ADD SI,DX ; SI := SI + Number columns in pattern) ;AN000; | ||
| 493 | JMP SHORT COMPARE_INTENSITY ;AN000; | ||
| 494 | ;AN000; | ||
| 495 | FOUND_PATTERN: ;AN000; | ||
| 496 | ;AN000; | ||
| 497 | POP DX ;AN000; | ||
| 498 | POP BX ;AN000; | ||
| 499 | POP AX ;AN000; | ||
| 500 | RET ;AN000; | ||
| 501 | ;AN000; | ||
| 502 | INT2PAT ENDP ;AN000; | ||
| 503 | PAGE ;AN000; | ||
| 504 | ;===============================================================================;AN000; | ||
| 505 | ; ;AN000; | ||
| 506 | ; PAT2BOX : SELECT AND EXTRACT THE PROPER BOX FROM THE PATTERN ACCORDING ;AN000; | ||
| 507 | ; TO THE COORDINATES OF THE PIXEL. ;AN000; | ||
| 508 | ; ;AN000; | ||
| 509 | ;-------------------------------------------------------------------------------;AN000; | ||
| 510 | ; ;AN000; | ||
| 511 | ; INPUT: SI = OFFSET OF CURRENT PATTERN ;AN000; | ||
| 512 | ; CUR_COLUMN, ;AN000; | ||
| 513 | ; CUR_ROW = COORDINATES OF THE CURRENT PIXEL ;AN000; | ||
| 514 | ; ;AN000; | ||
| 515 | ; OUTPUT: CUR_BOX = PORTION OF THE PATTERN TO BE PRINTED ;AN000; | ||
| 516 | ; ;AN000; | ||
| 517 | ;-------------------------------------------------------------------------------;AN000; | ||
| 518 | ; ;AN000; | ||
| 519 | ; DESCRIPTION: If the pixel is on even-even coordinates, then the ;AN000; | ||
| 520 | ; top-left box of the pattern is extracted. ;AN000; | ||
| 521 | ; If its Even-odd --> extract the top-right box. ;AN000; | ||
| 522 | ; Odd-even --> low-left box, and Odd-odd --> low-right box. ;AN000; | ||
| 523 | ; ;AN000; | ||
| 524 | PAGE ;AN000; | ||
| 525 | ; For example., (with a 3x2 box): ;AN000; | ||
| 526 | ; ;AN000; | ||
| 527 | ; PATTERN (over 6 bytes): ;AN000; | ||
| 528 | ; ;AN000; | ||
| 529 | ; ;AN000; | ||
| 530 | ; byte1 byte2 byte3 byte4 byte5 byte6 ;AN000; | ||
| 531 | ; ;AN000; | ||
| 532 | ; 0 0 0 0 0 0 ;AN000; | ||
| 533 | ; 0 0 0 0 0 0 ;AN000; | ||
| 534 | ; 0 0 0 0 0 0 ;AN000; | ||
| 535 | ; 0 0 0 0 0 0 ;AN000; | ||
| 536 | ; even-even --> dot1 dot2 dot3 | dot1 dot2 dot3 <-- even-odd ;AN000; | ||
| 537 | ; (row-column) dot4 dot5 dot6 | dot4 dot5 dot6 box ;AN000; | ||
| 538 | ; box. ------------------------------------------------ ;AN000; | ||
| 539 | ; odd-even --> dot1 dot2 dot3 | dot1 dot2 dot3 <-- odd-odd ;AN000; | ||
| 540 | ; box dot4 dot5 dot6 | dot4 dot5 dot6 box ;AN000; | ||
| 541 | ; ;AN000; | ||
| 542 | ; ;AN000; | ||
| 543 | ; The selected box is then stored as follow: ;AN000; | ||
| 544 | ; ;AN000; | ||
| 545 | ; CUR_BOX: ;AN000; | ||
| 546 | ; byte1 byte2 byte3 ;AN000; | ||
| 547 | ; MSB ------> 0 0 0 ;AN000; | ||
| 548 | ; (bit7) 0 0 0 ;AN000; | ||
| 549 | ; 0 0 0 ;AN000; | ||
| 550 | ; 0 0 0 ;AN000; | ||
| 551 | ; 0 0 0 ;AN000; | ||
| 552 | ; 0 0 0 ;AN000; | ||
| 553 | ; dot1 dot2 dot3 <-- box ;AN000; | ||
| 554 | ; LSB ------>dot4 dot5 dot6 ;AN000; | ||
| 555 | ; ;AN000; | ||
| 556 | ; LOGIC: ;AN000; | ||
| 557 | ; IF CUR_ROW is odd ;AN000; | ||
| 558 | ; THEN SI := SI + BOX_W ; Access right portion of pattern ;AN000; | ||
| 559 | ; Build a bit mask in BL of BOX_H bits, right justified. ;AN000; | ||
| 560 | ; FOR each column in the box (BOX_W) ;AN000; | ||
| 561 | ; Get the pattern column in AL ;AN000; | ||
| 562 | ; IF CUR_COLUMN is even ;AN000; | ||
| 563 | ; THEN ;AN000; | ||
| 564 | ; Move down the column of the top box. ;AN000; | ||
| 565 | ; AND BL,AL ; BL <-- Column of the desired box ;AN000; | ||
| 566 | ; ;AN000; | ||
| 567 | ; ;AN000; | ||
| 568 | PAT2BOX PROC NEAR ;AN000; | ||
| 569 | PUSH AX ;AN000; | ||
| 570 | PUSH BX ;AN000; | ||
| 571 | PUSH CX ;AN000; | ||
| 572 | PUSH SI ;AN000; | ||
| 573 | ;AN000; | ||
| 574 | ; SI := Offset of current pattern ;AN000; | ||
| 575 | INC SI ; Skip the MAX INTENSITY field ;AN000; | ||
| 576 | ;-------------------------------------------------------------------------------;AN000; | ||
| 577 | ; ;AN000; | ||
| 578 | ; Set SI to either the left or right set of 2 boxes in the pattern: ;AN000; | ||
| 579 | ; ;AN000; | ||
| 580 | ;-------------------------------------------------------------------------------;AN000; | ||
| 581 | TEST CUR_ROW,1 ; Odd row ? ;AN000; | ||
| 582 | JZ EXTRACT_BOX ; No, access left portion of pattern ;AN000; | ||
| 583 | MOV AL,BOX_W ; ;AN000; | ||
| 584 | CBW ; ;AN000; | ||
| 585 | ADD SI,AX ; Yes, access right portion of pattern;AN000; | ||
| 586 | ;AN000; | ||
| 587 | ;-------------------------------------------------------------------------------;AN000; | ||
| 588 | ; ;AN000; | ||
| 589 | ; Extract the box: ;AN000; | ||
| 590 | ; ;AN000; | ||
| 591 | ;-------------------------------------------------------------------------------;AN000; | ||
| 592 | EXTRACT_BOX: ;AN000; | ||
| 593 | ;-------Build a bit mask that will be used to keep only BOX_H bits ;AN000; | ||
| 594 | ;-------of the bytes where CUR_BOX is stored. ;AN000; | ||
| 595 | XOR AH,AH ; AH := Box column bit mask ;AN000; | ||
| 596 | MOV AL,BOX_H ; For each row of the box: ;AN000; | ||
| 597 | INIT_MASK: ; ;AN000; | ||
| 598 | SHL AH,1 ; ;AN000; | ||
| 599 | OR AH,1 ; Insert one bit in the mask. ;AN000; | ||
| 600 | DEC AL ; ;AN000; | ||
| 601 | CMP AL,0 ; ;AN000; | ||
| 602 | JG INIT_MASK ;AN000; | ||
| 603 | ;AN000; | ||
| 604 | XOR BX,BX ; BL := Column number within the box ;AN000; | ||
| 605 | ; ;AN000; | ||
| 606 | ;-------For each column of the box: ;AN000; | ||
| 607 | EXTRACT_1_BOX_COLUMN: ;AN000; | ||
| 608 | MOV AL,[SI] ; AL := Current column of pattern ;AN000; | ||
| 609 | TEST CUR_COLUMN,1 ; If the pixel is on ODD column ;AN000; | ||
| 610 | JNZ BOTTOM_BOX ; Then, need bottom box portion ;AN000; | ||
| 611 | MOV CL,BOX_H ; Else, need top box portion ;AN000; | ||
| 612 | TOP_BOX: ; Need top box: ;AN000; | ||
| 613 | SHR AL,CL ; Shift top box over bottom box ;AN000; | ||
| 614 | BOTTOM_BOX: ; The box we want is now at bottom ;AN000; | ||
| 615 | AND AL,AH ; Keep only bits from the box ;AN000; | ||
| 616 | MOV CUR_BOX[BX],AL ; Store this box column ;AN000; | ||
| 617 | INC SI ; Access next column of the pattern ;AN000; | ||
| 618 | INC BX ; One more column stored. ;AN000; | ||
| 619 | CMP BL,BOX_W ; All stored ? ;AN000; | ||
| 620 | JL EXTRACT_1_BOX_COLUMN ; No, continue ;AN000; | ||
| 621 | ;AN000; | ||
| 622 | POP SI ;AN000; | ||
| 623 | POP CX ;AN000; | ||
| 624 | POP BX ;AN000; | ||
| 625 | POP AX ;AN000; | ||
| 626 | RET ;AN000; | ||
| 627 | PAT2BOX ENDP ;AN000; | ||
| 628 | INCLUDE GRCOMMON.ASM ;AN000; | ||
| 629 | LEN_OF_BW_MODULES EQU $-PRINT_BW_APA ;AN000; | ||
| 630 | CODE ENDS ;AN000; | ||
| 631 | END ;AN000; | ||