home *** CD-ROM | disk | FTP | other *** search
/ Graphics Programming Black Book (Special Edition) / BlackBook.bin / disk1 / source / chapter51 / l50-1.asm < prev    next >
Assembly Source File  |  1997-06-18  |  7KB  |  158 lines

  1. ; Draws all pixels in the list of horizontal lines passed in, in
  2. ; Mode X, the VGA's undocumented 320x240 256-color mode. Clips to
  3. ; the rectangle specified by (ClipMinX,ClipMinY),(ClipMaxX,ClipMaxY).
  4. ; Draws to the page specified by CurrentPageBase.
  5. ; C near-callable as:
  6. ;
  7. ;     void DrawHorizontalLineList(struct HLineList * HLineListPtr,
  8. ;          int Color);
  9. ;
  10. ; Tested with TASM 4.0 by Jim Mischel 12/16/94.
  11.  
  12. SCREEN_WIDTH    equ     320
  13. SCREEN_SEGMENT  equ     0a000h
  14. SC_INDEX equ    03c4h   ;Sequence Controller Index
  15. MAP_MASK equ    2       ;Map Mask register index in SC
  16.  
  17. HLine   struc
  18. XStart  dw      ?       ;X coordinate of leftmost pixel in line
  19. XEnd    dw      ?       ;X coordinate of rightmost pixel in line
  20. HLine   ends
  21.  
  22. HLineList struc
  23. Lngth   dw      ?       ;# of horizontal lines
  24. YStart  dw      ?       ;Y coordinate of topmost line
  25. HLinePtr dw     ?       ;pointer to list of horz lines
  26. HLineList ends
  27.  
  28. Parms   struc
  29.                 dw      2 dup(?) ;return address & pushed BP
  30. HLineListPtr    dw      ?       ;pointer to HLineList structure
  31. Color           dw      ?       ;color with which to fill
  32. Parms   ends
  33.         .model small
  34.         .data
  35.         extrn   _CurrentPageBase:word,_ClipMinX:word
  36.         extrn   _ClipMinY:word,_ClipMaxX:word,_ClipMaxY:word
  37. ; Plane masks for clipping left and right edges of rectangle.
  38. LeftClipPlaneMask       db      00fh,00eh,00ch,008h
  39. RightClipPlaneMask      db      001h,003h,007h,00fh
  40.         .code
  41.         align   2
  42. ToFillDone:
  43.         jmp     FillDone
  44.         public _DrawHorizontalLineList
  45.         align   2
  46. _DrawHorizontalLineList proc
  47.         push    bp              ;preserve caller's stack frame
  48.         mov     bp,sp           ;point to our stack frame
  49.         push    si              ;preserve caller's register variables
  50.         push    di
  51.         cld                     ;make string instructions inc pointers
  52.         mov     dx,SC_INDEX
  53.         mov     al,MAP_MASK
  54.         out     dx,al           ;point SC Index to the Map Mask
  55.         mov     ax,SCREEN_SEGMENT
  56.         mov     es,ax   ;point ES to display memory for REP STOS
  57.         mov     si,[bp+HLineListPtr] ;point to the line list
  58.         mov     bx,[si+HLinePtr] ;point to the XStart/XEnd descriptor
  59.                                 ; for the first (top) horizontal line
  60.         mov     cx,[si+YStart]  ;first scan line to draw
  61.         mov     si,[si+Lngth]   ;# of scan lines to draw
  62.         cmp     si,0            ;are there any lines to draw?
  63.         jle     ToFillDone      ;no, so we're done
  64.         cmp     cx,[_ClipMinY]  ;clipped at top?
  65.         jge     MinYNotClipped  ;no
  66.         neg     cx              ;yes, discard however many lines are
  67.         add     cx,[_ClipMinY]  ; clipped
  68.         sub     si,cx           ;that many fewer lines to draw
  69.         jle     ToFillDone      ;no lines left to draw
  70.         shl     cx,1            ;lines to skip*2
  71.         shl     cx,1            ;lines to skip*4
  72.         add     bx,cx           ;advance through the line list
  73.         mov     cx,[_ClipMinY]  ;start at the top clip line
  74. MinYNotClipped:
  75.         mov     dx,si
  76.         add     dx,cx           ;bottom row to draw + 1
  77.         cmp     dx,[_ClipMaxY]  ;clipped at bottom?
  78.         jle     MaxYNotClipped  ;no
  79.         sub     dx,[_ClipMaxY]  ;# of lines to clip off the bottom
  80.         sub     si,dx           ;# of lines left to draw
  81.         jle     ToFillDone      ;all lines are clipped
  82. MaxYNotClipped:
  83.         mov     ax,SCREEN_WIDTH/4 ;point to the start of the first
  84.         mul     cx              ; scan line on which to draw
  85.         add     ax,[_CurrentPageBase] ;offset of first line
  86.         mov     dx,ax           ;ES:DX points to first scan line to
  87.                                 ; draw
  88.         mov     ah,byte ptr [bp+Color] ;color with which to fill
  89. FillLoop:
  90.         push    bx              ;remember line list location
  91.         push    dx              ;remember offset of start of line
  92.         push    si              ;remember # of lines to draw
  93.         mov     di,[bx+XStart]  ;left edge of fill on this line
  94.         cmp     di,[_ClipMinX]  ;clipped to left edge?
  95.         jge     MinXNotClipped  ;no
  96.         mov     di,[_ClipMinX]  ;yes, clip to the left edge
  97. MinXNotClipped:
  98.         mov     si,di
  99.         mov     cx,[bx+XEnd]    ;right edge of fill
  100.         cmp     cx,[_ClipMaxX]  ;clipped to right edge?
  101.         jl      MaxXNotClipped  ;no
  102.         mov     cx,[_ClipMaxX]  ;yes, clip to the right edge
  103.         dec     cx
  104. MaxXNotClipped:
  105.         cmp     cx,di
  106.         jl      LineFillDone        ;skip if negative width
  107.         shr     di,1            ;X/4 = offset of first rect pixel in scan
  108.         shr     di,1            ; line
  109.         add     di,dx           ;offset of first rect pixel in display mem
  110.         mov     dx,si           ;XStart
  111.         and     si,0003h        ;look up left edge plane mask
  112.         mov     bh,LeftClipPlaneMask[si] ; to clip & put in BH
  113.         mov     si,cx
  114.         and     si,0003h           ;look up right edge plane
  115.         mov     bl,RightClipPlaneMask[si] ; mask to clip & put in BL
  116.         and     dx,not 011b         ;calculate # of addresses across rect
  117.         sub     cx,dx
  118.         shr     cx,1
  119.         shr     cx,1            ;# of addresses across rectangle to fill - 1
  120.         jnz     MasksSet     ;there's more than one byte to draw
  121.         and     bh,bl           ;there's only one byte, so combine the left
  122.                                 ; and right edge clip masks
  123. MasksSet:
  124.         mov     dx,SC_INDEX+1     ;already points to the Map Mask reg
  125. FillRowsLoop:
  126.         mov     al,bh           ;put left-edge clip mask in AL
  127.         out     dx,al           ;set the left-edge plane (clip) mask
  128.         mov     al,ah           ;put color in AL
  129.         stosb                   ;draw the left edge
  130.         dec     cx              ;count off left edge byte
  131.         js      FillLoopBottom     ;that's the only byte
  132.         jz      DoRightEdge     ;there are only two bytes
  133.         mov     al,00fh         ;middle addresses are drawn 4 pixels at a pop
  134.         out     dx,al           ;set the middle pixel mask to no clip
  135.         mov     al,ah           ;put color in AL
  136.         rep     stosb           ;draw the middle addresses four pixels apiece
  137. DoRightEdge:
  138.         mov     al,bl           ;put right-edge clip mask in AL
  139.         out     dx,al           ;set the right-edge plane (clip) mask
  140.         mov     al,ah           ;put color in AL
  141.         stosb                   ;draw the right edge
  142. FillLoopBottom:
  143. LineFillDone:
  144.         pop     si                  ;retrieve # of lines to draw
  145.         pop     dx                  ;retrieve offset of start of line
  146.         pop     bx                  ;retrieve line list location
  147.         add     dx,SCREEN_WIDTH/4 ;point to start of next line
  148.         add     bx,size HLine       ;point to the next line descriptor
  149.         dec     si                  ;count down lines
  150.         jnz     FillLoop
  151. FillDone:
  152.         pop     di                  ;restore caller's register variables
  153.         pop     si
  154.         pop     bp                  ;restore caller's stack frame
  155.         ret
  156. _DrawHorizontalLineList endp
  157.         end
  158.