
                     GEM PROGRAMMING by Jonathan White

                                   ARTICLE 7


     Hello again. This time round we  are  going  to take out final look at
     the VDI part of the system. We are going to concentrate on BITMAPS.

     A bitmap is essentially any  arrangement  of  data  to form a picture.
     Mouse forms are bitmaps, even the characters are actually bitmaps, and
     the ST has a pixel based display.  But the VDI gives us the capability
     to create and use bitmaps ourselves,  provided  we know a little about
     how they are arranged.

     First of all, we must recognise  how  the  ST display is organised. In
     the vast majority of cases, the  displays  of  the ST are based around
     palettes. Even mono technically has a  palette, although it isn't used
     much :-). The palette is a  list  of actual colours, and any reference
     to a colour in the system apart from this does not reference an actual
     colour, but instead an entry in this table, often called a Colour Look
     Up Table (or CLUT for short).

     In the ST's screen memory, each  pixel  has a binary colour value. The
     number of colours in the 'mode' defines the number of bits used. In ST
     low, 16 colours means four bits,  and  ST medium means two. 256 colour
     modes use 8 bits, and are often referred to as '8 bit' modes.

     So if you are in ST low, all you have to do to alter the colour of the
     first pixel is to alter  the  first  four  bits  of  the first byte of
     screen memory yes? Errr, No. For some reason the bits are 'split'. The
     first 16 bits of screen  memory  are  the  first  bit  of the first 16
     pixels. The next 16 are the second  bits  of the first 16 pixels etc..
     What you get is a bit like this.

     Pretend for a moment that  the  first  pixel  is  set to colour 0, the
     second to colour 1, and so forth,  up  to the 16th which is colour 15.
     The bits work out like this..

     Pixel         0   1   2   3  4  5  6  7  8  9  10 11 12 13 14 15
     Bit 1 (1)     0   1   0   1  0  1  0  1  0  1  0  1  0  1  0  1
     Bit 2 (2)     0   0   1   1  0  0  1  1  0  0  1  1  0  0  1  1
     Bit 3 (4)     0   0   0   0  1  1  1  1  0  0  0  0  1  1  1  1
     Bit 4 (8)     0   0   0   0  0  0  0  0  1  1  1  1  1  1  1  1

     So if you look at the screen  memory,  you  would see the bits as they
     are above, starting from top left  and  reading  across the down a row
     and so on until you get to bottom right.

     Therefore, to change the colour  of  pixel  1,  you have to change the
     first bit, the 17th, the 33rd etc etc.

     Note that mono works this way too,  but  since it has only one bit per
     pixel you have no troubles.

     What relevance to the VDI has this, you are asking. Well, the VDI uses
     bitmaps in one of two formats.  The  first  is  the same as the screen
     display, i.e. as above.  The  second  is  a  'VDI Standard' bitmap, in
     which all the bit 0's are collected  together, followed by the bit 1's
     etc. This is called  a  'bitplane'  mode.  Incidentally, where all the
     pixels are together, it's called a  packbits mode.  That means ST mono
     is a packbits, bitplaned and bitmapped  mode  all at once! It's also a
     truecolour mode, according to some  definitions.  And you thought your
     ST wasn't graphically versatile.   Just  in  case  you were wondering,
     there is a function to  change  a  machine  specific bitmap into a VDI
     format one.

     It's called vr_trnfrm(). What it CAN'T  do  is transform a bitmap from
     one 'colour level' to  another.  If  you  want  to transform 16 colour
     bitmaps to mono ones, you are going  to  have  to figure out how to do
     that yourself. But it does mean that  if  you keep all your bitmaps in
     VDI form and transform them  when  you  need  them your program should
     also work on any bizarre  graphic  adapters  people might have (one of
     the functions of these cards video  drivers  is to correctly patch the
     vr_trnfrm() function). Unfortunately, it's  also  not  the quickest of
     functions.

     Anyway, on to the specifics. Any bitmap you might apply the VDI to has
     a posh name, a Memory Form Definition Block (MFDB). This is the format
     you must present the bitmap to  the  VDI  in,  and is a C structure as
     follows..

     typdef struct {
                     VOID *fd_addr;
                     WORD fd_w;
                     WORD fd_h;
                     WORD fd_wdwidth;
                     WORD fd_stand;
                     WORD fd_nplanes;
                     WORD fd_r1, fd_r2, fd_r3;
                   } MFDB;

     *fd_addr is a pointer to the  array  that holds the actual image data,
     arranged in either screen or VDI  format.  If  this is 0, the VDI uses
     the actual screen memory. This allows  you  to grab or place things on
     the screen.

     fd_w is the width of the bitmap

     fd_h is the height of the bitmap

     fd_wdwidth is used to store  the  number  of  words  of image data per
     line. One of the limitations of  VDI  usable bitmaps is that they have
     to be a multiple of 16 pixels wide, so this has to be a multiple of 16
     too.

     fs_stand is 1 if the bitmap  is  VDI  standard  format,  or 0 if it is
     machine specific.

     fd_nplanes is the number of bitplanes in the image (i.e no colours = 2
     (to the power fd_nplanes)).

     the fd_r*'s are reserved for future use..

     So, to create a bitplane, you  set  up  this structure, use malloc (or
     whatever) to grab the relevant  amount  of  memory,  then fill it with
     bitmap data. You can work out the  data  if you want longhand, but the
     easiest way to do it is to copy  it from the actual screen. You can do
     this by taking advantage of  the  fact  that  if  *fd_addr is equal to
     NULL, then the screen is used.  What  you  do  is simply copy a bitmap
     from the screen into your prepared  bitmap.  The  function to do it is
     one of two. You can do an opaque grab, or a transparent one. What does
     that mean? Well, to  explain  that  we  have  to  move  on to our next
     section..

     BITMAP OPERATIONS

     There are basically only two  bitmap  operations; copy opaque and copy
     transparent. Because both of these can  be done in both directions (to
     and from screen memory)  with  various  different  modes (we'll get to
     those later) as well as the  straight  copy between MFDBs (both opaque

     and transparent) you get quite a range of possible actions. We'll deal
     with the more simple case first..

     Opaque Copying. This copies the same  number of bitplanes (in an MFDB)
     from one place to  another.  Despite  the  name,  it  doesn't copy the
     source directly  over  the  destination.  Instead  it  can  operate in
     various modes..

     In this list,  S  is  the  source,  D  is  the  destination BEFORE the
     transfer, and R is the destination after the transfer.


             Mode            Operation               Description
             0               R = 0                   Clears destination
             1               R = S AND D
             2               R = S AND !D
             3               R = S                   Straight copy
             4               R = !S AND D
             5               R = D                   Er.. not a lot...
             6               R = S XOR D
             7               R = S OR D              Transparent Copy
             8               R = !(S OR D)
             9               R = !(S XOR D)
             10              R = !D
             11              R = S OR !D
             12              R = !S
             13              R = !S OR D
             14              R = !(S OR D)
             15              R = 1                   Fill with pen 1

             Note: ! in the above is the logical operation NOT

     Some of these are useless - anyone know  the  point of mode 5? - and 0
     and 15 are better done with other methods.

     This is  a  basic  sprite  function  -  if  for  example  your  sprite
     background is colour 0,  when  you  copy  your  sprite onto the screen
     using mode 7 the screen shows  through the sprite background. However,
     it is somewhat difficult to  predict  exactly  what the results of any
     given copy are, so I think it  is  best  if you play with these to try
     and get the hang  of  them.  Explaining  what  NOT  (A  bitmap) AND (a
     bitmap) does will take quite a long  time, whereas if you see it, it's
     much better.

     The other mode is the  copy  transparent  mode. The main difference is
     that this call allows you to  copy  a  bitmap to another bitmap if the
     source has  only  one  bitplane  into  a  destination  which  has  'n'
     bitplanes. Basically, it is what graphic people out there would call a
     masking function, as well  as  the  routine  the  AES  uses to display
     icons. The main trick to this function is that it allows you to define
     a pen colour that  will  be  used  to  draw  the  foreground (1's) and
     background ('0's). This one is a simpler function, in that it uses one
     of only four modes

             1       Replace
             2       Transparent
             3       XOR
             4       Reverse transparent

     Thus whenever there is a  1  in  the  source bitmap, the relevant mode
     operation is performed between the '1' colour and the destination, and
     between the background pen and the  destination when the source bitmap
     is '0'.

     Basically, if you want to play  with  these functions, try out a paint

     package or two. Most will have these modes available, so you can get a
     feel of their function.

     I'm sorry I can't provide  more  concrete  examples here, but the only
     way you can really understand what these  do is to see them in action.
     To be quite frank, I've used  them  before,  and  I STILL have to play
     around with the mode  parameters  occasionally  because  they don't do
     what I expect them to. I think the problem is that very few people can
     do four plane binary logic operations in their head..

     So if these things are  so  complicated,  why bother using them? Well,
     the simple answer is that they make your life easier. For example, say
     you have a graphic image  you  want  to  display. On some systems, you
     would have to know the way screen  data  is  organised. On an ST (or a
     TT, or  a  falcon,  or  a  graphics  card  adapter,  or  a  Medusa, or
     WHATEVER..) all you have to do is  sort your image into VDI format and
     let the VDI worry about the exact display ram.

     The second example is  possibly  better.  Say  you  have a text editor
     window, and your user clicks the  down  arrow,  you go down a line and
     redraw the screen, yes? No.  You  cheat.  You  take  a  bit map of all
     except the top line of your  text,  copy  it  into the right place and
     just redraw the bottom line.  The  time saving isn't really noticeable
     in standard text modes, but when  using  GDOS  fonts  it can be a real
     lifesaver..

     So that should (sort of) cover  VDI  bitmaps.  At least it should give
     you a place to start playing. I didn't really understand how they work
     until I actually programmed with  them,  and  that's the best advise I
     can give you..

     So that wraps up the VDI. Next time we'll look at the biggest function
     in the AES, the  dreaded  evnt_multi,  the  general  'wake  me up when
     something happens'  function.  After  that  we'll  start  digging into
     resource files and structures.
