|Previous||Table of Contents||Next|
Thats an interesting application of write mode 2, you may well say, but is it really useful? While the ability to convert chunky bitmaps into VGA bitmaps does have its uses, Listing 27.1 is primarily intended to illustrate the mechanics of write mode 2.
|For performance, its best to store 16-color bitmaps in pre-separated four-plane format in system memory, and copy one plane at a time to the screen. Ideally, such bitmaps should be copied one scan line at a time, with all four planes completed for one scan line before moving on to the next. I say this because when entire images are copied one plane at a time, nasty transient color effects can occur as one plane becomes visibly changed before other planes have been modified.|
A more serviceable use of write mode 2 is shown in the program presented in Listing 27.2. The program draws multicolored horizontal, vertical, and diagonal lines, basing the color patterns on passed color tables. Write mode 2 is ideal because in this application color can vary from one pixel to the next, and in write mode 2 all thats required to set pixel color is a change of the lower nibble of the byte written by the CPU. Set/reset could be used to achieve the same result, but an index/data pair of OUTs would be required to set the Set/Reset register to each new color. Similarly, the Map Mask register could be used in write mode 0 to set pixel color, but in this case not only would an index/data pair of OUTs be required but there would also be no guarantee that data already in display memory wouldnt interfere with the color of the pixel being drawn, since the Map Mask register allows only selected planes to be drawn to.
Listing 27.2 is hardly a comprehensive line drawing program. It draws only a few special line cases, and although it is reasonably fast, it is far from the fastest possible code to handle those cases, because it goes through a dot-plot routine and because it draws horizontal lines a pixel rather than a byte at a time. Write mode 2 would, however, serve just as well in a full-blown line drawing routine. For any type of patterned line drawing on the VGA, the basic approach remains the same: Use the bit mask to select the pixel (or pixels) to be altered and use the CPU byte in write mode 2 to select the color in which to draw.
LISTING 27.2 L27-2.ASM
; Program to illustrate one use of write mode 2 of the VGA and EGA by ; drawing lines in color patterns. ; ; Assemble with MASM or TASM ; ; By Michael Abrash ; Stack segment para stack STACK db 512 dup(0) Stack ends SCREEN_WIDTH_IN_BYTES equ 80 GRAPHICS_SEGMENT equ 0a000h ;mode 10 bit-map segment SC_INDEX equ 3c4h ;Sequence Controller Index register MAP_MASK equ 2 ;index of Map Mask register GC_INDEX equ 03ceh ;Graphics Controller Index reg GRAPHICS_MODE equ 5 ;index of Graphics Mode reg BIT_MASK equ 8 ;index of Bit Mask reg Data segment para common DATA Pattern0 db 16 db 0, 1, 2, 3, 4, 5, 6, 7, 8 db 9, 10, 11, 12, 13, 14, 15 Pattern1 db 6 db 2, 2, 2, 10, 10, 10 Pattern2 db 8 db 15, 15, 15, 0, 0, 15, 0, 0 Pattern3 db 9 db 1, 1, 1, 2, 2, 2, 4, 4, 4 Data ends Code segment para public CODE assume cs:Code, ds:Data Start proc near mov ax,Data mov ds,ax mov ax,10h int 10h ;select video mode 10h (640×350) ; ; Draw 8 radial lines in upper-left quadrant in pattern 0. ; mov bx,0 mov cx,0 mov si,offset Pattern0 call QuadrantUp ; ; Draw 8 radial lines in upper-right quadrant in pattern 1. ; mov bx,320 mov cx,0 mov si,offset Pattern1 call QuadrantUp ; ; Draw 8 radial lines in lower-left quadrant in pattern 2. ; mov bx,0 mov cx,175 mov si,offset Pattern2 call QuadrantUp ; ; Draw 8 radial lines in lower-right quadrant in pattern 3. ; mov bx,320 mov cx,175 mov si,offset Pattern3 call QuadrantUp ; ; Wait for a key before returning to text mode and ending. ; mov ah,01h int 21h mov ax,03h int 10h mov ah,4ch int 21h ; ; Draws 8 radial lines with specified pattern in specified mode 10h ; quadrant. ; ; Input: ; BX = X coordinate of upper left corner of quadrant ; CX = Y coordinate of upper left corner of quadrant ; SI = pointer to pattern, in following form: ; Byte 0: Length of pattern ; Byte 1: Start of pattern, one color per byte ; ; AX, BX, CX, DX destroyed ; QuadrantUp proc near add bx,160 add cx,87 ;point to the center of the quadrant mov ax,0 mov dx,160 call LineUp ;draw horizontal line to right edge mov ax,1 mov dx,88 call LineUp ;draw diagonal line to upper right mov ax,2 mov dx,88 call LineUp ;draw vertical line to top edge mov ax,3 mov dx,88 call LineUp ;draw diagonal line to upper left mov ax,4 mov dx,161 call LineUp ;draw horizontal line to left edge mov ax,5 mov dx,88 call LineUp ;draw diagonal line to lower left mov ax,6 mov dx,88 call LineUp ;draw vertical line to bottom edge mov ax,7 mov dx,88 call LineUp ;draw diagonal line to bottom right ret QuadrantUp endp ; ; Draws a horizontal, vertical, or diagonal line (one of the eight ; possible radial lines) of the specified length from the specified ; starting point. ; ; Input: ; AX = line direction, as follows: ; 3 2 1 ; 4 * 0 ; 5 6 7 ; BX = X coordinate of starting point ; CX = Y coordinate of starting point ; DX = length of line (number of pixels drawn) ; ; All registers preserved. ; ; Table of vectors to routines for each of the 8 possible lines. ; LineUpVectors label word dw LineUp0, LineUp1, LineUp2, LineUp3 dw LineUp4, LineUp5, LineUp6, LineUp7 ; ; Macro to draw horizontal, vertical, or diagonal line. ; ; Input: ; XParm = 1 to draw right, -1 to draw left, 0 to not move horz. ; YParm = 1 to draw up, -1 to draw down, 0 to not move vert. ; BX = X start location ; CX = Y start location ; DX = number of pixels to draw ; DS:SI = line pattern ; MLineUp macro XParm, YParm local LineUpLoop, CheckMoreLine mov di,si ;set aside start offset of pattern lodsb ;get length of pattern mov ah,al LineUpLoop: lodsb ;get color of this pixel... call DotUpInColor ;...and draw it if XParm EQ 1 inc bx endif if XParm EQ -1 dec bx endif if YParm EQ 1 inc cx endif if YParm EQ -1 dec cx endif dec ah ;at end of pattern? jnz CheckMoreLine mov si,di ;get back start of pattern lodsb mov ah,al ;reset pattern count CheckMoreLine: dec dx jnz LineUpLoop jmp LineUpEnd endm LineUp proc near push ax push bx push cx push dx push si push di push es mov di,ax mov ax,GRAPHICS_SEGMENT mov es,ax push dx ;save line length ; ; Enable writes to all planes. ; mov dx,SC_INDEX mov al,MAP_MASK out dx,al inc dx mov al,0fh out dx,al ; ; Select write mode 2. ; mov dx,GC_INDEX mov al,GRAPHICS_MODE out dx,al inc dx mov al,02h out dx,al ; ; Vector to proper routine. ; pop dx ;get back line length shl di,1 jmp cs:[LineUpVectors+di] ; ; Horizontal line to right. ; LineUp0: MLineUp 1, 0 ; ; Diagonal line to upper right. ; LineUp1: MLineUp 1, -1 ; ; Vertical line to top. ; LineUp2: MLineUp 0, -1 ; ; Diagonal line to upper left. ; LineUp3: MLineUp -1, -1 ; ; Horizontal line to left. ; LineUp4: MLineUp -1, 0 ; ; Diagonal line to bottom left. ; LineUp5: MLineUp -1, 1 ; ; Vertical line to bottom. ; LineUp6: MLineUp 0, 1 ; ; Diagonal line to bottom right. ; LineUp7: MLineUp 1, 1 LineUpEnd: pop es pop di pop si pop dx pop cx pop bx pop ax ret LineUp endp ; ; Draws a dot in the specified color at the specified location. ; Assumes that the VGA is in write mode 2 with writes to all planes ; enabled and that ES points to display memory. ; ; Input: ; AL = dot color ; BX = X coordinate of dot ; CX = Y coordinate of dot ; ES = display memory segment ; ; All registers preserved. ; DotUpInColor proc near push bx push cx push dx push di ; ; Point ES:DI to the display memory byte in which the pixel goes, with ; the bit mask set up to access that pixel within the addressed byte. ; push ax ;preserve dot color mov ax,SCREEN_WIDTH_IN_BYTES mul cx ;offset of start of top scan line mov di,ax mov cl,bl and cl,111b mov dx,GC_INDEX mov al,BIT_MASK out dx,al inc dx mov al,80h shr al,cl out dx,al ;set the bit mask for the pixel shr bx,1 shr bx,1 shr bx,1 ;X in bytes add di,bx ;offset of byte pixel is in mov al,es:[di] ;load latches pop ax ;get back dot color stosb ;write dot in desired color pop di pop dx pop cx pop bx ret DotUpInColor endp Start endp Code ends end Start
|Previous||Table of Contents||Next|