[Contents] [Index] [Help] [Retrace] [Browse <] [Browse >]

Up to now we have dealt with the blitter only in moving words of memory
around and combining them with logic operations.  This is sufficient for
 moving graphic images  around, so long as the images stay in the same
position relative to the beginning of a word.  If our car image has its
leftmost pixel on the second pixel from the left, we can easily draw it on
the screen in any position where the leftmost pixel also starts two pixels
from the beginning of some word.  But often we want to draw that car
shifted left or right by a few pixels. To this end, both the A and B
 DMA channels  have a barrel shifter that can shift an image between 0 and
15 bits.

This shifting operation is completely free; it requires no more time to
execute a blit with shifts than a blit without shifts, as opposed to
shifting with the 680x0.  The shift is normally towards the right. This
shifter allows movement of images on pixel boundaries, even though the
pixels are addressed 16 at a time by each word address of the bitplane

So if the incoming data is shifted to the right, what is shifted in
from the left?  For the first word of the blit, zeros are shifted in; for
each subsequent word of the same blit, the data shifted out from the
previous word is shifted in.

The shift value for the A channel is set with bits 15 through 12 of
 BLTCON0 ; the B shift value is set with bits 15 through 12 of  BLTCON1 .
For most operations, the same value will be used for both shifts.  For
shifts of greater than fifteen bits, load the  address register pointer 
of the destination with a higher address; a shift of 100 bits would
require the  destination pointer  to be advanced 100/16 or 6 words (12
bytes), and a right shift of the remaining 4 bits to be used.

As an example, let us say we are doing a blit that is three words wide,
two words high, and we are using a shift of 4 bits.  For simplicity, let
us assume we are doing a straight copy from A to D.  The first word that
will be written to D is the first word fetched from A, shifted right four
bits with zeros shifted in from the left.  The second word will be the
second word fetched from the A, shifted right, with the least significant
(rightmost) four bits of the first word shifted in. Next, we will write
the first word of the second row fetched from A, shifted four bits, with
the least significant four bits of the last word from the first row
shifted in. This would continue until the blit is finished.

On shifted blits, therefore, we only get zeros shifted in for the first
word of the first row. On all other rows the blitter will shift in the
bits that it shifted out of the previous row. For most graphics
applications, this is undesirable.  For this reason, the blitter has the
ability to mask the first and last word of each row coming through the A
 DMA channel .

Thus, it is possible to extract rectangular data from a source whose right
and left edges are between word boundaries. These two registers are called
BLTAFWM and BLTALWM, for blitter A channel first and last word masks.
When not in use, both should be initialized to all ones ($FFFF).

   A note about fonts.
   Text fonts on the Amiga are stored in a packed bitmap.  Individual
   characters from the font are extracted using the blitter, masking out
   unwanted bits.  The character may then be positioned to any pixel
   alignment by shifting it the appropriate amount.

These masks are "anded" with the source data, before any shifts are
applied. Only when there is a 1 bit in the first-word mask will that bit
of source A actually appear in the logic operation. The first word of each
row is anded with BLTAFWM, and the last word is "anded" with BLTALWM.  If
the width of the row is a single word, both masks are applied

The masks are also useful for extracting a certain range of "columns" from
some bitplane.  Let us say we have, for example, a predrawn rectangle
containing text and graphics that is 23 pixels wide.  The leftmost edge is
the leftmost bit in its bitmap, and the bitmap is two words wide.  We wish
to render this rectangle starting at pixel position 5 into our 320 by 200
screen bitmap, without disturbing anything that lies outside of the

                 |<--------- two word source bitmap -------->|
                 |                                           |
                 |<--- extract a 32-bit image --->|          |
                 |                                |          |
                 |<--- 16-bit word -->|           |          |
                 |                                           |
    source       | 00000000  00000000     00000000  00000000 |
    DMA B        | 11111111  11111111     11111111  11111111 |
                 | 10101010  01010101     10101010  01010101 |
                       |         |          |         |
                 Source is passed through mask when it is one,
                     outherwise the destination is copied.
                       |         |          |         |
                  _____v_________v____   ___v_________v______
                 |                    | |                    |
    mask on      | 11111111  11111111 | | 11111110  00000000 |
    DMA A        |  first word mask   | |  second word mask  |
                 |____________________| |____________________|
                       |         |          |  ||     |
                       |         |          |  |-     -
    final        |                                           |
    destination  | 00000000  00000000     00000000  11111111 |
    DMA D        | 11111111  11111111     11111111  11111111 |
    (points to   | 10101010  01010101     10101010  11111111 |
    same address |___________________________________________|
    as DMA C)                                   ^   ^  ^   ^
                       -         -         -    |   |  |   | <-+
                  _____|_________|_________|____|___|__|___|_  |
    destination  |                                           | |
    before blit  | 00000000  00000000     00000000  00000000 | |
    DMA C        | 11111111  11111111     11111111  11111111 | |
    (to be       | 10101010  01010101     10101010  01010101 | |
    overwritten) |___________________________________________| |
                 Destination does not change where mask is 0 --+

                   Figure 6-4: Extracting a Range of Columns

To do this, we point the B  DMA channel  at the bitmap containing the
source image, and the D  DMA channel  at the screen bitmap. We use a shift
value of 5.  We also point the C  DMA channel  at the screen bitmap. We
use a blit width of 2 words. What we need is a simple copy operation,
except we wish to leave the first five bits of the first word, and the
last four bits (2 times 16, less 23, less 5) of the last word alone. The A
 DMA channel  comes to the rescue.  We preload the A  data register  with
$FFFF (all ones), and use a first word mask with the most significant five
bits set to zero ($07FF) and a last word mask with the least significant
four bits set to zero ($FFF0).  We do not enable the A  DMA channel , but
only the B, C, and D channels, since we want to use the A channel as a
simple row mask. We then wish to pass the B (source) data along wherever
the A channel is 1 (for a  minterm  of AB) and pass along the original
destination data (from the C channel) wherever A is 0
(for a  minterm  of AC),
yielding our classic cookie-cut function of AB+AC, or $CA.

   About disabling.
   Even though the A channel is disabled, we use it in our logic
   function and preload the  data register .  Disabling a channel simply
   turns off the memory fetches for that channel; all other operations
   are still performed, only from a constant value stored in the
   channel's  data register .

An alternative but more subtle way of accomplishing the same thing is to
use an A shift of five, a first word mask of all ones, and a last word
mask with the rightmost nine bits set to zero.  All other registers remain
the same.

   Be sure to load the blitter immediate  data registers  only after
   setting the shift count in  BLTCON0/BLTCON1 , as loading the
    data registers  first will lead to unpredictable results. For instance,
   if the last person left BSHIFT to be "4", and I load BDATA with "1" and
   then change BSHIFT to "2", the resulting BDATA that is used is
   "1<<4", not "1<<2". The act of loading one of the  data registers 
   "draws" the data through the machine and shifts it.

[Back to Amiga Developer Docs]