home *** CD-ROM | disk | FTP | other *** search
/ Graphics Programming Black Book (Special Edition) / BlackBook.bin / disk1 / source / chapterg / lg-4.asm < prev    next >
Encoding:
Assembly Source File  |  1997-06-18  |  7.9 KB  |  156 lines

  1. ; Draws all pixels in the list of horizontal lines passed in, in
  2. ; Hicolor (32K color) mode on an ET4000-based SuperVGA. Uses REP STOSW
  3. ; to fill each line. C near-callable as: 
  4. ;      void DrawHCLineList(struct HLineList * HLineListPtr, int Color);
  5. ; Tested with TASM 4.0 by Jim Mischel 12/16/94.
  6.  
  7. SCREEN_SEGMENT  equ     0a000h
  8. GC_SEGMENT_SELECT equ   03cdh
  9.  
  10. HLine   struc
  11. XStart  dw      ?       ;X coordinate of leftmost pixel in line
  12. XEnd    dw      ?       ;X coordinate of rightmost pixel in line
  13. HLine   ends
  14.  
  15. HLineList struc
  16. Lngth   dw      ?       ;# of horizontal lines
  17. YStart  dw      ?       ;Y coordinate of topmost line
  18. HLinePtr dw     ?       ;pointer to list of horz lines
  19. HLineList ends
  20.  
  21. Parms   struc
  22.                 dw      2 dup(?) ;return address & pushed BP
  23. HLineListPtr    dw      ?       ;pointer to HLineList structure
  24. Color           dw      ?       ;color with which to fill
  25. Parms   ends
  26.  
  27. ; Advances both the read and write windows to the next 64K bank.
  28. ; Note: Theoretically, a delay between IN and OUT may be needed under
  29. ; some circumstances to avoid accessing the VGA chip too quickly, but
  30. ; in actual practice, I haven't found any delay to be required.
  31. INCREMENT_BANK  macro
  32.         push    ax              ;preserve fill color
  33.         push    dx              ;preserve scan line start pointer
  34.         mov     dx,GC_SEGMENT_SELECT
  35.         in      al,dx           ;get the current segment select
  36.         add     al,11h          ;increment both the read & write banks
  37.         out     dx,al           ;set the new bank #
  38.         pop     dx              ;restore scan line start pointer
  39.         pop     ax              ;restore fill color
  40.         endm
  41.  
  42.         .model small
  43.         .data
  44.         extrn   _BitmapWidthInBytes:word
  45.         .code
  46.         public _DrawHCLineList
  47.         align   2
  48. _DrawHCLineList proc    near
  49.         push    bp              ;preserve caller's stack frame
  50.         mov     bp,sp           ;point to our stack frame
  51.         push    si              ;preserve caller's register variables
  52.         push    di
  53.         cld                     ;make string instructions inc pointers
  54.         mov     ax,SCREEN_SEGMENT
  55.         mov     es,ax   ;point ES to display memory for REP STOS
  56.         mov     si,[bp+HLineListPtr] ;point to the line list
  57.         mov     ax,[_BitmapWidthInBytes] ;point to the start of the
  58.         mul     [si+YStart]     ; first scan line on which to draw
  59.         mov     di,ax           ;ES:DI points to first scan line to
  60.         mov     al,dl           ; draw; AL is the initial bank #
  61.                                 ;upper nibble of AL is read bank #,
  62.         mov     cl,4            ; lower nibble is write bank # (only
  63.         shl     dl,cl           ; the write bank is really needed for
  64.         or      al,dl           ; this module, but it's less confusing
  65.                                 ; to point both to the same place)
  66.         mov     dx,GC_SEGMENT_SELECT
  67.         out     dx,al           ;set the initial bank
  68.         mov     dx,di           ;ES:DX points to first scan line
  69.         mov     bx,[si+HLinePtr] ;point to the XStart/XEnd descriptor
  70.                                 ; for the first (top) horizontal line
  71.         mov     si,[si+Lngth]   ;# of scan lines to draw
  72.         and     si,si           ;are there any lines to draw?
  73.         jz      FillDone        ;no, so we're done
  74.         mov     ax,[bp+Color]   ;color with which to fill
  75.         mov     bp,[_BitmapWidthInBytes] ;so we can keep everything
  76.                                 ; in registers inside the loop
  77.                                 ;***stack frame pointer destroyed!***
  78. FillLoop:
  79.         mov     di,[bx+XStart]  ;left edge of fill on this line
  80.         mov     cx,[bx+XEnd]    ;right edge of fill
  81.         sub     cx,di
  82.         jl      LineFillDone    ;skip if negative width
  83.         inc     cx              ;# of pixels to fill on this line
  84.         add     di,di           ;*2 because pixels are 2 bytes in size
  85.         add     dx,bp           ;do we cross a bank during this line?
  86.         jnc     NormalFill      ;no
  87.         jz      NormalFill      ;no
  88.                                 ;yes, there is a bank crossing on this
  89.                                 ; line; figure out where
  90.         sub     dx,bp           ;point back to start of line
  91.         add     di,dx           ;offset of left edge of fill
  92.         jc      CrossBankBeforeFilling ;raster splits before the left
  93.                                 ; edge of fill
  94.         add     cx,cx           ;fill width in bytes (pixels * 2)
  95.         add     di,cx           ;do we split during the fill area?
  96.         jnc     CrossBankAfterFilling ;raster splits after the right
  97.         jz      CrossBankAfterFilling ; edge of fill
  98.                                 ;bank boundary falls within fill area;
  99.                                 ; draw in two parts, one in each bank
  100.         sub     di,cx           ;point back to start of fill area
  101.         neg     di              ;# of bytes left before split
  102.         sub     cx,di           ;# of bytes to fill to the right of
  103.                                 ; the bank split
  104.         push    cx              ;remember right-of-split fill width
  105.         mov     cx,di           ;# of left-of-split bytes to fill
  106.         shr     cx,1            ;# of left-of-split words to fill
  107.         neg     di              ;offset at which to start filling
  108.         rep     stosw           ;fill left-of-split portion of line
  109.         pop     cx              ;get back right-of-split fill width
  110.         shr     cx,1            ;# of right-of-split words to fill
  111.                                 ;advance to the next bank       
  112.         INCREMENT_BANK          ;point to the next bank (DI already
  113.                                 ; points to offset 0, as desired)
  114.         rep     stosw           ;fill right-of-split portion of line
  115.         add     dx,bp           ;point to the next scan line
  116.         jmp     short CountDownLine ; (already advanced the bank)
  117. ;======================================================================
  118.         align   2               ;dfill area is entirely to the left of
  119. CrossBankAfterFilling:          ; the bank boundary
  120.         sub     di,cx           ;point back to start of fill area
  121.         shr     cx,1            ;CX = fill width in pixels
  122.         jmp     short FillAndAdvance ;doesn't split until after the
  123.                                 ; fill area, so handle normally
  124. ;======================================================================
  125.         align   2               ;fill area is entirely to the right of
  126. CrossBankBeforeFilling:         ; the bank boundary
  127.         INCREMENT_BANK          ;first, point to the next bank, where
  128.                                 ; the fill area resides
  129.         rep     stosw           ;fill this scan line
  130.         add     dx,bp           ;point to the next scan line
  131.         jmp     short CountDownLine ; (already advanced the bank)
  132. ;======================================================================
  133.         align   2               ;no bank boundary problems; just fill
  134. NormalFill:                     ; normally
  135.         sub     dx,bp           ;point back to start of line
  136.         add     di,dx           ;offset of left edge of fill
  137. FillAndAdvance:
  138.         rep     stosw           ;fill this scan line
  139. LineFillDone:
  140.         add     dx,bp           ;point to the next scan line
  141.         jnc     CountDownLine   ;didn't cross a bank boundary
  142.         INCREMENT_BANK          ;did cross, so point to the next bank 
  143. CountDownLine:
  144.         add     bx,size HLine   ;point to the next line descriptor
  145.         dec     si              ;count off lines to fill
  146.         jnz     FillLoop
  147. FillDone:
  148.         pop     di              ;restore caller's register variables
  149.         pop     si
  150.         pop     bp              ;restore caller's stack frame
  151.         ret
  152. ;======================================================================
  153. _DrawHCLineList endp
  154.         end
  155.  
  156.