**LISTING 41.3 L41-3.ASM** ; Draws all pixels in list of horizontal lines passed in, in mode 13h, VGA's ; 320x200 256-color mode. Uses REP STOS to fill each line. ; ****************************************************************** ; NOTE: is able to reverse the X coords for a scan line, if necessary, to make ; XStart < XEnd. Expects whichever edge is rightmost on any scan line to be in ; +1 format; that is, XEnd is 1 greater than rightmost pixel to draw. If ; XStart == XEnd, nothing is drawn on that scan line. ; ****************************************************************** ; C near-callable as: ; void DrawHorizontalLineList(struct HLineList * HLineListPtr, int Color); ; All assembly code tested with TASM and MASM SCREEN_WIDTH equ 320 SCREEN_SEGMENT equ 0a000h HLine struc XStart dw ? ;X coordinate of leftmost pixel in line XEnd dw ? ;X coordinate of rightmost pixel in line HLine ends HLineList struc Lngth dw ? ;# of horizontal lines YStart dw ? ;Y coordinate of topmost line HLinePtr dw ? ;pointer to list of horz lines HLineList ends Parms struc dw 2 dup(?) ;return address & pushed BP HLineListPtr dw ? ;pointer to HLineList structure Color dw ? ;color with which to fill Parms ends .model small .code public _DrawHorizontalLineList align 2 _DrawHorizontalLineList proc push bp ;preserve caller's stack frame mov bp,sp ;point to our stack frame push si ;preserve caller's register variables push di cld ;make string instructions inc pointers mov ax,SCREEN_SEGMENT mov es,ax ;point ES to display memory for REP STOS mov si,[bp+HLineListPtr] ;point to the line list mov ax,SCREEN_WIDTH ;point to the start of the first scan mul [si+YStart] ; line in which to draw mov dx,ax ;ES:DX points to first scan line to draw mov bx,[si+HLinePtr] ;point to the XStart/XEnd descriptor ; for the first (top) horizontal line mov si,[si+Lngth] ;# of scan lines to draw and si,si ;are there any lines to draw? jz FillDone ;no, so we're done mov al,byte ptr [bp+Color] ;color with which to fill mov ah,al ;duplicate color for STOSW FillLoop: mov di,[bx+XStart] ;left edge of fill on this line mov cx,[bx+XEnd] ;right edge of fill cmp di,cx ;is XStart > XEnd? jle NoSwap ;no, we're all set xchg di,cx ;yes, so swap edges NoSwap: sub cx,di ;width of fill on this line jz LineFillDone ;skip if zero width add di,dx ;offset of left edge of fill test di,1 ;does fill start at an odd address? jz MainFill ;no stosb ;yes, draw the odd leading byte to ; word-align the rest of the fill dec cx ;count off the odd leading byte jz LineFillDone ;done if that was the only byte MainFill: shr cx,1 ;# of words in fill rep stosw ;fill as many words as possible adc cx,cx ;1 if there's an odd trailing byte to ; do, 0 otherwise rep stosb ;fill any odd trailing byte LineFillDone: add bx,size HLine ;point to the next line descriptor add dx,SCREEN_WIDTH ;point to the next scan line dec si ;count off lines to fill jnz FillLoop FillDone: pop di ;restore caller's register variables pop si pop bp ;restore caller's stack frame ret _DrawHorizontalLineList endp end Listing 41.4 is almost identical to Listing 40.1 from Chapter 40. I've modified Listing 40.1 to employ the vertical-monotone detection test we've been talking about and use the fast vertical-monotone drawing code whenever possible; that's what Listing 41.4 is. Note well that Listing 40.5 from Chapter 40 is also required in order for this code to link. Listing 41.5 is an appropriately updated version of the POLYGON.H header file.