/* dbuff.gels.c */


/* SAMPLE PROGRAM THAT USES GELTOOLS TO PRODUCE A DOUBLE BUFFERED DISPLAY
 * SCREEN CONTAINING TWO BOBS AND TWO VSPRITES
 *
 * Author:  David Lucas
 */


/* Leave this structure definition at the top. Look at gels.h. */
struct vInfo {
	short vx,vy;		/* This VSprites velocity. */
	short id;
};
#define VUserStuff struct vInfo


/* Things to notice:

        Default value in sprite/playfield priority register has all
        hardware sprites having a higher priority than either of the
        two playfields.   Areas containing color 0 of both the bob and
        vsprite are shown as transparent (see hole in center of each).

        You can specify bob drawing order by using the before and after
        pointers, thereby always maintaining an apparent precedence of
        one bob over another.  Re Vsprites.... because they are assigned
        sequentially from top of screen to bottom, in sprite numerical
        order (0, 1, 2, 3 etc), and because the lowest numbered hardware
        sprite has the highest video precedence, the sprite that is
        closest to the top of the screen always appears in front of the
        sprite beneath it.

        Without double-buffering, there would be flicker on the part
	of the bobs.  Double buffering consists of writing into an area
	that is not being displayed.  Some of the flicker could have been
	alleviated by waiting for the video beam to reach top-of-frame
	before doing the drawing, but when the bobs are near the top,
	it makes it all the more difficult to draw without apparent
	flicker in that case.  Also note that multitasking will
	occasionally upset even this plan in that it can delay the
	drawing operation until the beam is in the area that is being drawn.

*/

/*******************************************************************************
 * A sprite and a bob on a screen.
 */

#include "intuall.h"

#define SBMWIDTH 320	/* My screen size constants. */
#define SBMHEIGHT 200
#define SBMDEPTH 4

#define RBMWIDTH 330	/* My rastport size constants. */
#define RBMHEIGHT 210
#define RBMDEPTH SBMDEPTH

#define VSPRITEWIDTH 1	/* My VSprite constants. */
#define VSPRITEHEIGHT 12
#define VSPRITEDEPTH 2
#define NSPRITES 2

#define BOBWIDTH 62	/* My Bob constants. */
#define BOBHEIGHT 31
#define BOBDEPTH 4
#define NBOBS 2

struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;

struct IntuiMessage *MyIntuiMessage = NULL;

struct TextAttr TestFont = {	/* Needed for opening screen. */
	(STRPTR)"topaz.font", TOPAZ_EIGHTY, 0, 0
};

/* DBL BUF */
struct BitMap *MyBitMapPtrs[2] = {NULL, NULL};
WORD ToggleFrame = 0;

struct GelsInfo GInfo;		/* For all Gels. */

struct VSprite *VSprites[NSPRITES];
WORDBITS VSpriteImage[] = {
/* Plane 0, Plane 1 */
	0xFFFF, 0xFFFF,	/* Line 1, first. */
	0xFFFF, 0xC003,
	0xFFFF, 0xC003,
	0xF00F, 0xCFF3,
	0xF00F, 0xCFF3,
	0xF00F, 0xCC33,
	0xF00F, 0xCC33,
	0xF00F, 0xCFF3,
	0xF00F, 0xCFF3,
	0xFFFF, 0xC003,
	0xFFFF, 0xC003,
	0xFFFF, 0xFFFF,	/* Line 12, last. */
};
USHORT *VSpriteImage_chip = 0;

/* These are the colors that will be used for my VSprites. Note I really do mean
 * colors, not color register numbers. High to low, starting at bit 12 and going
 * down to LSB, there are four bits each of red, green and blue. Please read the
 * sprite section of the hardware manual. The gels system will put them into the
 * proper color registers when they are displayed. Reminder: Sprites can only
 * use color registers in sets of 3...
 *   17,18,19 = sprite 0 and 1,
 *   21,22,23 = sprite 2 and 3,
 *   25,26,27 = sprite 4 and 5,
 *   29,30,31 = sprite 6 and 7.
 * Please read the section on how VSprites are assigned in the RKM.
 */
WORD MyVSpriteColors[] = {
	0x0f00,	/* Full red. */
	0x00f0,	/* Full green. */
	0x000f	/* Full blue. */
};

struct Bob *Bobs[NBOBS];
short BobImage[] = {
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,	/* Plane 0, line 1. */
	0xC000, 0x0000,	0x0000, 0x000C,
	0xCFFF, 0xFFFF,	0xFFFF, 0xFFCC,
	0xCC00, 0x0000,	0x0000, 0x00CC,
	0xCCFF, 0xFFFF,	0xFFFF, 0xFCCC,
	0xCCC0, 0x0000,	0x0000, 0x0CCC,
	0xCCCF, 0xFFFF,	0xFFFF, 0xCCCC,
	0xCCCC, 0x0000,	0x0000, 0xCCCC,
	0xCCCC, 0xFFFF, 0xFFFC, 0xCCCC,
	0xCCCC, 0xC000,	0x000C, 0xCCCC,
	0xCCCC, 0xCFFF,	0xFFCC, 0xCCCC,
	0xCCCC, 0xCC00,	0x00CC, 0xCCCC,
	0xCCCC, 0xCCFF,	0xFCCC, 0xCCCC,
	0xCCCC, 0xCCC0,	0x0CCC, 0xCCCC,
	0xCCCC, 0xCCCF,	0xCCCC, 0xCCCC,
	0xCCCC, 0xCCCC,	0xCCCC, 0xCCCC,
	0xCCCC, 0xCCCF,	0xCCCC, 0xCCCC,
	0xCCCC, 0xCCC0,	0x0CCC, 0xCCCC,
	0xCCCC, 0xCCFF,	0xFCCC, 0xCCCC,
	0xCCCC, 0xCC00,	0x00CC, 0xCCCC,
	0xCCCC, 0xCFFF,	0xFFCC, 0xCCCC,
	0xCCCC, 0xC000,	0x000C, 0xCCCC,
	0xCCCC, 0xFFFF, 0xFFFC, 0xCCCC,
	0xCCCC, 0x0000,	0x0000, 0xCCCC,
	0xCCCF, 0xFFFF,	0xFFFF, 0xCCCC,
	0xCCC0, 0x0000,	0x0000, 0x0CCC,
	0xCCFF, 0xFFFF,	0xFFFF, 0xFCCC,
	0xCC00, 0x0000,	0x0000, 0x00CC,
	0xCFFF, 0xFFFF,	0xFFFF, 0xFFCC,
	0xC000, 0x0000,	0x0000, 0x000C,
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,	/* Plane 0, line 31. */

        0xFFFF, 0xFFFF, 0xFFFF, 0xFFFC,	/* Plane 1, line 1. */
        0xFFFF, 0xFFFF, 0xFFFF, 0xFFFC,
        0xF000, 0x0000, 0x0000, 0x003C,
        0xF000, 0x0000, 0x0000, 0x003C,
        0xF0FF, 0xFFFF, 0xFFFF, 0xFC3C,
        0xF0FF, 0xFFFF, 0xFFFF, 0xFC3C,
        0xF0F0, 0x0000, 0x0000, 0x3C3C,
        0xF0F0, 0x0000, 0x0000, 0x3C3C,
        0xF0F0, 0xFFFF, 0xFFFC, 0x3C3C,
        0xF0F0, 0xFFFF, 0xFFFC, 0x3C3C,
        0xF0F0, 0xF000, 0x003C, 0x3C3C,
        0xF0F0, 0xF000, 0x003C, 0x3C3C,
        0xF0F0, 0xF0FF, 0xFC3C, 0x3C3C,
        0xF0F0, 0xF0FF, 0xFC3C, 0x3C3C,
        0xF0F0, 0xF0F0, 0x3C3C, 0x3C3C,
        0xF0F0, 0xF0F0, 0x3C3C, 0x3C3C,
        0xF0F0, 0xF0F0, 0x3C3C, 0x3C3C,
        0xF0F0, 0xF0FF, 0xFC3C, 0x3C3C,
        0xF0F0, 0xF0FF, 0xFC3C, 0x3C3C,
        0xF0F0, 0xF000, 0x003C, 0x3C3C,
        0xF0F0, 0xF000, 0x003C, 0x3C3C,
        0xF0F0, 0xFFFF, 0xFFFC, 0x3C3C,
        0xF0F0, 0xFFFF, 0xFFFC, 0x3C3C,
        0xF0F0, 0x0000, 0x0000, 0x3C3C,
        0xF0F0, 0x0000, 0x0000, 0x3C3C,
        0xF0FF, 0xFFFF, 0xFFFF, 0xFC3C,
        0xF0FF, 0xFFFF, 0xFFFF, 0xFC3C,
        0xF000, 0x0000, 0x0000, 0x003C,
        0xF000, 0x0000, 0x0000, 0x003C,
        0xFFFF, 0xFFFF, 0xFFFF, 0xFFFC,
        0xFFFF, 0xFFFF, 0xFFFF, 0xFFFC,	/* Plane 1, line 31. */

	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFC, /* Plane 2, line 1. */
	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFC,
	0xFF00, 0x0000, 0x0000, 0x03FC,
	0xFF00, 0x0000, 0x0000, 0x03FC,
	0xFF00, 0x0000, 0x0000, 0x03FC,
	0xFF00, 0x0000, 0x0000, 0x03FC,
	0xFF00, 0xFFFF, 0xFFFC, 0x03FC,
	0xFF00, 0xFFFF, 0xFFFC, 0x03FC,
	0xFF00, 0xFFFF, 0xFFFC, 0x03FC,
	0xFF00, 0xFFFF, 0xFFFC, 0x03FC,
	0xFF00, 0xFF00, 0x03FC, 0x03FC,
	0xFF00, 0xFF00, 0x03FC, 0x03FC,
	0xFF00, 0xFF00, 0x03FC, 0x03FC,
	0xFF00, 0xFF00, 0x03FC, 0x03FC,
	0xFF00, 0xFF00, 0x03FC, 0x03FC,
	0xFF00, 0xFF00, 0x03FC, 0x03FC,
	0xFF00, 0xFF00, 0x03FC, 0x03FC,
	0xFF00, 0xFFFF, 0xFFFC, 0x03FC,
	0xFF00, 0xFFFF, 0xFFFC, 0x03FC,
	0xFF00, 0xFFFF, 0xFFFC, 0x03FC,
	0xFF00, 0xFFFF, 0xFFFC, 0x03FC,
	0xFF00, 0x0000, 0x0000, 0x03FC,
	0xFF00, 0x0000, 0x0000, 0x03FC,
	0xFF00, 0x0000, 0x0000, 0x03FC,
	0xFF00, 0x0000, 0x0000, 0x03FC,
	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFC,	/* Plane 2, line 31. */

	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC, /* Plane 3, line 1. */
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,
	0xFFFF, 0x0000,	0x0003, 0xFFFC,
	0xFFFF, 0x0000,	0x0003, 0xFFFC,
	0xFFFF, 0x0000,	0x0003, 0xFFFC,
	0xFFFF, 0x0000,	0x0003, 0xFFFC,
	0xFFFF, 0x0000,	0x0003, 0xFFFC,
	0xFFFF, 0x0000,	0x0003, 0xFFFC,
	0xFFFF, 0x0000,	0x0003, 0xFFFC,
	0xFFFF, 0x0000,	0x0003, 0xFFFC,
	0xFFFF, 0x0000,	0x0003, 0xFFFC,
	0xFFFF, 0x0000,	0x0003, 0xFFFC,
	0xFFFF, 0x0000,	0x0003, 0xFFFC,
	0xFFFF, 0x0000,	0x0003, 0xFFFC,
	0xFFFF, 0x0000,	0x0003, 0xFFFC,
	0xFFFF, 0x0000,	0x0003, 0xFFFC,
	0xFFFF, 0x0000,	0x0003, 0xFFFC,
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC,
	0xFFFF, 0xFFFF,	0xFFFF, 0xFFFC	/* Plane 3, line 31. */
};
USHORT *BobImage_chip = 0;

/* These are for my custom screen. */
struct Screen *screen = NULL;
struct NewScreen ns = {
   0, 0,		/* Start position. */
   SBMWIDTH, SBMHEIGHT, SBMDEPTH,	/* Width, height, depth. */
   0, 0,		/* Default detail pen, block pen. */
   NULL,		/* Viewing mode. */
   CUSTOMSCREEN | CUSTOMBITMAP,		/* Screen type. DBL BUF */
   &TestFont,		/* Font to use. */
   NULL,		/* No default title. */
   NULL,		/* No pointer to additional gadgets. */
   NULL			/* No pointer to CustomBitMap. */
};

/* These are for my window. */
struct Window *window = NULL;
struct NewWindow nw = {
   0, 0,		/* Start position. */
   SBMWIDTH, SBMHEIGHT,	/* Width, height. */
   0, 0,		/* Detail pen, block pen. */
   CLOSEWINDOW,		/* IDCMP flags. */
   WINDOWCLOSE | BORDERLESS,		/* Flags. */
   NULL,		/* No pointer to FirstGadget. */
   NULL,		/* No pointer to first CheckMark. */
   NULL,		/* No default Title. */
   NULL,		/* No pointer to Screen. */
   NULL,		/* No pointer to BitMap. */
   0, 0,		/* MinWidth, MinHeight (not used). */
   SBMWIDTH, SBMHEIGHT,	/* MaxWidth, MaxHeight (not used). */
   CUSTOMSCREEN		/* Screen type. */
};

/*******************************************************************************
 * This will be called if a sprite collision with the border is detected.
 */

borderPatrol(s, b)
struct VSprite *s;
int b;
{
   register struct vInfo *info;

   info = &s->VUserExt;
   if (b & (TOPHIT | BOTTOMHIT))	/* Top/Bottom hit, change direction. */
      info->vy = -(info->vy);
   if (b & (LEFTHIT | RIGHTHIT))	/* Left/Right hit, change direction. */
      info->vx = -(info->vx);

}

/*******************************************************************************
 * Fun Starts.
 */

main()
{
   SHORT i, j;

   /* Open libraries that will be used directly. */
   if ((IntuitionBase = (struct IntuitionBase *)
         OpenLibrary("intuition.library", LIBRARY_VERSION)) == 0) {
#ifdef DEBUG
      kprintf("Main: Can't open Intuition.\n");
#endif
      MyCleanup();
      Exit(-1);
   }

   if ((GfxBase = (struct GfxBase *)
         OpenLibrary("graphics.library", LIBRARY_VERSION)) == 0) {
#ifdef DEBUG
      kprintf("Main: Can't open Graphics.\n");
#endif
      MyCleanup();
      Exit(-1);
   }

/*******************************************************************************
 * DBL BUF
 */
   for(j=0; j<2; j++) {
      if ((MyBitMapPtrs[j] = (struct BitMap *)
            AllocMem(sizeof(struct BitMap), MEMF_CHIP)) == 0) {
#ifdef DEBUG
         kprintf("Main: Can't allocate BitMap.\n");
#endif
         MyCleanup();
         Exit(-1);
      }
      InitBitMap(MyBitMapPtrs[j], RBMDEPTH, RBMWIDTH, RBMHEIGHT);
      for(i=0; i<RBMDEPTH; i++) {
         if ((MyBitMapPtrs[j]->Planes[i] = (PLANEPTR)AllocRaster(RBMWIDTH,
               RBMHEIGHT)) == 0) {
#ifdef DEBUG
            kprintf("Main: Can't allocate BitMaps' Planes.\n");
#endif
            MyCleanup();
            Exit(-1);
         }
         BltClear(MyBitMapPtrs[j]->Planes[i], (RBMWIDTH / 8) * RBMHEIGHT, 1);
      }
   }
   ns.CustomBitMap = MyBitMapPtrs[0]; /* !! */
   screen->RastPort.Flags = DBUFFER;

   /* Open My Very Own Screen. */
   if ((screen = (struct Screen *)OpenScreen(&ns)) == 0) {
#ifdef DEBUG
      kprintf("Main: Can't open Screen.\n");
#endif
      MyCleanup();
      Exit(-1);
   }

   /* Now get that flashing title bar off the display. DBL BUF */
/*
   screen->ViewPort.RasInfo->RxOffset = 5;
   screen->ViewPort.RasInfo->RyOffset = 5;
*/

   /* Set screens' colors (Could've used LoadRGB4()). */

   /* Values changed by DCW because Manx thinks that 08 is a bad octal
    * number. Picky, but correct. So 08 == 8 & 09 == 9 etc.
    */
   SetRGB4(&screen->ViewPort, 00, 00, 00, 00);
   SetRGB4(&screen->ViewPort, 01, 15, 00, 00);
   SetRGB4(&screen->ViewPort, 02, 00, 15, 00);
   SetRGB4(&screen->ViewPort, 03, 00, 00, 15);
   SetRGB4(&screen->ViewPort, 04, 15, 15, 00);
   SetRGB4(&screen->ViewPort, 05, 15, 00, 15);
   SetRGB4(&screen->ViewPort, 06,  8, 15, 15);
   SetRGB4(&screen->ViewPort, 07, 15, 11, 00);
   SetRGB4(&screen->ViewPort,  8, 05, 13, 00);
   SetRGB4(&screen->ViewPort,  9, 14, 03, 00);
   SetRGB4(&screen->ViewPort, 10, 15, 02, 14);
   SetRGB4(&screen->ViewPort, 11, 15, 13, 11);
   SetRGB4(&screen->ViewPort, 12, 12,  9,  8);
   SetRGB4(&screen->ViewPort, 13, 11, 11, 11);
   SetRGB4(&screen->ViewPort, 14, 07, 13, 15);
   SetRGB4(&screen->ViewPort, 15, 15, 15, 15);

   nw.Screen = screen;

   if ((window = (struct Window *)OpenWindow(&nw)) == 0) {
#ifdef DEBUG
      kprintf("Main: Can't open Window.\n");
#endif
      MyCleanup();
      Exit(-1);
   }

  /*****************************************************************************
   * Now that the screen envirionment is set up, It's time to set up the
   * gels system.
   */

   /* ReadyGels is in GelTools(). */
   if (ReadyGels(&GInfo, &screen->RastPort) != 0) {
#ifdef DEBUG
      kprintf("Main: ReadyGels failed.\n");
#endif
      MyCleanup();
      Exit(-1);
   }

   SetCollision(0, borderPatrol, &GInfo);

   /* Copy Images to chip memory. */
   if (!InitImages()) {
#ifdef DEBUG
      kprintf("Main: InitImages() failed.\n");
#endif
      MyCleanup();
      Exit(-1);
   }

  /*****************************************************************************
   * System is set up, now set up each Gel.
   */

   /* First use the routines in geltools to get the sprite. */
   for(i = 0; i < NSPRITES; i++) {
      if ((VSprites[i] = (struct VSprite *)MakeVSprite(VSPRITEHEIGHT,
            VSpriteImage_chip, &MyVSpriteColors[0], i*6, (i*8)+10,
            VSPRITEWIDTH,  VSPRITEDEPTH, VSPRITE)) == 0) {
#ifdef DEBUG
         kprintf("Main: MakeVSprite failed.\n");
#endif
         MyCleanup();
         Exit(-1);
      }

      VSprites[i]->VUserExt.vx = 1;
      VSprites[i]->VUserExt.vy = 1;
      VSprites[i]->VUserExt.id = i;

      AddVSprite(VSprites[i], &screen->RastPort);
   }

   /* First use the routines in geltools to get the bob. */
   for(i = 0; i < NBOBS; i++) {
      if ((Bobs[i] = (struct Bob *)MakeBob(BOBWIDTH, BOBHEIGHT, BOBDEPTH,
            BobImage_chip, 0x0F, 0x00, (i*6), (i*8)+10,
            SAVEBACK | OVERLAY)) == 0) {
#ifdef DEBUG
         kprintf("Main: MakeBob failed.\n");
#endif
         MyCleanup();
         Exit(-1);
      }

      Bobs[i]->BobVSprite->VUserExt.vx = 1;
      Bobs[i]->BobVSprite->VUserExt.vy = 1;
      Bobs[i]->BobVSprite->VUserExt.id = i;

      /* DBL BUF */
      if ((Bobs[i]->DBuffer = (struct DBufPacket *)AllocMem (sizeof(struct
            DBufPacket), MEMF_CHIP)) == 0) {
#ifdef DEBUG
         kprintf("Main: Can't allocate double buffers' packet for a bob.\n");
#endif
         MyCleanup();
         Exit(-1);
      }
      if ((Bobs[i]->DBuffer->BufBuffer = (WORD *)AllocMem (sizeof(SHORT) *
            ((BOBWIDTH+15)/16) * BOBHEIGHT * BOBDEPTH, MEMF_CHIP)) == 0) {
#ifdef DEBUG
         kprintf("Main: Can't allocate double buffer for a bob.\n");
#endif
         MyCleanup();
         Exit(-1);
      }
      AddBob(Bobs[i], &screen->RastPort);

      /* The following relies on the fact that AddBob sets the before
       * and after pointers to 0, so the first before and last after.
       * are left alone.
       * Earlier bob has higher priority, thus this bob'll be drawn
       * AFTER that one, thus this bob will appear on top of all earlier
       * ones. One could set the bobs to be drawn in any order by rearranging
       * these pointers.
       */
      if (i > 0) {
         Bobs[i]->After = Bobs[i-1];
         Bobs[i]->After->Before = Bobs[i];
      }
   }  /* End of for. */

  /*****************************************************************************
   * Hey, wow, everything opened, and allocated, and initialized! Whew.
   */
   for (;;) {
      DrawGels();

      while (MyIntuiMessage = (struct IntuiMessage *)
            GetMsg(window->UserPort))
         switch (MyIntuiMessage->Class) {
            case CLOSEWINDOW:
               ReplyMsg(MyIntuiMessage);
               MyCleanup();
               Exit(TRUE);
               break;
            default:
               ReplyMsg(MyIntuiMessage);
               break;
         }
   }
}

/*******************************************************************************
 * DrawGels part of loop.
 */

DrawGels()
{
   register struct VSprite *pSprite;

   /* Move everything in the sprite list. This includes Bobs. */
   pSprite = GInfo.gelHead->NextVSprite;
   while (pSprite != GInfo.gelTail){
      pSprite->X += pSprite->VUserExt.vx;
      pSprite->Y += pSprite->VUserExt.vy;
      pSprite = pSprite->NextVSprite;
   }

   SortGList(&screen->RastPort);        /* Put the list in order. */
   DoCollision(&screen->RastPort);	/* Collision routines may called now. */
   DrawGList(&screen->RastPort,&screen->ViewPort);      /* Draw 'em. */
   screen->ViewPort.RasInfo->BitMap = MyBitMapPtrs[ToggleFrame];   /* DBL BUF */
   WaitTOF();                           /* When the beam hits the top... */
   MakeScreen(screen);                  /* Tell intuition to do it's stuff. */
   RethinkDisplay();                    /* Does a MrgCop & LoadView. */
   ToggleFrame ^=1;						   /* DBL BUF */
   screen->RastPort.BitMap = MyBitMapPtrs[ToggleFrame];		   /* DBL BUF */
}

/*******************************************************************************
 * This will be called in case of error, or when main is done.
 */

MyCleanup()
{
   short i, j;

   for (i=0; i < NBOBS; i++) {
      if (Bobs[i] != NULL) {
        DeleteGel(Bobs[i]->BobVSprite);
      }
   }

   for (i=0; i < NSPRITES; i++) {
      if (VSprites[i] != NULL) {
        DeleteGel(VSprites[i]);
      }
   }
   PurgeGels(&GInfo);
   FreeImages();
   if (window != NULL)
      CloseWindow(window);
   if (screen != NULL)
      CloseScreen(screen);

   /* DBL BUF */
   for(j=0; j<2; j++) {
      if (MyBitMapPtrs[j] != NULL) {
         for(i=0; i<RBMDEPTH; i++) {
         if (MyBitMapPtrs[j]->Planes[i] != 0)
            FreeRaster(MyBitMapPtrs[j]->Planes[i], RBMWIDTH, RBMHEIGHT);
        }
         FreeMem(MyBitMapPtrs[j], sizeof(struct BitMap));
     }
   }

   if (GfxBase != NULL)
      CloseLibrary(GfxBase);
   if (IntuitionBase != NULL)
      CloseLibrary(IntuitionBase);
}

InitImages()
{
   extern USHORT *VSpriteImage_chip;
   extern USHORT *BobImage_chip;
   int i;

   if ((VSpriteImage_chip = (USHORT *)
         AllocMem(sizeof(VSpriteImage), MEMF_CHIP)) == 0) {
#ifdef DEBUG
      kprintf("InitImages: No Memory for VSpriteImage.\n");
#endif
      return(FALSE);
   }
   if ((BobImage_chip = (USHORT *)
         AllocMem(sizeof(BobImage), MEMF_CHIP)) == 0) {
#ifdef DEBUG
      kprintf("InitImages: No Memory for BobImage.\n");
#endif
      return(FALSE);
   }
   for(i=0; i<24; i++)
      VSpriteImage_chip[i] = VSpriteImage[i];
   for(i=0; i<496; i++)
      BobImage_chip[i] = BobImage[i];
   return(TRUE);
}

FreeImages()
{
   extern USHORT *VSpriteImage_chip;
   extern USHORT *BobImage_chip;

   if (VSpriteImage_chip != 0)
         FreeMem(VSpriteImage_chip, sizeof(VSpriteImage));
   if (BobImage_chip != 0)
         FreeMem(BobImage_chip, sizeof(BobImage));
}
