; 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 (640x350) ; ; 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