Previous | Table of Contents | Next

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.

Previous | Table of Contents | Next

Graphics Programming Black Book © 2001 Michael Abrash