home *** CD-ROM | disk | FTP | other *** search
/ Graphics Programming Black Book (Special Edition) / BlackBook.bin / disk1 / source / chapter48 / l48-2.asm < prev    next >
Assembly Source File  |  1997-06-18  |  9KB  |  177 lines

  1. ; Mode X (320x240, 256 colors) rectangle 4x4 pattern fill routine.
  2. ; Upper left corner of pattern is always aligned to a multiple-of-4
  3. ; row and column. Works on all VGAs. Uses approach of copying the
  4. ; pattern to off-screen display memory, then loading the latches with
  5. ; the pattern for each scan line and filling each scan line four
  6. ; pixels at a time. Fills up to but not including the column at EndX
  7. ; and the row at EndY. No clipping is performed. 
  8. ; Tested with TASM 4.0 by Jim Mischel 12/16/94.
  9. ; C near-callable as:
  10. ;
  11. ;    void FillPatternX(int StartX, int StartY, int EndX, int EndY,
  12. ;       unsigned int PageBase, char* Pattern);
  13.  
  14. SC_INDEX equ    03c4h   ;Sequence Controller Index register port
  15. MAP_MASK equ    02h     ;index in SC of Map Mask register
  16. GC_INDEX equ    03ceh   ;Graphics Controller Index register port
  17. BIT_MASK equ    08h     ;index in GC of Bit Mask register
  18. PATTERN_BUFFER equ 0fffch ;offset in screen memory of the buffer used
  19.                         ; to store each pattern during drawing
  20. SCREEN_SEG equ  0a000h  ;segment of display memory in Mode X
  21. SCREEN_WIDTH equ 80     ;width of screen in addresses from one scan
  22.                         ; line to the next
  23. parms   struc
  24.         dw      2 dup (?) ;pushed BP and return address
  25. StartX  dw      ?       ;X coordinate of upper left corner of rect
  26. StartY  dw      ?       ;Y coordinate of upper left corner of rect
  27. EndX    dw      ?       ;X coordinate of lower right corner of rect
  28.                         ; (the row at EndX is not filled)
  29. EndY    dw      ?       ;Y coordinate of lower right corner of rect
  30.                         ; (the column at EndY is not filled)
  31. PageBase dw     ?       ;base offset in display memory of page in
  32.                         ; which to fill rectangle
  33. Pattern dw      ?       ;4x4 pattern with which to fill rectangle
  34. parms   ends
  35.  
  36. NextScanOffset equ -2   ;local storage for distance from end of one
  37.                         ; scan line to start of next
  38. RectAddrWidth equ -4    ;local storage for address width of rectangle
  39. Height   equ     -6     ;local storage for height of rectangle
  40. STACK_FRAME_SIZE equ 6
  41.  
  42.         .model  small
  43.         .data
  44. ; Plane masks for clipping left and right edges of rectangle.
  45. LeftClipPlaneMask       db      00fh,00eh,00ch,008h
  46. RightClipPlaneMask      db      00fh,001h,003h,007h
  47.         .code
  48.         public  _FillPatternX
  49. _FillPatternX proc    near
  50.         push    bp      ;preserve caller's stack frame
  51.         mov     bp,sp   ;point to local stack frame
  52.         sub     sp,STACK_FRAME_SIZE ;allocate space for local vars
  53.         push    si      ;preserve caller's register variables
  54.         push    di
  55.  
  56.         cld
  57.         mov     ax,SCREEN_SEG   ;point ES to display memory
  58.         mov     es,ax
  59.                                 ;copy pattern to display memory buffer
  60.         mov     si,[bp+Pattern] ;point to pattern to fill with
  61.         mov     di,PATTERN_BUFFER ;point ES:DI to pattern buffer
  62.         mov     dx,SC_INDEX     ;point Sequence Controller Index to
  63.         mov     al,MAP_MASK     ; Map Mask
  64.         out     dx,al
  65.         inc     dx              ;point to SC Data register
  66.         mov     cx,4            ;4 pixel quadruplets in pattern
  67. DownloadPatternLoop:
  68.         mov     al,1            ;
  69.         out     dx,al           ;select plane 0 for writes
  70.         movsb                   ;copy over next plane 0 pattern pixel
  71.         dec     di              ;stay at same address for next plane
  72.         mov     al,2            ;
  73.         out     dx,al           ;select plane 1 for writes
  74.         movsb                   ;copy over next plane 1 pattern pixel
  75.         dec     di              ;stay at same address for next plane
  76.         mov     al,4            ;
  77.         out     dx,al           ;select plane 2 for writes
  78.         movsb                   ;copy over next plane 2 pattern pixel
  79.         dec     di              ;stay at same address for next plane
  80.         mov     al,8            ;
  81.         out     dx,al           ;select plane 3 for writes
  82.         movsb                   ;copy over next plane 3 pattern pixel
  83.                                 ; and advance address
  84.         loop    DownloadPatternLoop
  85.  
  86.         mov     dx,GC_INDEX     ;set the bit mask to select all bits
  87.         mov     ax,00000h+BIT_MASK ; from the latches and none from
  88.         out     dx,ax           ; the CPU, so that we can write the
  89.                                 ; latch contents directly to memory
  90.         mov     ax,[bp+StartY]  ;top rectangle scan line
  91.         mov     si,ax
  92.         and     si,011b         ;top rect scan line modulo 4
  93.         add     si,PATTERN_BUFFER ;point to pattern scan line that
  94.                                 ; maps to top line of rect to draw
  95.         mov     dx,SCREEN_WIDTH
  96.         mul     dx      ;offset in page of top rectangle scan line
  97.         mov     di,[bp+StartX]
  98.         mov     bx,di
  99.         shr     di,1    ;X/4 = offset of first rectangle pixel in scan
  100.         shr     di,1    ; line
  101.         add     di,ax   ;offset of first rectangle pixel in page
  102.         add     di,[bp+PageBase] ;offset of first rectangle pixel in
  103.                         ; display memory
  104.         and     bx,0003h                 ;look up left edge plane mask
  105.         mov     ah,LeftClipPlaneMask[bx] ; to clip
  106.         mov     bx,[bp+EndX]
  107.         and     bx,0003h                  ;look up right edge plane
  108.         mov     al,RightClipPlaneMask[bx] ; mask to clip
  109.         mov     bx,ax                   ;put the masks in BX
  110.         
  111.         mov     cx,[bp+EndX]    ;calculate # of addresses across rect
  112.         mov     ax,[bp+StartX]
  113.         cmp     cx,ax
  114.         jle     FillDone        ;skip if 0 or negative width
  115.         dec     cx
  116.         and     ax,not 011b
  117.         sub     cx,ax
  118.         shr     cx,1
  119.         shr     cx,1    ;# of addresses across rectangle to fill - 1
  120.         jnz     MasksSet ;there's more than one pixel to draw
  121.         and     bh,bl   ;there's only one pixel, so combine the left
  122.                         ; and right edge clip masks
  123. MasksSet:
  124.         mov     ax,[bp+EndY]
  125.         sub     ax,[bp+StartY]  ;AX = height of rectangle
  126.         jle     FillDone        ;skip if 0 or negative height
  127.         mov     [bp+Height],ax
  128.         mov     ax,SCREEN_WIDTH
  129.         sub     ax,cx   ;distance from end of one scan line to start
  130.         dec     ax      ; of next
  131.         mov     [bp+NextScanOffset],ax
  132.         mov     [bp+RectAddrWidth],cx ;remember width in addresses - 1
  133.         mov     dx,SC_INDEX+1 ;point to Sequence Controller Data reg
  134.                                 ; (SC Index still points to Map Mask)
  135. FillRowsLoop:
  136.         mov     cx,[bp+RectAddrWidth] ;width across - 1
  137.         mov     al,es:[si] ;read display memory to latch this scan
  138.                         ; line's pattern
  139.         inc     si      ;point to the next pattern scan line, wrapping
  140.         jnz     short NoWrap ; back to the start of the pattern if
  141.         sub     si,4    ; we've run off the end
  142. NoWrap:
  143.         mov     al,bh   ;put left-edge clip mask in AL
  144.         out     dx,al   ;set the left-edge plane (clip) mask
  145.         stosb           ;draw the left edge (pixels come from latches;
  146.                         ; value written by CPU doesn't matter)
  147.         dec     cx      ;count off left edge address
  148.         js      FillLoopBottom ;that's the only address
  149.         jz      DoRightEdge ;there are only two addresses
  150.         mov     al,00fh ;middle addresses are drawn 4 pixels at a pop
  151.         out     dx,al   ;set the middle pixel mask to no clip
  152.         rep     stosb   ;draw the middle addresses four pixels apiece
  153.                         ; (from latches; value written doesn't matter)
  154. DoRightEdge:
  155.         mov     al,bl   ;put right-edge clip mask in AL
  156.         out     dx,al   ;set the right-edge plane (clip) mask
  157.         stosb           ;draw the right edge (from latches; value
  158.                         ; written doesn't matter)
  159. FillLoopBottom:
  160.         add     di,[bp+NextScanOffset] ;point to the start of the next scan
  161.                                         ; line of the rectangle
  162.         dec     word ptr [bp+Height] ;count down scan lines
  163.         jnz     FillRowsLoop
  164. FillDone:
  165.         mov     dx,GC_INDEX+1 ;restore the bit mask to its default,
  166.         mov     al,0ffh       ; which selects all bits from the CPU
  167.         out     dx,al         ; and none from the latches (the GC
  168.                               ; Index still points to Bit Mask)
  169.         pop     di      ;restore caller's register variables
  170.         pop     si
  171.         mov     sp,bp   ;discard storage for local variables
  172.         pop     bp      ;restore caller's stack frame
  173.         ret
  174. _FillPatternX endp
  175.         end
  176.  
  177.