//---------------------------------------------------------------------------
// Background class
//---------------------------------------------------------------------------

#include <sys\types.h>
#include <libetc.h>
#include <libgte.h>
#include <libgpu.h>
#include <rand.h>
#include <libcd.h>
#include <memory.h>

extern u_long FrameCounter;
extern int    NightVision;
extern int    NightVisionCnt;
extern char   CarChaseTimerNear;
extern char   CarChaseTimerFar;
extern int    LevelSelected;
extern int    LE1orLE2;

#ifndef __point
   #define __point
   typedef struct
   {
      int x;
      int y;
   } point;
#endif

#include "..\include\compile.h"
#include "..\include\readfile.h"
#include "..\include\db.h"
#include "..\include\alocvram.h"
#include "..\include\bkgnd.h"

//-------------------------------------
// Constructor
//-------------------------------------
Background::Background ()
{
   int i;

   BkdX = 0;
   BkdY = 0;
   DestX = 0;
   DestY = 0;
   DestStep = 0;
   DestTotalStep = 0;

   for (i = 0; i < BKDMAXIMAGE; i++)
   {
      VramMemHandle[i] = -1;
      ClutY[i] = -1;
   }
}

//-------------------------------------
// Load a background
//-------------------------------------
int Background::Load (char filename[], u_long *memptr)
{
   char *memloc;
   int i, j;

   BkdAngle = 0;
   BKDType = 0;
   StreetX = 0;
   ColumnX = 0;
   Acceler = 0;
   DeltaX = 3;
   BackX = 0;
   FrontX = 3000;
   Shaking = 0;

   // Load the ricochet file
   for (i = 0; (filename[i] != '.') && (filename[i] != 0); i++)
      filnam[i] = filename[i];
   filnam[i] = '.';
   filnam[i + 1] = 'R';
   filnam[i + 2] = 'I';
   filnam[i + 3] = 'C';
   filnam[i + 4] = 0;
   if (LoadRicochetMap (filnam, memptr))
      return (0);

   memloc = (char *)*memptr;

   if ((u_long)memloc & 3)
      memloc = (char *)(((u_long)memloc + 4) & 0xFFFFFFFC);

   if (OpenFile (filename) == -1)
      return (0);

   //----------------------------------
   // Reads the header of the animation file
   if (ReadFile (memloc, 9) != 9)
   {
      CloseFile ();
      return (0);
   }

   // Check to be sure it is an Animation file
   if ((memloc[0] != 'B') || (memloc[1] != 'G'))
   {
      CloseFile ();
      return (0);
   }

   NbrSpr = memloc[2] + (memloc[3] << 8);
   NbrImage = memloc[4];
   BkdWidth = memloc[5] + (memloc[6] << 8);
   BkdHeight = memloc[7] + (memloc[8] << 8);

   //----------------------------------
   // Reads the width and height of the images
   if (ReadFile (memloc, 4 * NbrImage) != 4 * NbrImage)
   {
      CloseFile ();
      return (0);
   }
   for (i = 0; i < NbrImage; i++)
   {
      ImageWidth[i] = memloc[i << 1] + (memloc[(i << 1) + 1] << 8);
      ImageHeight[i] = memloc[(NbrImage << 1) + (i << 1)] +
                       (memloc[(NbrImage << 1) + (i << 1) + 1] << 8);
   }

   //----------------------------------
   // Reads the width of every sprite
   if (ReadFile ((char *)SprW, NbrSpr) != NbrSpr)
   {
      CloseFile ();
      return (0);
   }

   // Reads the height of every sprite
   if (ReadFile ((char *)SprH, NbrSpr) != NbrSpr)
   {
      CloseFile ();
      return (0);
   }

   // Reads the relative x coordinate of every sprite in the bkd
   if (ReadFile ((char *)SprX, NbrSpr << 1) != NbrSpr << 1)
   {
      CloseFile ();
      return (0);
   }

   // Reads the relative y coordinate of every sprite in the bkd
   if (ReadFile ((char *)SprY, NbrSpr << 1) != NbrSpr << 1)
   {
      CloseFile ();
      return (0);
   }

   // Reads the U coordinate of every sprite in the tpage
   if (ReadFile ((char *)SprU, NbrSpr << 1) != NbrSpr << 1)
   {
      CloseFile ();
      return (0);
   }

   // Reads the V coordinate of every sprite in the tpage
   if (ReadFile ((char *)SprV, NbrSpr) != NbrSpr)
   {
      CloseFile ();
      return (0);
   }

   // Reads the layer # of every sprite
   if (ReadFile ((char *)SprLayer, NbrSpr) != NbrSpr)
   {
      CloseFile ();
      return (0);
   }
   for (i = 0; i < NbrSpr; i++)
      SprLayer[i] = SprLayer[i] * 5;

   // Reads the image # of every sprite
   if (ReadFile ((char *)SprImage, NbrSpr) != NbrSpr)
   {
      CloseFile ();
      return (0);
   }

   //----------------------------------
   // Reads the clut size
   if (ReadFile (memloc, 5) != 5)
   {
      CloseFile ();
      return (0);
   }
   if ((memloc[2] != 'p') || (memloc[3] != 'a') || (memloc[4] != 'l'))
   {
      CloseFile ();
      return (0);
   }

   i = memloc[0] + memloc[1] * 256;

   // Read the cluts
   for (j = 0; j < NbrImage; j++)
   {
//      if ((LE1orLE2 == 1) && (LevelSelected == 3) && (j == 5))
//      {                                                 // Train robbery...
//         if (ReadFile ((char *)ActualClut[j], 32) != 32)
//         {
//            CloseFile ();
//            return (0);
//         }
//      }
//      else
//      {
         if (ReadFile ((char *)ActualClut[j], (i << 1)) != (i << 1))
         {
            CloseFile ();
            return (0);
         }
//      }
   }

   //----------------------------------
   // Reads the hit map width
   if (ReadFile ((char *)&HitMapW, 2) != 2)
   {
      CloseFile ();
      return (0);
   }

   // Reads the hit map height
   if (ReadFile ((char *)&HitMapH, 2) != 2)
   {
      CloseFile ();
      return (0);
   }

   // Reads the hit map itself
   if (ReadFile ((char *)memloc, HitMapW * HitMapH * 3) != HitMapW * HitMapH * 3)
   {
      CloseFile ();
      return (0);
   }

   HitMapAddr[0] = (u_char *)memloc;
   HitMapAddr[1] = (u_char *)memloc + (HitMapW * HitMapH);
   HitMapAddr[2] = (u_char *)memloc + (HitMapW * HitMapH * 2);
   memloc = (char *)((int)memloc + (HitMapW * HitMapH * 3));

   // Reads the images themselves
   for (i = 0; i < NbrImage; i++)
   {
      if ((u_long)memloc & 3)
         memloc = (char *)(((u_long)memloc + 4) & 0xFFFFFFFC);
      Address[i] = (u_long *)memloc;
      if (ReadFile ((char *)memloc, (ImageWidth[i] * ImageHeight[i])) !=
          (ImageWidth[i] * ImageHeight[i]))
      {
         CloseFile ();
         return (0);
      }
      memloc = (char *)((int)memloc + (ImageWidth[i] * ImageHeight[i]));
   }

   // Check if the file is terminated by 'end'
   if (ReadFile (memloc, 3) != 3)
   {
      CloseFile ();
      return (0);
   }

   if (!((memloc[0] == 'e') && (memloc[1] == 'n') && (memloc[2] == 'd')))
   {
      CloseFile ();
      return (0);
   }

   if (CloseFile () == -1)
      return (0);

   for (i = 0; i < NbrImage; i++)
   {
      if (ImageWidth[i] <= 128)
         VramSpace[i] = AllocVram (ImageWidth[i] >> 1, ImageHeight[i],
                                   &VramMemHandle[i], 0);
      else
         VramSpace[i] = AllocVram (ImageWidth[i] >> 1, ImageHeight[i],
                                   &VramMemHandle[i], 1);
      if (VramSpace[i].x == -1)
         return (0);

      // Put image in VRAM
      RECT dest = {VramSpace[i].x,VramSpace[i].y,
                   ImageWidth[i] / 2,ImageHeight[i]};
      LoadImage (&dest, Address[i]);
   }

   for (i = 0; i < NbrImage; i++)
   {
      if ((ClutY[i] = AllocClut () + 480) == 479)
         return (0);

      RECT rect = {0,ClutY[i], 256,1};          // Put clut in vram
      LoadImage (&rect, (u_long *)ActualClut[i]);
   }

   for (i = 0; i < NbrSpr; i++)
   {
      SprXTP[i] = (VramSpace[SprImage[i]].x & ~63) + ((SprU[i] >> 1) & ~63);
      SprYTP[i] = VramSpace[SprImage[i]].y & ~255;
      SprU[i] = (SprU[i] & 127) + (VramSpace[SprImage[i]].x & 63) * 2;
      SprV[i] += VramSpace[SprImage[i]].y & 255;
   }

   (*memptr) = ((u_long)HitMapAddr[2] + HitMapW * HitMapH);

   for (i = 0; i < BKDMAXIMAGE; i++)
      BWChangeComplete[i] = -1;

   return (-1);
}

//-------------------------------------
// Change a clut so that it becomes
// closer to a specified target clut.
// Returns 0 if both cluts are the
// same.
//-------------------------------------
int Background::ChangeClut (void)
{
   int i, j, k;
   int temp;

   for (k = 0; k < NbrImage; k++)
   {
      j = 256;

      if (BWChangeComplete[k] == 0)
      {
         for (i = 0; i < 256; i++)
         {
            if (ActualClut[k][i] == DestClut[k][i])
               j--;
            else
            {
               temp = ActualClut[k][i] & 31;
               if (temp != (DestClut[k][i] & 31))
               {
                  ActualClut[k][i] &= ~31;
                  if (temp > (DestClut[k][i] & 31))
                     ActualClut[k][i] |= temp - 1;
                  else
                     ActualClut[k][i] |= temp + 1;
               }

               temp = ActualClut[k][i] & 992;
               if (temp != (DestClut[k][i] & 992))
               {
                  ActualClut[k][i] &= ~992;
                  if (temp > (DestClut[k][i] & 992))
                     ActualClut[k][i] |= temp - 32;
                  else
                     ActualClut[k][i] |= temp + 32;
               }

               temp = ActualClut[k][i] & 31744;
               if (temp != (DestClut[k][i] & 31744))
               {
                  ActualClut[k][i] &= ~31744;
                  if (temp > (DestClut[k][i] & 31744))
                     ActualClut[k][i] |= temp - 1024;
                  else
                     ActualClut[k][i] |= temp + 1024;
               }
            }
         }
      }
      else
         j = 0;

      if (j == 0)
      {
         BWChangeComplete[k] = -1;

         if (NightVision == 6)
         {
            NightVision = 7;
         }
         else if (NightVision == 2)
         {
            NightVision = 3;
            NightVisionCnt = 300;
         }
      }

      RECT rect = {0,ClutY[k], 256,1};    // Put new clut in vram
      LoadImage (&rect, (u_long *)ActualClut[k]);
   }

   return (j);
}

//-------------------------------------
// Clear the memory allocated for the
// background
//-------------------------------------
// return -1 if error
//-------------------------------------
int Background::Clear (void)
{
   int i;

   for (i = 0; i < NbrImage; i++)
   {
      if (ClutY[i] != -1)
      {
         if (FreeClut (ClutY[i] - 480) == 0)
            return (0);
         else
            ClutY[i] = -1;
      }
      if (VramMemHandle[i] != -1)
      {
         if (FreeVram (VramMemHandle[i]) == 0)
            return (0);
         else
            VramMemHandle[i] = -1;
      }
   }
   return (-1);
}

//-------------------------------------
// Scroll the background to a specified
// coordinate.
//-------------------------------------
int Background::ScrollTo (int coorx, int coory, int step)
{
   DestX = coorx;
   DestY = coory;
   DestTotalStep = step;
   DestStep = 0;
}

//-------------------------------------
// Set background location relative to
// the screen coordinate
//-------------------------------------
void Background::SetLocation (int coorx, int coory)
{
   SourceX = coorx;
   SourceY = coory;
   DestX = coorx;
   DestY = coory;
   DestTotalStep = 0;
   DestStep = 0;
   BkdX = coorx;
   BkdY = coory;
}

//-------------------------------------
// Return the actual background's X
// coordinate
//-------------------------------------
int Background::Bkd_X ()
{
   return (BkdX);
}

//-------------------------------------
// Return the actual background's Y
// coordinate
//-------------------------------------
int Background::Bkd_Y ()
{
   short Shaker[8] = {0,-2,-4,-2,0,2,4,2};
   return (BkdY + Shaker[Shaking & 7]);
}

//-------------------------------------
// Check if the background has been
// shot.  If not, return (0).
// Otherwise, return -1.
//-------------------------------------
int Background::GetHit (int level, int coorx, int coory, int *sfx, int *vab)
{
   int i, j;
   short Shaker[8] = {0,-2,-4,-2,0,2,4,2};

   *sfx = -1;
   *vab = -1;

   if ((BKDType == 1) || (BKDType == 4) || (BKDType == 10))  // Car chases don't have a hit map
      return (0);

   if (Shaking)
      coory -= Shaker[Shaking & 7];

   //----------------------------------
   coorx >>= 1;                         // Check if there is a hit
   coory >>= 1;

   i = coory * HitMapW + (coorx >> 3);
   j = coorx & 7;

   if ((HitMapAddr[level][i] >> j) & 1)
   {
      coorx >>= 2;                      // There is a hit... return the
      coory >>= 2;                      // correct sfx and vab number
      i = coory * RicochetW + coorx;
      if ((Ricochet[i] == 'b') || (Ricochet[i] == 'w'))
      {
         *sfx = 8;
         *vab = 0;
      }
      else if (Ricochet[i] == 'm')
      {
         *sfx = 9;
         *vab = 0;
      }

      return (-1);
   }
   else
      return (0);
}

//-------------------------------------
// Load a ricochet map
//-------------------------------------
int Background::LoadRicochetMap (char filename[], u_long *memptr)
{
   char *memloc;

   OpenFile (filename);

   memloc = (char *)*memptr;

   RicochetW = 1234;
   RicochetH = 5678;
   // Reads the header of the ricochet file
   ReadFile (memloc, 5);

   // Check to be sure it is a ricochet file
   if ((memloc[0] != 'r') || (memloc[1] != 'i') || (memloc[2] != 'c'))
   {
      FntPrint ("Can't read file:\n");
      //DumpMessage (filename);
      while (1);
   }
   RicochetW = memloc[3];
   RicochetH = memloc[4];

   // Reads the data in the ricochet
   ReadFile (memloc, RicochetW * RicochetH);

   Ricochet = memloc;

   memloc += RicochetW * RicochetH;

   // Reads the end of the ricochet file
   ReadFile (memloc, 3);
   if ((memloc[0] != 'e') || (memloc[1] != 'n') || (memloc[2] != 'd'))
   {
      FntPrint ("Can't read file:\n");
      //DumpMessage (filename);
      while (1);
   }

   *memptr = (u_long)memloc;
   if (CloseFile () == -1)
   {
      FntPrint ("Can't close file:\n");
      //DumpMessage (filename);
      while (1);
   }
}

//-------------------------------------
//
//-------------------------------------
void Background::DumpData (void)
{
   int i;

   FntPrint ("ImageWidth:");
   for (i = 0; i < 10; i++)
      FntPrint (" %d", ImageWidth[i]);
   FntPrint ("\nImageHeight:");
   for (i = 0; i < 10; i++)
      FntPrint (" %d", ImageHeight[i]);
   FntPrint ("\nSprImage:");
   for (i = 0; i < NbrSpr; i++)
      FntPrint (" %d", SprImage[i]);
   FntPrint ("\n");
}

//-------------------------------------
// Build a destination clut
//-------------------------------------
// 0 = Fade to Black & white
// 1 = Fade to White
// 2 = Fade to Black
// 3 = Go to Green
// 4 = Go Back to color
//-------------------------------------
void Background::BuildDestClut (int typeclut)
{
   int i, j, temp;

   if (typeclut == 0)                   // Black & white with fading
   {
      for (j = 0; j < NbrImage; j++)
      {
         for (i = 0; i < 256; i++)
         {
            temp = ((ActualClut[j][i] & 31) + ((ActualClut[j][i] & 992) >> 5) +
                    ((ActualClut[j][i] & 31744) >> 10)) / 3;
            if ((temp == 0) && ((ActualClut[j][i] & ~32768) != 0))
               temp = 1;
            DestClut[j][i] = temp + (temp << 5) + (temp << 10) +
                             (ActualClut[j][i] & 32768);
         }
      }
      for (i = 0; i < BKDMAXIMAGE; i++)
         BWChangeComplete[i] = 0;
   }
   else if (typeclut == 1)              // White with fading
   {
      for (j = 0; j < NbrImage; j++)
      {
         for (i = 0; i < 256; i++)
         {
            if ((ActualClut[j][i] & ~32768) == 0)
               DestClut[j][i] = ActualClut[j][i];
            else
               DestClut[j][i] = 0x7FFF + (ActualClut[j][i] & 0x8000);
         }
      }
      for (i = 0; i < BKDMAXIMAGE; i++)
         BWChangeComplete[i] = 0;
   }
   else if (typeclut == 2)              // Black with fading
   {
      for (j = 0; j < NbrImage; j++)
      {
         for (i = 0; i < 256; i++)
         {
            if ((ActualClut[j][i] & ~32768) == 0)
               DestClut[j][i] = ActualClut[j][i];
            else
               DestClut[j][i] = (ActualClut[j][i] & 0x8000) + 0x421;
         }
      }
      for (i = 0; i < BKDMAXIMAGE; i++)
         BWChangeComplete[i] = 0;
   }
   else if (typeclut == 3)              // Green without fading
   {
      for (j = 0; j < NbrImage; j++)
      {
         for (i = 0; i < 256; i++)
         {
            temp = ((OriginalClut[j][i] & 31) + ((OriginalClut[j][i] & 992) >> 5) +
                    ((OriginalClut[j][i] & 31744) >> 10)) / 3;
            if ((temp == 0) && ((OriginalClut[j][i] & ~32768) != 0))
               temp = 1;
            if ((~ActualClut[j][i] & 0x8000) && (temp == 0))
               ActualClut[j][i] = 0x0;
            else
            {
               if (temp == 0x1F)
                  temp = 0x1E;
               ActualClut[j][i] = (~(temp << 5)) & 0x3E0 + (ActualClut[j][i] & 0x8000);
            }
         }

         RECT rect = {0,ClutY[j], 256,1};          // Put clut in vram
         LoadImage (&rect, (u_long *)ActualClut[j]);
      }
      for (i = 0; i < BKDMAXIMAGE; i++)
         BWChangeComplete[i] = -1;
   }
   else if (typeclut == 4)              // Color without fading
   {
      for (j = 0; j < NbrImage; j++)
      {
         for (i = 0; i < 256; i++)
            ActualClut[j][i] = OriginalClut[j][i];

         RECT rect = {0,ClutY[j], 256,1};          // Put clut in vram
         LoadImage (&rect, (u_long *)ActualClut[j]);
      }
      for (i = 0; i < BKDMAXIMAGE; i++)
         BWChangeComplete[i] = -1;
   }
}

//-------------------------------------
// Draw a background's layer
//-------------------------------------
void Background::Draw (DoubleBuffer *db, int pause)
{
   int i;
   short Shaker[8] = {0,-2,-4,-2,0,2,4,2};
   SPRT *spr;
   DR_MODE *drmode;
   int bkdy;

   if (BKDType == 1)
   {
      DrawStreet (db, pause);
      return;
   }
   else if (BKDType == 2)
   {
      DrawSubway (db, pause);
      return;
   }
   else if (BKDType == 3)
      DrawAirport4 (db, pause);
   else if (BKDType == 5)
   {
      DrawCalibration (db);
      return;
   }
   else if (BKDType == 4)
   {
      DrawHighway (db, pause);
      return;
   }
   else if (BKDType == 6)
      DrawConveyer (db, pause);
   else if (BKDType == 9)
   {
      DrawStage2 (db, pause);
      return;
   }
   else if (BKDType == 10)
   {
      DrawTrain (db, pause);
      return;
   }

   if (!pause)
   {
      if (DestStep < DestTotalStep)
      {
         if (DestStep != DestTotalStep)
            DestStep++;
         BkdX = SourceX + ((DestX - SourceX) * DestStep / DestTotalStep);
         BkdY = SourceY + ((DestY - SourceY) * DestStep / DestTotalStep);
      }
      else
      {
         BkdX = DestX;
         BkdY = DestY;
         SourceX = DestX;
         SourceY = DestY;
      }

      if (Shaking)
         Shaking--;
   }

   bkdy = BkdY + Shaker[Shaking & 7];

   int k = NbrSpr;
   if (BKDType == 3)
      k--;
   for (i = 0; i < k; i++)
   {
      if (!((SprX[i] + BkdX >= SCREENWIDTH) ||   // Don't draw the sprites
          (SprY[i] + bkdy >= SCREENHEIGHT) ||    // that are out of the
          (SprX[i] + BkdX + SprW[i] <= 0) ||     // screen
          (SprY[i] + bkdy + SprH[i] <= 0)))
      {
         /* Put the sprite itself in the OT */
         spr = db->Get_Spr ();
         setXY0 (spr, SprX[i] + BkdX, SprY[i] + bkdy);
         setUV0 (spr, SprU[i], SprV[i]);
         spr->w = SprW[i];
         spr->h = SprH[i];
         spr->clut = GetClut (0, ClutY[SprImage[i]]);

         db->Add_Spr (spr, SprLayer[i]);

         /* Put the new drawing environment in the OT */
         drmode = db->Get_DrMode ();    
         RECT rect = {SprXTP[i], SprYTP[i], 256, 256};
         SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[i], SprYTP[i]), &rect);
         db->Add_DrMode (drmode, SprLayer[i]);
      }
   }

   if (BKDType == 7)
      DrawAirport3 (db);
}

//-------------------------------------
// Set background's type:
//    0 = Normal
//    1 = Bank's car chase
//    2 = To be defined.
//-------------------------------------
void Background::SetBKDType (int bkdtype, u_long *memptr)
{
   char *memloc = (char *)*memptr;
   int i, j;
   BKDType = bkdtype;

   switch (bkdtype)
   {
      case 1: StreetX = 0;
              ColumnX = 0;
              Acceler = 0;
              DeltaX = 3;
              BackX = 0;
              FrontX = 3000;
              break;
      case 2: BackX = 0;
              FrontX = 0;
              break;
      case 3: FrontX = 0;
              BackX = 0;
              for (i = 0; i < NbrSpr; i++)
                 if (SprLayer[i] == 0)
                    SprLayer[i] = 1;
              break;
      case 4: StreetX = 0;
              BackX = 270;
              FrontX = 0;
              FrontY = 0;
              MiddleX = 0;
              BarrierX = 3500;
              break;
      case 6: FrontX = -63;
              break;
      case 8: for (i = 0; i < NbrImage; i++)
              {
                 if ((u_long)memloc & 3)
                    memloc = (char *)(((u_long)memloc + 4) & 0xFFFFFFFC);
                 OriginalClut[i] = (u_short *)memloc;
                 memloc += 512;
                 for (j = 0; j < 256; j++)
                    OriginalClut[i][j] = ActualClut[i][j];
              }
              (*memptr) = (u_long)memloc;
              break;
      case 9: BackX = 8400;     // Start mountains down
              FrontX = 0;
              break;
      case 10: FrontX = 0;
               ColumnX = 250;
               BkdX = 0;
               break;
   }
}

//-------------------------------------
// Make the background to shake
//-------------------------------------
void Background::Shake (void)
{
   Shaking = 64;
}

//-------------------------------------
// Draw the car chase background
// (Bank 3)
//-------------------------------------
void Background::DrawStreet (DoubleBuffer *db, int pause)
{
   POLY_FT4 *polygon;
   SPRT *spr;
   DR_MODE *drmode;
   int i, j, k;
   short Shaker[8] = {0,-2,-4,-2,0,2,4,2};
   u_char BackPattern[124] = {30,31,32,33,30,31,32,33,30,31,32,33, 0, 1, 2, 3, 0, 1, 2, 3,40,41,42,43,
                              40,41,42,43,30,31,32,33,30,31,32,33,30,31,32,33,30,31,32,33,30,31,32,33,
                              36,37,38,39,36,37,38,39, 0, 1, 2, 3, 0, 1, 2, 3, 9,10,11,40,41,42,43,30,
                              31,32,33,30,31,32,33,24,25,30,31,32,33,30,31,32,33,24,25,30,31,32,33,22,
                              23,22,23,22,23,22,23,30,31,32,33, 4, 5, 6, 7, 8,30,31,32,33, 0, 1, 2, 3,
                              40,41,42,43};
   u_char FrontPattern[6] =  {9,10,11,12,13,14};

   int bkdy = Shaker[Shaking & 7];

   if (!pause)
   {
      Acceler++;
      if (Acceler == 40)
      {
         Acceler = 0;
         if (DeltaX < 8)
            DeltaX++;
      }
   }

   for (i = -2; i < 4; i++)
   {
      int actualxh = ((StreetX) + i * 64) + 160;
      int actualxl = ((StreetX * 2) + i * 128) + 160;
      polygon = db->Get_Poly ();
      polygon->u0 = polygon->u2 = SprU[34];
      polygon->u1 = polygon->u3 = SprU[34] + SprW[34] - 1;
      polygon->v0 = polygon->v1 = SprV[34];
      polygon->v2 = polygon->v3 = SprV[34] + SprH[34] - 1;
      polygon->tpage = GetTPage (1, 0, SprXTP[34], SprYTP[34]);
      polygon->clut = GetClut (0, ClutY[SprImage[34]]);
      SetSemiTrans (polygon, 0);
      SetShadeTex (polygon, 1);
      setXY4 (polygon, actualxh - 32,bkdy + 96, actualxh + 32,bkdy + 96,
                       actualxl - 64,bkdy + 240, actualxl + 64,bkdy + 240);
      db->Add_Poly (polygon, 0);
   }

   if (!pause)
   {
      if ((StreetX -= DeltaX) <= -64)
         StreetX += 64;
      if ((ColumnX -= DeltaX * 2) <= -480)
         ColumnX += 480 + 320;
   }

   //-- Draw the column in foreground -
   if ((ColumnX < 320) && (ColumnX > -63))
   {
      spr = db->Get_Spr ();
      setXY0 (spr, ColumnX, bkdy);
      setUV0 (spr, SprU[35], SprV[35]);
      spr->w = SprW[35];
      spr->h = SprH[35];
      spr->clut = GetClut (0, ClutY[SprImage[35]]);
      db->Add_Spr (spr, 13);

      spr = db->Get_Spr ();
      setXY0 (spr, ColumnX, bkdy + 80);
      setUV0 (spr, SprU[35], SprV[35]);
      spr->w = SprW[35];
      spr->h = SprH[35];
      SetSemiTrans (polygon, 0);
      SetShadeTex (polygon, 1);
      spr->clut = GetClut (0, ClutY[SprImage[35]]);
      db->Add_Spr (spr, 13);

      spr = db->Get_Spr ();
      setXY0 (spr, ColumnX, bkdy + 160);
      setUV0 (spr, SprU[35], SprV[35]);
      spr->w = SprW[35];
      spr->h = SprH[35];
      spr->clut = GetClut (0, ClutY[SprImage[35]]);
      db->Add_Spr (spr, 13);
   }

   drmode = db->Get_DrMode ();
   RECT rect = {SprXTP[35], SprYTP[35], 256, 256};
   SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[35], SprYTP[35]), &rect);
   db->Add_DrMode (drmode, 13);

   //----- Draw the back buildings ----
   j = BackX;
   i = 0;
   while (j < 320)
   {
      k = BackPattern[i];

      if ((j + SprW[k]) >= 0)
      {
         spr = db->Get_Spr ();
         setXY0 (spr, j, bkdy);
         setUV0 (spr, SprU[k], SprV[k]);
         spr->w = SprW[k];
         spr->h = SprH[k];
         spr->clut = GetClut (0, ClutY[SprImage[k]]);
         SetSemiTrans (spr, 0);
         SetShadeTex (spr, 1);
         db->Add_Spr (spr, 0);

         drmode = db->Get_DrMode ();
         RECT rect = {SprXTP[k], SprYTP[k], 256, 256};
         SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[k], SprYTP[k]), &rect);
         db->Add_DrMode (drmode, SprLayer[k]);
      }

      j += SprW[k];
      i++;
      if (i == 124)
      {
         i = 0;
         if (j <= 0)
            BackX = j;
      }
   }

   if (!pause)
      BackX -= DeltaX;

   //---- Draw the front buildings ----
   if (CarChaseTimerNear >= 7)
   {
      j = FrontX;
      i = 0;
      while (j < 320)
      {
         k = FrontPattern[i];

         if ((j + SprW[k] * 169 / 96) >= 0)
         {
            polygon = db->Get_Poly ();
            polygon->u0 = polygon->u2 = SprU[k];
            polygon->u1 = polygon->u3 = SprU[k] + SprW[k] - 1;
            polygon->v0 = polygon->v1 = SprV[k];
            polygon->v2 = polygon->v3 = SprV[k] + SprH[k] - 1;
            polygon->tpage = GetTPage (1, 0, SprXTP[k], SprYTP[k]);
            polygon->clut = GetClut (0, ClutY[SprImage[k]]);
            SetSemiTrans (polygon, 0);
            SetShadeTex (polygon, 1);
            setXY4 (polygon, j,bkdy, j + SprW[k] * 169 / 96,bkdy, j,bkdy + 169,
                             j + SprW[k] * 169 / 96,bkdy + 169);
            db->Add_Poly (polygon, 5);
         }

         j += SprW[k] * 169 / 96;
         if (++i > 5)
         {
            i = 0;
            if ((j < 0) && (CarChaseTimerNear < 8))
               FrontX = j;
            if (CarChaseTimerNear > 7)
               j = 320;
         }
      }

      if (!pause)
         FrontX -= DeltaX * 3 / 2;
   }
}

//-------------------------------------
// Draw guns calibration's background
//-------------------------------------
void Background::DrawCalibration (DoubleBuffer *db)
{
   SPRT *spr;
   DR_MODE *drmode;
   POLY_FT4 *polygon;

   spr = db->Get_Spr ();
   setXY0 (spr, 0, 0);
   setUV0 (spr, SprU[0], SprV[0]);
   spr->w = SprW[0];
   spr->h = SprH[0];
   spr->clut = GetClut (0, ClutY[SprImage[0]]);
   SetSemiTrans (spr, 0);
   SetShadeTex (spr, 1);
   db->Add_Spr (spr, 0);

   drmode = db->Get_DrMode ();
   RECT rect = {SprXTP[0], SprYTP[0], 256, 256};
   SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[0], SprYTP[0]), &rect);
   db->Add_DrMode (drmode, 0);

   polygon = db->Get_Poly ();
   polygon->u0 = polygon->u2 = SprU[0];
   polygon->u1 = polygon->u3 = SprU[0] + SprW[0] - 1;
   polygon->v0 = polygon->v1 = SprV[0];
   polygon->v2 = polygon->v3 = SprV[0] + SprH[0] - 1;
   polygon->tpage = GetTPage (1, 0, SprXTP[0], SprYTP[0]);
   polygon->clut = GetClut (0, ClutY[SprImage[0]]);
   SetSemiTrans (polygon, 0);
   SetShadeTex (polygon, 1);
   setXY4 (polygon, 320,0, 160,0, 320,120, 160,120);
   db->Add_Poly (polygon, 0);

   polygon = db->Get_Poly ();
   polygon->u0 = polygon->u2 = SprU[0];
   polygon->u1 = polygon->u3 = SprU[0] + SprW[0] - 1;
   polygon->v0 = polygon->v1 = SprV[0];
   polygon->v2 = polygon->v3 = SprV[0] + SprH[0] - 1;
   polygon->tpage = GetTPage (1, 0, SprXTP[0], SprYTP[0]);
   polygon->clut = GetClut (0, ClutY[SprImage[0]]);
   SetSemiTrans (polygon, 0);
   SetShadeTex (polygon, 1);
   setXY4 (polygon, 0,240, 160,240, 0,120, 160,120);
   db->Add_Poly (polygon, 0);

   polygon = db->Get_Poly ();
   polygon->u0 = polygon->u2 = SprU[0];
   polygon->u1 = polygon->u3 = SprU[0] + SprW[0] - 1;
   polygon->v0 = polygon->v1 = SprV[0];
   polygon->v2 = polygon->v3 = SprV[0] + SprH[0] - 1;
   polygon->tpage = GetTPage (1, 0, SprXTP[0], SprYTP[0]);
   polygon->clut = GetClut (0, ClutY[SprImage[0]]);
   SetSemiTrans (polygon, 0);
   SetShadeTex (polygon, 1);
   setXY4 (polygon, 320,240, 160,240, 320,120, 160,120);
   db->Add_Poly (polygon, 0);
}

//-------------------------------------
// Draw the highway chase background
// (Drug dealers 4)
//-------------------------------------
void Background::DrawHighway (DoubleBuffer *db, int pause)
{
   POLY_FT4 *polygon;
   POLY_G4 *sky;
   SPRT *spr;
   DR_MODE *drmode;
   int i, j, k;
   short Shaker[8] = {0,-2,-4,-2,0,2,4,2};
   u_char BackPattern[6] = {0,1,2,3,4,5};
   u_char FrontPattern[2] = {99,99};
   u_char BackBuilding[56] = {9,10,11,12, 9,10,11,12, 9,10,11,12, 9,10,11,12,
                              13,14,15,16, 9,10,11,12, 9,10,11,12, 9,10,11,12,
                              13,14,15,16, 9,10,11,12, 9,10,11,12, 9,10,11,12,
                              9,10,11,12, 13,14,15,16};
   int bkdy = Shaker[Shaking & 7];

   //--------- Draw the street --------
   for (i = -2; i < 4; i++)
   {
      int actualxh = ((StreetX) + i * 64) + 160;
      int actualxl = ((StreetX * 2) + i * 128) + 160;
      polygon = db->Get_Poly ();
      polygon->u0 = polygon->u2 = SprU[6];
      polygon->u1 = polygon->u3 = SprU[6] + SprW[6] - 1;
      polygon->v0 = polygon->v1 = SprV[6];
      polygon->v2 = polygon->v3 = SprV[6] + SprH[6] - 1;
      polygon->tpage = GetTPage (1, 0, SprXTP[6], SprYTP[6]);
      polygon->clut = GetClut (0, ClutY[SprImage[6]]);
      SetSemiTrans (polygon, 0);
      SetShadeTex (polygon, 1);
      setXY4 (polygon, actualxh - 32,bkdy + 146, actualxh + 32,bkdy + 146,
                       actualxl - 64,bkdy + 240, actualxl + 64,bkdy + 240);
      db->Add_Poly (polygon, 7);
   }

   if (!pause)
   {
      if ((StreetX -= 8) <= -64)
         StreetX += 64;
   }

   //---- Draw the city in the back ---
   j = BackX;
   i = 0;
   while (j < 320)
   {
      k = BackPattern[i];

      if ((j + SprW[k]) >= 0)
      {
         spr = db->Get_Spr ();
         setXY0 (spr, j, bkdy + 130 - SprH[k]);
         setUV0 (spr, SprU[k], SprV[k]);
         spr->w = SprW[k];
         spr->h = SprH[k];
         spr->clut = GetClut (0, ClutY[SprImage[k]]);
         SetSemiTrans (spr, 0);
         SetShadeTex (spr, 1);
         db->Add_Spr (spr, 0);

         drmode = db->Get_DrMode ();
         RECT rect = {SprXTP[k], SprYTP[k], 256, 256};
         SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[k], SprYTP[k]), &rect);
         db->Add_DrMode (drmode, 0);
      }

      j += SprW[k];
      i++;
      if (i == 6)
      {
         i = 0;
         if (j <= 0)
            BackX = j;
      }
   }

   if (!pause)
      BackX -= 1;

   //------- Draw the sky behind ------
   sky = db->Get_Gouraud ();
   setXYWH (sky, 0,bkdy, 107,106);
   setRGB0 (sky, 0,63,81);
   setRGB1 (sky, 0,63,81);
   setRGB2 (sky, 0,63,81);
   setRGB3 (sky, 143,111,0);
   db->Add_Gouraud (sky, 0);

   sky = db->Get_Gouraud ();
   setXYWH (sky, 107,bkdy, 106,106);
   setRGB0 (sky, 0,63,81);
   setRGB1 (sky, 0,63,81);
   setRGB2 (sky, 143,111,0);
   setRGB3 (sky, 143,111,0);
   db->Add_Gouraud (sky, 0);

   sky = db->Get_Gouraud ();
   setXY4 (sky, 320,bkdy, 320,bkdy + 106, 213,bkdy, 213,bkdy + 106);
   setRGB2 (sky, 0,63,81);
   setRGB0 (sky, 0,63,81);
   setRGB3 (sky, 143,111,0);
   setRGB1 (sky, 0,63,81);
   db->Add_Gouraud (sky, 0);
   
   //--- Draw the 1st street barrier --
   j = MiddleX;
   while (j < 320)
   {
      k = 8;

      if ((j + SprW[k]) >= 0)
      {
         spr = db->Get_Spr ();
         setXY0 (spr, j, bkdy + 114);
         setUV0 (spr, SprU[k], SprV[k]);
         spr->w = SprW[k];
         spr->h = SprH[k];
         spr->clut = GetClut (0, ClutY[SprImage[k]]);
         SetSemiTrans (spr, 0);
         SetShadeTex (spr, 1);
         db->Add_Spr (spr, 7);

         drmode = db->Get_DrMode ();
         RECT rect = {SprXTP[k], SprYTP[k], 256, 256};
         SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[k], SprYTP[k]), &rect);
         db->Add_DrMode (drmode, 7);
      }

      j += SprW[k];
      if (j <= 0)
         MiddleX = j;
   }

   if (!pause)
      MiddleX -= 8;

   //----- Draw the back buildings ----
   j = FrontX;
   i = 0;
   while ((j < 320) && (i < 56) && (FrontX > -3500))
   {
      if (FrontX < -1722)
         FrontY = ((-FrontX) - 1722) / 12;

      k = BackBuilding[i];

      if ((j + SprW[k]) >= 0)
      {
         spr = db->Get_Spr ();
         setXY0 (spr, j, bkdy + FrontY);
         setUV0 (spr, SprU[k], SprV[k]);
         spr->w = SprW[k];
         spr->h = SprH[k];
         spr->clut = GetClut (0, ClutY[SprImage[k]]);
         SetSemiTrans (spr, 0);
         SetShadeTex (spr, 1);
         db->Add_Spr (spr, 1);

         drmode = db->Get_DrMode ();
         RECT rect = {SprXTP[k], SprYTP[k], 256, 256};
         SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[k], SprYTP[k]), &rect);
         db->Add_DrMode (drmode, 1);
      }

      j += SprW[k];
      i++;
   }

   if (!pause)
      FrontX -= 8;

   //----- Draw the back barriers -----
   j = BarrierX;
   while (j < -4096)
      j += 4096;
   while (j < -512)
      j += 512;
   i = 0;

   if (CarChaseTimerFar > 0)
   {
      if ((BarrierY < 120) && ((FrameCounter & 7) == 0))
      {
         if (++BarrierY == 120)
            CarChaseTimerFar = 2;
      }
   }
   else if (BarrierX > -1)
      BarrierY = 120;
   else if ((BarrierX > -450) && (BarrierX < 0))
      BarrierY = (BarrierX + 450) / 12 + 90;
   else // if ((BarrierX < -450) && (BarrierX > -2000))
      BarrierY = 90;

   while ((j < 320) && (i < 56))
   {
      k = 7;

      if ((j + SprW[k]) >= 0)
      {
         spr = db->Get_Spr ();
         setXY0 (spr, j,bkdy + BarrierY);
         setUV0 (spr, SprU[k], SprV[k]);
         spr->w = SprW[k];
         spr->h = SprH[k];
         spr->clut = GetClut (0, ClutY[SprImage[k]]);
         SetSemiTrans (spr, 0);
         SetShadeTex (spr, 1);
         db->Add_Spr (spr, 6);

         drmode = db->Get_DrMode ();
         RECT rect = {SprXTP[k], SprYTP[k], 256, 256};
         SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[k], SprYTP[k]), &rect);
         db->Add_DrMode (drmode, 6);
      }

      j += SprW[k];
   }

   if (!pause)
      BarrierX -= 7;
}

//-------------------------------------
// Draw the subway chase (Chinatown 4)
//-------------------------------------
void Background::DrawSubway (DoubleBuffer *db, int pause)
{
   SPRT *spr;
   DR_MODE *drmode;
   int i, j, k;
   short Shaker[8] = {0,-2,-4,-2,0,2,4,2};
   u_char BackPattern[23] = {6,6,6,6,6,7,8,9,6,6,6,6,6,6,6,6,6,6,6,6,7,8,9};
   u_char FrontPattern[43] = {4,4,4,4,4,4,4,3,4,4,4,4,0,4,4,
                              2,4,4,4,4,0,4,4,4,4,4,5,4,4,4,
                              4,4,1,4,4,4,4,3,4,4,4,4,4};
   int bkdy = Shaker[Shaking & 7];

   if ((FrameCounter > 3540) && (!pause))
   {
      BkdX = -61 - csin (BkdAngle) * 50 / 4096;
      if ((BkdAngle += 13) > 4096)
         BkdAngle -= 4096;
      if ((FrameCounter & 128) && ((FrameCounter & 127) > 20))
         BkdX++;
      else if ((~FrameCounter & 128) && ((FrameCounter & 127) > 20))
         BkdX--;
   }
   else
   {
      if ((FrameCounter < 860) && ((FrameCounter % 7) == 0) &&
          (!pause) && (BkdX > -120))
         BkdX--;
      else if ((FrameCounter > 950) && (FrameCounter < 1581) &&
               ((FrameCounter % 6) == 0) && (!pause) && (BkdX < 0))
         BkdX++;
      else if ((FrameCounter > 1680) && (FrameCounter < 2345) &&
               ((FrameCounter % 6) == 0) && (!pause) && (BkdX > -120))
         BkdX--;
      else if ((FrameCounter > 2672) && (FrameCounter < 3375) &&
               ((FrameCounter % 6) == 0) && (!pause) && (BkdX < 0))
         BkdX++;
      else if ((FrameCounter > 3450) && (FrameCounter < 3510) &&
               (!pause) && (BkdX > -120))
         BkdX--;
   }

   //---- Draw the sky in the back ---
   j = BackX;
   i = 0;
   while (j < 320)
   {
      k = BackPattern[i];

      if ((j + SprW[k]) >= 0)
      {
         spr = db->Get_Spr ();
         setXY0 (spr, j, bkdy);
         setUV0 (spr, SprU[k], SprV[k]);
         spr->w = SprW[k];
         spr->h = SprH[k];
         spr->clut = GetClut (0, ClutY[SprImage[k]]);
         SetSemiTrans (spr, 0);
         SetShadeTex (spr, 1);
         db->Add_Spr (spr, 0);

         drmode = db->Get_DrMode ();
         RECT rect = {SprXTP[k], SprYTP[k], 256, 256};
         SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[k], SprYTP[k]), &rect);
         db->Add_DrMode (drmode, 0);
      }

      j += SprW[k];
      i++;
      if (i == 23)
      {
         i = 0;
         if (j <= 0)
            BackX = j;
      }
   }

   if (!pause)
      BackX -= 6;

   //------ Draw the under train ------
   j = FrontX;
   i = 0;
   while ((j < 320) && (i < 43))
   {
      k = FrontPattern[i];

      if ((j + SprW[k]) >= 0)
      {
         spr = db->Get_Spr ();
         setXY0 (spr, j, bkdy + 240 - SprH[k]);
         setUV0 (spr, SprU[k], SprV[k]);
         spr->w = SprW[k];
         spr->h = SprH[k];
         spr->clut = GetClut (0, ClutY[SprImage[k]]);
         SetSemiTrans (spr, 0);
         SetShadeTex (spr, 1);
         db->Add_Spr (spr, 13);

         drmode = db->Get_DrMode ();
         RECT rect = {SprXTP[k], SprYTP[k], 256, 256};
         SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[k], SprYTP[k]), &rect);
         db->Add_DrMode (drmode, 13);
      }

      j += SprW[k];
      i++;
      if (i == 43)
      {
         i = 0;
         if (j <= 0)
            FrontX = j;
      }
   }

   if (!pause)
      FrontX -= 12;

   //------ Draw the train itself -----
   j = BkdX;
   for (i = 10; (i < 24) && (j < 320); i++)
   {
      if (j + SprW[i] >= 0)
      {
         spr = db->Get_Spr ();
         setXY0 (spr, j, bkdy + 38);
         setUV0 (spr, SprU[i], SprV[i]);
         spr->w = SprW[i];
         spr->h = SprH[i];
         spr->clut = GetClut (0, ClutY[SprImage[i]]);
         SetSemiTrans (spr, 0);
         SetShadeTex (spr, 1);
         db->Add_Spr (spr, 11);

         drmode = db->Get_DrMode ();
         RECT rect = {SprXTP[i], SprYTP[i], 256, 256};
         SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[i], SprYTP[i]), &rect);
         db->Add_DrMode (drmode, 11);
      }

      j += SprW[i];
   }
}

//-------------------------------------
// Draw the conveyer belt in the
// chemical plant sabotage 1
//-------------------------------------
void Background::DrawConveyer (DoubleBuffer *db, int pause)
{
   int      i, j;
   short    Shaker[8] = {0,-2,-4,-2,0,2,4,2};
   SPRT     *spr;
   DR_MODE  *drmode;
   int bkdy = Shaker[Shaking & 7];

   j = FrontX;
   for (i = 0; i < 6; i++)
   {
      spr = db->Get_Spr ();
      setXY0 (spr, j, bkdy + 213);
      setUV0 (spr, SprU[26], SprV[26] + 17);
      spr->w = 64;
      spr->h = 13;
      spr->clut = GetClut (0, ClutY[SprImage[26]]);
      SetSemiTrans (spr, 0);
      SetShadeTex (spr, 1);
      db->Add_Spr (spr, 10);

      j += 64;
   }

   drmode = db->Get_DrMode ();
   RECT rect = {SprXTP[26], SprYTP[26], 256, 256};
   SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[26], SprYTP[26]), &rect);
   db->Add_DrMode (drmode, 10);

   if (!pause)
   {
      if ((++FrontX) == 0)
         FrontX = -63;
   }
}

//-------------------------------------
// Draw extra elements for the airport3
// background
//-------------------------------------
void Background::DrawAirport3 (DoubleBuffer *db)
{
   POLY_F4  *plain;
   short    Shaker[8] = {0,-2,-4,-2,0,2,4,2};
   int      bkdy = Shaker[Shaking & 7];

   plain = db->Get_Plain ();
   setXY4 (plain, 0,bkdy, 319,bkdy, 0,bkdy + 139, 319,bkdy + 139);
   setRGB0 (plain, 216,216,216);
   SetSemiTrans (plain, 0);
   db->Add_Plain (plain, 0);
}

//-------------------------------------
// Draw the far background in airport 4
//-------------------------------------
void Background::DrawAirport4 (DoubleBuffer *db, int pause)
{
   int      i, j;
   short    Shaker[8] = {0,-2,-4,-2,0,2,4,2};
   SPRT     *spr;
   DR_MODE  *drmode;
   int      spu[4] = {128,128,128,0};
   int      spv[4] = {0,85,170,156};
   int      bkdy = Shaker[Shaking & 7];

   //-------- Draw the clouds ---------
   j = FrontX;
   for (i = 0; i < 4; i++)
   {
      spr = db->Get_Spr ();
      setXY0 (spr, j, bkdy);
      setUV0 (spr, SprU[66], SprV[66]);
      if ((j + 128) > 319)
         spr->w = 320 - j;
      else
         spr->w = 128;
      if ((j + 128 > 113) && (BkdX < -513))
         spr->h = 156;
      else
         spr->h = 36;
      spr->clut = GetClut (0, ClutY[SprImage[66]]);
      SetSemiTrans (spr, 0);
      SetShadeTex (spr, 1);
      db->Add_Spr (spr, 0);

      j += 128;
   }

   //----- Draw the airport under -----
   j = BackX;
   i = 0;
   while (j < 320)
   {
      if ((j > -128) && ((-BkdX + 128 + j) > 342))
      {
         spr = db->Get_Spr ();
         if ((-BkdX + j + 128) > 887)
         {
            setXY0 (spr, j, bkdy + 156);
            spr->h = 84;
            setUV0 (spr, SprU[66] + spu[i], SprV[66] + spv[i]);
         }
         else
         {
            setXY0 (spr, j, bkdy + 195);
            spr->h = 45;
            setUV0 (spr, SprU[66] + spu[i], SprV[66] + spv[i] + 39);
         }
         if ((j + 128) > 319)
            spr->w = 320 - j;
         else
            spr->w = 128;
         spr->clut = GetClut (0, ClutY[SprImage[66]]);
         SetSemiTrans (spr, 0);
         SetShadeTex (spr, 1);
         db->Add_Spr (spr, 0);
      }

      i = (i + 1) & 3;
      j += 128;
   }

   drmode = db->Get_DrMode ();
   RECT rect = {SprXTP[66], SprYTP[66], 256, 256};
   SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[66], SprYTP[66]), &rect);
   db->Add_DrMode (drmode, 0);

   if (!pause)
   {
      if ((--FrontX) == -128)
         FrontX = 0;

      if ((--BackX) == -512)
         BackX = 0;
   }
}

//-------------------------------------
// Draw the moving part of stage holdup
// level 2
//-------------------------------------
void Background::DrawStage2 (DoubleBuffer *db, int pause)
{
   SPRT *spr;
   DR_MODE *drmode;
   POLY_FT4 *polygon;
   int i;

   // Draw the sky
   for (i = 5; i < 7; i++)
   {
      spr = db->Get_Spr ();
      setXY0 (spr, SprX[i], SprY[i]);
      setUV0 (spr, SprU[i], SprV[i]);
      spr->w = SprW[i];
      spr->h = SprH[i];
      spr->clut = GetClut (0, ClutY[SprImage[i]]);
      db->Add_Spr (spr, SprLayer[i]);

      drmode = db->Get_DrMode ();
      RECT rect = {SprXTP[i], SprYTP[i], 256, 256};
      SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[i], SprYTP[i]), &rect);
      db->Add_DrMode (drmode, SprLayer[i]);
   }

   // Draw the mountains
   spr = db->Get_Spr ();
   setXY0 (spr, SprX[7], BackX / 120);
   setUV0 (spr, SprU[7], SprV[7]);
   spr->w = SprW[7];
   spr->h = SprH[7];
   spr->clut = GetClut (0, ClutY[SprImage[7]]);
   db->Add_Spr (spr, 1);

   drmode = db->Get_DrMode ();
   RECT rect = {SprXTP[7], SprYTP[7], 256, 256};
   SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[7], SprYTP[7]), &rect);
   db->Add_DrMode (drmode, 1);

   spr = db->Get_Spr ();
   setXY0 (spr, SprX[8], BackX / 120 + 70);
   setUV0 (spr, SprU[8], SprV[8]);
   spr->w = SprW[8];
   spr->h = SprH[8];
   spr->clut = GetClut (0, ClutY[SprImage[8]]);
   db->Add_Spr (spr, 1);

   drmode = db->Get_DrMode ();
   RECT rect2 = {SprXTP[8], SprYTP[8], 256, 256};
   SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[8], SprYTP[8]), &rect2);
   db->Add_DrMode (drmode, 1);

   // Draw the ground
   i = FrontX / 3;
   polygon = db->Get_Poly ();
   polygon->u0 = polygon->u2 = SprU[i];
   polygon->u1 = polygon->u3 = SprU[i] + SprW[i] - 1;
   polygon->v0 = polygon->v1 = SprV[i];
   polygon->v2 = polygon->v3 = SprV[i] + SprH[i] - 1;
   polygon->tpage = GetTPage (1, 0, SprXTP[0], SprYTP[0]);
   polygon->clut = GetClut (0, ClutY[SprImage[0]]);
   SetSemiTrans (polygon, 0);
   SetShadeTex (polygon, 1);
   setXY4 (polygon, 0,154, 319,154, 0,239, 319,239);
   db->Add_Poly (polygon, 5);

   //----------------------------------
   if (!pause)
   {
      if ((++FrontX) == 15)             // Alternate between the 5 grounds
         FrontX = 0;

      if ((--BackX) < 600)              // Mountains go up...
         BackX = 600;
   }
}

//-------------------------------------
// Draw the moving part of stage holdup
// level 2
//-------------------------------------
void Background::DrawTrain (DoubleBuffer *db, int pause)
{
   int  PassengerX[24] =   {504,416,328,240,439,311,752, 0,81,81,129,177,225,273,321,369,417,465,513,561,609,657,705,705};
   char PassengerY[24] =   {187,187,187,187, 54, 54, 20,20,20,20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20};
   char PassengerRev[24] = {  1,  1,  0,  0,  0,  0,  0, 1, 1, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0};
   char PassengerSpr[24] = { 14, 15, 15, 14, 13, 12, 10,10,11, 9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 11,  9};

   int  PlankX[9] =   {  0, 22,104,184,264,344,424,168,236};
   char PlankY[9] =   {179,135,135,135,135,135,135,189,189};
   char PlankSpr[9] = { 22, 21, 20, 20, 20, 20, 23, 24, 25};

   int  WoodX[16] =   { 0,64,108,152,168,168,256,280,304,328,388,448,256,362,168,168};
   char WoodY[16] =   {35,39, 39, 39, 39,174, 39, 39, 39, 39, 39, 35,190, 69, 46,110};
   char WoodSpr[16] = {26,27, 27, 28, 36, 35, 29, 29, 29, 30, 31, 26, 33, 34, 32, 37};
   char WoodRev[16] = { 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0};
   char WoodLyr[16] = { 9, 9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  3,  3,  3};

   int  FlatX[6] = {  0,300,236,260,120,408};
   char FlatY[6] = {118, 74,167,128,118, 74};

   int  CowX[18] =   {  0,21,73,125,176,176,256,298,336,388,440,490, 65,122,174,217,354,409};
   char CowY[18] =   {181,36,36, 36, 37,175, 36, 36, 36, 36, 36,181, 89, 52, 47, 47, 52, 89};
   char CowSpr[18] = { 57,44,45, 46, 51, 52, 47, 48, 46, 45, 44, 57, 49, 56, 53, 54, 56, 49};
   char CowRev[18] = {  0, 0, 0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0,  0,  0,  0,  1,  1};
   char CowLyr[18] = {  9, 9, 9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  3,  3,  3,  3,  3,  3};

   int  BankX[24] =   { 0,80,128,184,240,288,320,320,408,466,521,521,586,586,614,662,240,377,320,512,85,245,461,619};
   char BankY[24] =   {24,24, 24, 24, 24, 24, 24,175, 24, 24, 24,164, 24,112, 24, 24,191,191, 63, 62,68, 68, 68, 68};
   char BankSpr[24] = {59,60, 61, 61, 60, 62, 69, 75, 63, 64, 70, 68, 71, 72, 60, 59, 66, 67, 65, 74,73, 73, 73, 73};
   char BankRev[24] = { 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0, 0,  0,  0,  0};
   char BankLyr[24] = { 9, 9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  3,  3, 3,  3,  3,  3};

   int  EngineX[20] =   {  0, 40,174,320,308,346,376,428,480,532,680,736,736,736,840,796,317,345,368,415};
   char EngineY[20] =   {163,103,103,169, 40, 40, 23, 23, 23, 62, 83, 23, 80,143,191, 40, 52, 52, 60, 60};
   char EngineSpr[20] = { 79, 76, 77, 81, 91, 80, 85, 86, 87, 78, 89, 83, 84, 88, 90, 82, 93, 94, 95, 96};
   char EngineLyr[20] = {  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  3,  3,  3,  3};

   int  WheelX[14] = {80,592, 912,1424, 1686,1988, 2198,2507,
                      2710,3019, 3222,3531, 3792,4216};

   SPRT *spr;
   DR_MODE *drmode;
   POLY_FT4 *polygon;
   int i, j, k;
   char TrackPattern[2] = {3,4};
   char CanyonPattern[4] = {5,6,7,8};
   int  WagonX;

   //---------- Draw the sky ----------
   for (i = 0; i < 3; i++)
   {
      polygon = db->Get_Poly ();
      polygon->u0 = polygon->u2 = SprU[i];
      polygon->u1 = polygon->u3 = SprU[i] + SprW[i] - 1;
      polygon->v0 = polygon->v1 = SprV[i];
      polygon->v2 = polygon->v3 = SprV[i] + SprH[i] - 1;
      polygon->tpage = GetTPage (1, 0, SprXTP[i], SprYTP[i]);
      polygon->clut = GetClut (0, ClutY[SprImage[i]]);
      SetSemiTrans (polygon, 0);
      SetShadeTex (polygon, 1);
      setXY4 (polygon, SprX[i],0, SprX[i] + SprW[i],0,
                       SprX[i],100, SprX[i] + SprW[i],100);
      db->Add_Poly (polygon, 0);
   }

   //--------- Draw the track ---------
   j = FrontX;
   i = 0;
   while (j < 320)
   {
      k = TrackPattern[i];

      if ((j + SprW[k]) >= 0)
      {
         spr = db->Get_Spr ();
         setXY0 (spr, j, 221);
         setUV0 (spr, SprU[k], SprV[k]);
         spr->w = SprW[k];
         spr->h = SprH[k];
         spr->clut = GetClut (0, ClutY[SprImage[k]]);
         SetSemiTrans (spr, 0);
         SetShadeTex (spr, 1);
         db->Add_Spr (spr, 0);

         drmode = db->Get_DrMode ();
         RECT rect = {SprXTP[k], SprYTP[k], 256, 256};
         SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[k], SprYTP[k]), &rect);
         db->Add_DrMode (drmode, 0);
      }

      j += SprW[k];
      if (++i > 1)
      {
         i = 0;
         if (j < 0)
            FrontX = j;
      }
   }

   //-------- Draw the canyon ---------
   j = BackX;
   i = 0;
   while (j < 320)
   {
      k = CanyonPattern[i];

      if ((j + SprW[k]) >= 0)
      {
         spr = db->Get_Spr ();
         setXY0 (spr, j, 26);
         setUV0 (spr, SprU[k], SprV[k]);
         spr->w = SprW[k];
         spr->h = SprH[k];
         spr->clut = GetClut (0, ClutY[SprImage[k]]);
         SetSemiTrans (spr, 0);
         SetShadeTex (spr, 1);
         db->Add_Spr (spr, 1);

         drmode = db->Get_DrMode ();
         RECT rect = {SprXTP[k], SprYTP[k], 256, 256};
         SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[k], SprYTP[k]), &rect);
         db->Add_DrMode (drmode, 1);
      }

      j += SprW[k];
      if (++i > 3)
      {
         i = 0;
         if (j < 0)
            BackX = j;
      }
   }

   //---- draw the passenger wagons ---
   for (j = 0; j < 2; j++)
   {
      WagonX = BkdX + 832 * j;
      for (i = 0; i < 24; i++)
      {
         k = PassengerSpr[i];
         if (!(((PassengerX[i] + WagonX) > 319) ||
             ((PassengerX[i] + SprW[k] + 1 + WagonX) < 0)))
         {
            if (PassengerRev[i])
            {
               polygon = db->Get_Poly ();
               polygon->u0 = polygon->u2 = SprU[k];
               polygon->u1 = polygon->u3 = SprU[k] + SprW[k] - 1;
               polygon->v0 = polygon->v1 = SprV[k];
               polygon->v2 = polygon->v3 = SprV[k] + SprH[k] - 1;
               polygon->tpage = GetTPage (1, 0, SprXTP[k], SprYTP[k]);
               polygon->clut = GetClut (0, ClutY[SprImage[k]]);
               SetSemiTrans (polygon, 0);
               SetShadeTex (polygon, 1);
               setXY4 (polygon, PassengerX[i] + SprW[k] + 1 + WagonX,PassengerY[i],
                                PassengerX[i] + WagonX,PassengerY[i],
                                PassengerX[i] + SprW[k] + 1 + WagonX,PassengerY[i] + SprH[k],
                                PassengerX[i] + WagonX, PassengerY[i] + SprH[k]);
               db->Add_Poly (polygon, 9);
            }
            else
            {
               spr = db->Get_Spr ();
               setXY0 (spr, PassengerX[i] + WagonX, PassengerY[i]);
               setUV0 (spr, SprU[k], SprV[k]);
               spr->w = SprW[k];
               spr->h = SprH[k];
               spr->clut = GetClut (0, ClutY[SprImage[k]]);
               SetSemiTrans (spr, 0);
               SetShadeTex (spr, 1);
               db->Add_Spr (spr, 9);
            }
         }
      }
   }
   k = PassengerSpr[0];
   drmode = db->Get_DrMode ();
   RECT rect = {SprXTP[k], SprYTP[k], 256, 256};
   SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[k], SprYTP[k]), &rect);
   db->Add_DrMode (drmode, 9);

   for (j = 0; j < 2; j++)              // Draw the inside windows
   {
      WagonX = BkdX + 832 * j;
      for (i = 0; i < 14; i++)
      {
         if (!(((WagonX + i * 48 + 86) > 320) ||
             ((WagonX + i * 48 + 113) < 0)))
         {
            spr = db->Get_Spr ();
            setXY0 (spr, i * 48 + 86 + WagonX, 76);
            setUV0 (spr, SprU[92], SprV[92]);
            spr->w = SprW[92];
            spr->h = SprH[92];
            spr->clut = GetClut (0, ClutY[SprImage[92]]);
            SetSemiTrans (spr, 0);
            SetShadeTex (spr, 1);
            db->Add_Spr (spr, 3);
         }
      }
   }
   drmode = db->Get_DrMode ();
   RECT rectq = {SprXTP[92], SprYTP[92], 256, 256};
   SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[92], SprYTP[92]), &rectq);
   db->Add_DrMode (drmode, 3);

   //--------- Draw the plank ---------
   WagonX = BkdX + 1664;
   for (i = 0; i < 9; i++)
   {
      k = PlankSpr[i];
      if (!(((PlankX[i] + WagonX) > 319) ||
          ((PlankX[i] + SprW[k] + 1 + WagonX) < 0)))
      {
         spr = db->Get_Spr ();
         setXY0 (spr, PlankX[i] + WagonX, PlankY[i]);
         setUV0 (spr, SprU[k], SprV[k]);
         spr->w = SprW[k];
         spr->h = SprH[k];
         spr->clut = GetClut (0, ClutY[SprImage[k]]);
         SetSemiTrans (spr, 0);
         SetShadeTex (spr, 1);
         db->Add_Spr (spr, 9);
      }
   }
   k = PlankSpr[0];
   drmode = db->Get_DrMode ();
   RECT rectw = {SprXTP[k], SprYTP[k], 256, 256};
   SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[k], SprYTP[k]), &rectw);
   db->Add_DrMode (drmode, 9);

   //------ Draw the wood wagon -------
   WagonX = BkdX + 2176;
   for (i = 0; i < 16; i++)
   {
      k = WoodSpr[i];
      if (!(((WoodX[i] + WagonX) > 319) ||
          ((WoodX[i] + SprW[k] + 1 + WagonX) < 0)))
      {
         if (WoodRev[i])
         {
            polygon = db->Get_Poly ();
            polygon->u0 = polygon->u2 = SprU[k];
            polygon->u1 = polygon->u3 = SprU[k] + SprW[k] - 1;
            polygon->v0 = polygon->v1 = SprV[k];
            polygon->v2 = polygon->v3 = SprV[k] + SprH[k] - 1;
            polygon->tpage = GetTPage (1, 0, SprXTP[k], SprYTP[k]);
            polygon->clut = GetClut (0, ClutY[SprImage[k]]);
            SetSemiTrans (polygon, 0);
            SetShadeTex (polygon, 1);
            setXY4 (polygon, WoodX[i] + SprW[k] + 1 + WagonX,WoodY[i],
                             WoodX[i] + WagonX,WoodY[i],
                             WoodX[i] + SprW[k] + 1 + WagonX,WoodY[i] + SprH[k],
                             WoodX[i] + WagonX, WoodY[i] + SprH[k]);
            db->Add_Poly (polygon, WoodLyr[i]);
         }
         else
         {
            spr = db->Get_Spr ();
            setXY0 (spr, WoodX[i] + WagonX, WoodY[i]);
            setUV0 (spr, SprU[k], SprV[k]);
            spr->w = SprW[k];
            spr->h = SprH[k];
            spr->clut = GetClut (0, ClutY[SprImage[k]]);
            SetSemiTrans (spr, 0);
            SetShadeTex (spr, 1);
            db->Add_Spr (spr, WoodLyr[i]);

            drmode = db->Get_DrMode ();
            RECT rectl = {SprXTP[k], SprYTP[k], 256, 256};
            SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[k], SprYTP[k]), &rectl);
            db->Add_DrMode (drmode, WoodLyr[i]);
         }
      }
   }

   //------ Draw the flat wagon -------
   WagonX = BkdX + 2688;
   for (i = 0; i < 6; i++)
   {
      k = 38 + i;
      if (!(((FlatX[i] + WagonX) > 319) ||
          ((FlatX[i] + (SprW[k] << 1) + 1 + WagonX) < 0)))
      {
         polygon = db->Get_Poly ();
         polygon->u0 = polygon->u2 = SprU[k];
         polygon->u1 = polygon->u3 = SprU[k] + SprW[k] - 1;
         polygon->v0 = polygon->v1 = SprV[k];
         polygon->v2 = polygon->v3 = SprV[k] + SprH[k] - 1;
         polygon->tpage = GetTPage (1, 0, SprXTP[k], SprYTP[k]);
         polygon->clut = GetClut (0, ClutY[SprImage[k]]);
         SetSemiTrans (polygon, 0);
         SetShadeTex (polygon, 1);
         setXY4 (polygon, FlatX[i] + WagonX,FlatY[i],
                          FlatX[i] + (SprW[k] << 1) + 1 + WagonX,FlatY[i],
                          FlatX[i] + WagonX, FlatY[i] + SprH[k],
                          FlatX[i] + (SprW[k] << 1) + 1 + WagonX,FlatY[i] + SprH[k]);
         db->Add_Poly (polygon, 9);
      }
   }

   //------- Draw the cow wagon -------
   WagonX = BkdX + 3200;
   for (i = 0; i < 18; i++)
   {
      k = CowSpr[i];
      if (!(((CowX[i] + WagonX) > 319) ||
          ((CowX[i] + SprW[k] + 1 + WagonX) < 0)))
      {
         if (CowRev[i])
         {
            polygon = db->Get_Poly ();
            polygon->u0 = polygon->u2 = SprU[k];
            polygon->u1 = polygon->u3 = SprU[k] + SprW[k] - 1;
            polygon->v0 = polygon->v1 = SprV[k];
            polygon->v2 = polygon->v3 = SprV[k] + SprH[k] - 1;
            polygon->tpage = GetTPage (1, 0, SprXTP[k], SprYTP[k]);
            polygon->clut = GetClut (0, ClutY[SprImage[k]]);
            SetSemiTrans (polygon, 0);
            SetShadeTex (polygon, 1);
            setXY4 (polygon, CowX[i] + SprW[k] + 1 + WagonX,CowY[i],
                             CowX[i] + WagonX,CowY[i],
                             CowX[i] + SprW[k] + 1 + WagonX,CowY[i] + SprH[k],
                             CowX[i] + WagonX, CowY[i] + SprH[k]);
            db->Add_Poly (polygon, CowLyr[i]);
         }
         else
         {
            spr = db->Get_Spr ();
            setXY0 (spr, CowX[i] + WagonX, CowY[i]);
            setUV0 (spr, SprU[k], SprV[k]);
            spr->w = SprW[k];
            spr->h = SprH[k];
            spr->clut = GetClut (0, ClutY[SprImage[k]]);
            SetSemiTrans (spr, 0);
            SetShadeTex (spr, 1);
            db->Add_Spr (spr, CowLyr[i]);

            drmode = db->Get_DrMode ();
            RECT rectt = {SprXTP[k], SprYTP[k], 256, 256};
            SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[k], SprYTP[k]), &rectt);
            db->Add_DrMode (drmode, CowLyr[i]);
         }
      }
   }

   //------ Draw the bank wagon -------
   WagonX = BkdX + 3712;
   for (i = 0; i < 24; i++)
   {
      k = BankSpr[i];
      if (!(((BankX[i] + WagonX) > 319) ||
          ((BankX[i] + SprW[k] + 1 + WagonX) < 0)))
      {
         if (BankRev[i])
         {
            polygon = db->Get_Poly ();
            polygon->u0 = polygon->u2 = SprU[k];
            polygon->u1 = polygon->u3 = SprU[k] + SprW[k] - 1;
            polygon->v0 = polygon->v1 = SprV[k];
            polygon->v2 = polygon->v3 = SprV[k] + SprH[k] - 1;
            polygon->tpage = GetTPage (1, 0, SprXTP[k], SprYTP[k]);
            polygon->clut = GetClut (0, ClutY[SprImage[k]]);
            SetSemiTrans (polygon, 0);
            SetShadeTex (polygon, 1);
            setXY4 (polygon, BankX[i] + SprW[k] + 1 + WagonX,BankY[i],
                             BankX[i] + WagonX,BankY[i],
                             BankX[i] + SprW[k] + 1 + WagonX,BankY[i] + SprH[k],
                             BankX[i] + WagonX, BankY[i] + SprH[k]);
            db->Add_Poly (polygon, BankLyr[i]);
         }
         else
         {
            spr = db->Get_Spr ();
            setXY0 (spr, BankX[i] + WagonX, BankY[i]);
            setUV0 (spr, SprU[k], SprV[k]);
            spr->w = SprW[k];
            spr->h = SprH[k];
            spr->clut = GetClut (0, ClutY[SprImage[k]]);
            SetSemiTrans (spr, 0);
            SetShadeTex (spr, 1);
            db->Add_Spr (spr, BankLyr[i]);

            drmode = db->Get_DrMode ();
            RECT rectt = {SprXTP[k], SprYTP[k], 256, 256};
            SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[k], SprYTP[k]), &rectt);
            db->Add_DrMode (drmode, BankLyr[i]);
         }
      }
   }

   //-------- Draw the engine ---------
   WagonX = BkdX + 4455;
   for (i = 0; i < 20; i++)
   {
      k = EngineSpr[i];
      if (!(((EngineX[i] + WagonX) > 319) ||
          ((EngineX[i] + SprW[k] + 1 + WagonX) < 0)))
      {
         spr = db->Get_Spr ();
         setXY0 (spr, EngineX[i] + WagonX, EngineY[i]);
         setUV0 (spr, SprU[k], SprV[k]);
         spr->w = SprW[k];
         spr->h = SprH[k];
         spr->clut = GetClut (0, ClutY[SprImage[k]]);
         SetSemiTrans (spr, 0);
         SetShadeTex (spr, 1);
         db->Add_Spr (spr, EngineLyr[i]);

         drmode = db->Get_DrMode ();
         RECT rectw = {SprXTP[k], SprYTP[k], 256, 256};
         SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[k], SprYTP[k]), &rectw);
         db->Add_DrMode (drmode, EngineLyr[i]);
      }
   }

   //------ Draw all the wheels -------
   for (i = 0; i < 14; i++)
   {
      if (!(((WheelX[i] + BkdX) > 319) || ((WheelX[i] + 160 + BkdX) < 0)))
      {
         for (j = 0; j < 2; j++)
         {
            k = 16 + ((FrameCounter & 4) >> 1) + j;
            spr = db->Get_Spr ();
            setXY0 (spr, WheelX[i] + j * 80 + BkdX, 187);
            setUV0 (spr, SprU[k], SprV[k]);
            spr->w = SprW[k];
            spr->h = SprH[k];
            spr->clut = GetClut (0, ClutY[SprImage[k]]);
            SetSemiTrans (spr, 0);
            SetShadeTex (spr, 1);
            db->Add_Spr (spr, 2);
         }
      }
   }
   drmode = db->Get_DrMode ();
   RECT rectk = {SprXTP[16], SprYTP[16], 256, 256};
   SetDrawMode (drmode, 0, 0, GetTPage (1, 0, SprXTP[16], SprYTP[16]), &rectk);
   db->Add_DrMode (drmode, 2);

   //----------------------------------
   if (!pause)
   {
      if ((FrontX -= 15) < -320)        // Move the track
         FrontX += 320;
      if ((BackX -= 4) < -320)          // Move the canyon
         BackX += 320;

      if (((FrameCounter > 599) && (FrameCounter < 9850)) || // Move the train
         ((FrameCounter > 10149) && (FrameCounter < 11000)))
         if (FrameCounter & 1)
            BkdX--;
   }

   if ((FrameCounter == 4000) && (VramMemHandle[9] != -1))
   {                    // Free passenger wagon
      FreeVram (VramMemHandle[9]);
      VramMemHandle[9] = -1;
   }
   else if ((FrameCounter == 6000) && (VramMemHandle[8] != -1))
   {                    // Free wood wagon
      FreeVram (VramMemHandle[8]);
      VramMemHandle[8] = -1;
   }
   else if ((FrameCounter == 7000) && (VramMemHandle[7] != -1))
   {                    // Free flat wagon
      FreeVram (VramMemHandle[7]);
      VramMemHandle[7] = -1;
   }                    
   else if ((FrameCounter == 8025) && (VramMemHandle[4] != -1))
   {                    
      FreeVram (VramMemHandle[4]);
      VramMemHandle[4] = -1;
   }
   else if ((FrameCounter == 9525) && (VramMemHandle[3] != -1))
   {                    // Free bank wagon
      FreeVram (VramMemHandle[3]);
      VramMemHandle[3] = -1;
   }
}
