//---------------------------------------------------------------------------
// Lethal Enforcers I & II - PlayStation conversion
// January 16th 1997, Geoffroy Audy
//---------------------------------------------------------------------------

#include "include\compile.h"            //

#define MEMSTART  0x8009A000            //
#define NULL 0                          //

int debug = 0;                          // Debug mode (1) or not (0)...

char PleaseWait[2] = {0,0};             //

char NarratorVoice = 0;                 // Sound things...
int commonvab;                          //
int bkdvab;                             //

int Difficulty = 4;                     // Game options...
int SfxVol = 127;                       //
int MusicVol = 64;                      //
int GameMode = 1;                       //
int BloodyMode = 0;                     //
int DemoMode = 0;                       //
int DynamicDifficulty;                  //
int LE1orLE2 = 1;                       //

unsigned short XGunMiddle = 780;        //
unsigned short YGunMiddle = 120;        //

int LevelSelected = -1;                 // Level # (bank, chinatown, etc...)
int LastScript, ActualScript = -1;      //
char GamePause = 0;                     //
char GamePausedBy = 0;                  //

#include <sys\types.h>
#include <libetc.h>
#include <libgte.h>
#include <libgpu.h>
#include <stdlib.h>
#include <rand.h>
#include <libcd.h>
#include <memory.h>
#include <audiolib.h>
#include <audio_xa.h>
#include <audio_mm.h>
#include <audio_cd.h>

int    ButtonSelection[2][3] = {{6,1,4},{6,1,4}};
int    ButtonCode[8] = {PADRleft,PADRdown,PADRright,PADRup,PADL1,PADL2,PADR1,PADR2};
u_long MemoryP = MEMSTART;                      // Free memory pointer
int    Flash[2] = {0, 0};                       //
u_long FrameCounter;                            //
char   CannotSelect[6] = {0,0,0,0,0,0};         //

#ifdef _AUDIOLIB_H
   FILE_ID   CDXACue;                      // For Frank's sound library
   FILE_ID   CommonCue;                    //
   FILE_ID   LevelCue;                     //
   SOUND_ID  CDXAId;                       //
#endif
    
void  Intrus (...);             //////////
int   vcnt = 0;                 //////////
int   IntrusGunX[2][3] = {{1,2,3},{1,2,3}};
int   IntrusGunY[2][3] = {{1,2,3},{1,2,3}};
int   IntrusReload[2] = {0,0};  ////////// Wait 3 VSync () before considering
int   IntrusIndex[2] = {0,0};   //////////  the gun outside of the screen...
int   Gun_X[2] = {0,0}, Gun_Y[2] = {0,0};

//-------------------------------------
// Patch!!! Includes all the hard coded
// stuff.
//-------------------------------------
int     PassFallen = 0;
int     HelicoScale = 0;
int     NightVision = 0;
int     NightVisionCnt = 0;
int     MissileLaunch;
int     MisLnchTime[8] = {540,520,500,480,460,440,420,400};
int     WhichClut = 0;
char    BossAirportDown = 0;
int     ExtraGuyNbr = 86;
char    BossAirportDead = 0;
char    AirportEndCnt = 0;
char    BossChemicalDead = 0;
char    CarChaseTimerFar = 0;
char    CarChaseTimerNear = 0;
char    CarKilled[7] = {0,0,0,0,0,0,0};
u_short CarTimer[7] = {0,0,0,0,0,0,0};
char    MetalBoxUp = 0;
short   SmallFireX = 160;
short   SmallFireY = 120;
short   YouLose = 0;
short   TimeToShoot[6] = {-1,-1,-1,-1,-1,-1};
char    BarrelUp;
char    NextBarrel;
char    BossStageCoachDead;

//-------------------------------------
#include "include\lethal1.h"            // To play Lethal 1's CDXAs
//#include "include\lethal2.h"            // To play Lethal 2's CDXAs

#include "include\db.h"                 // Double buffer class
#include "include\readfile.h"           // File management module
#include "include\alocvram.h"           // VRAM allocation functions...
#include "include\fonts.h"              // Fonts class
#include "include\sound.h"              // Sound system class
#include "include\bkgnd.h"              // Background class
#include "include\gun.h"                // Guns functions
#include "include\characte.h"           // Character class
#include "include\links.h"              // Links and attaches for characters
#include "include\explosio.h"           // Explosions shit
#include "include\foregrnd.h"           // Foreground drawing functions
#include "include\score.h"              // Accuracy, victims, etc...
#include "include\miscella.h"           // Miscellaneous functions...
#include "include\demo.h"               // For the demo mode
#include "include\scrnsht.h"            // Screen shot shit!!!
#include "include\controll.h"           // Controllers (gun & padd) functions

PLAYER *Playa[2];

#include "include\options.h"            // Option screen and gun calibration
#include "include\hallfame.h"           // Hall of fame stuff
#include "include\intro.h"              // Intro functions
#include "include\script.h"             // Scripting language functions
#include "include\innocent.h"           // Innocent victims shit
#include "include\movie.h"              // Movies functions
#include "include\blood.h"              // For the bloody mode
#include "include\qualify.h"            //
#include "include\maintitl.h"           // Main title stuff.
#include "soundfx\le1qcom\psxcomon.h"   //

void SetDumpMessage (DoubleBuffer *db);

//-------------------------------------
// Main procedure
//-------------------------------------
long main (void)
{
   u_long TopMemory;                    //
   int BkdX = 0, BkdY = 0;              // Coordinate of the background
   int trigger = 0;                     // If the gun trigger is pressed
   int i, j, k, meu;                    // Multi-bullshit variable
   PLAYER *player;                      // Ba be bi bo bu.
   static DoubleBuffer dbuff;           //
   static Character *Chars[122];        //
   static Foreground frgnd = {4,0,0};   //
   static Background bkgnd[2];          //
   int NbrChars;                        //
   int Sfx;                             //
   int Vab;                             //
   shootpnt *shot;                      //
   int Buttons;                         //
   point Popo;                          // Multi-purpose point
   char Power;                          //
   char GunPower[7] = {1,1,3,4,1,2,1};  //
   char Results = 0, EndRound = 0;      //
   signed char PauseChoice;             //
   int posi;                            //
   int voll, volr;                      // Sound fx volume left and right
   int shower = 255;                    //
   int actualvol;                       //
   int zut;                             //
   int ShootingTime;                    //
   int ShootingLimit;                   //
   u_char NbrScripts[2][6] = {{1,3,4,4,4,3},{5,1,7,1,5}};
   u_char FirstScript[2][6] = {{0,2,5,9,13,17},{0,6,7,14,15}};
   u_char DemoScript[2][6] = {{14,5,6,9,4,16},{0,0,0,0,0,0}};
   u_char NextDemo = 0;                 //
   PLAYER DemoPlayer;                   //
   char *ScriptName[2][21] = {{"\\SCRIPT\\SHOOT.SCP", "\\SCRIPT\\SHOOT.SCP",
                           "\\SCRIPT\\BANK1.SCP", "\\SCRIPT\\BANK2.SCP",
                           "\\SCRIPT\\BANK3.SCP", "\\SCRIPT\\CHINA1.SCP",
                           "\\SCRIPT\\CHINA2.SCP", "\\SCRIPT\\CHINA3.SCP",
                           "\\SCRIPT\\CHINA4.SCP", "\\SCRIPT\\AIRPORT1.SCP",
                           "\\SCRIPT\\AIRPORT2.SCP", "\\SCRIPT\\AIRPORT3.SCP",
                           "\\SCRIPT\\AIRPORT4.SCP", "\\SCRIPT\\DRUG1.SCP",
                           "\\SCRIPT\\DRUG2.SCP", "\\SCRIPT\\DRUG3.SCP",
                           "\\SCRIPT\\DRUG4.SCP", "\\SCRIPT\\CHEMICL1.SCP",
                           "\\SCRIPT\\CHEMICL2.SCP", "\\SCRIPT\\CHEMICL3.SCP",
                           ""}, {"\\SCRIPT\\LE2\\BANK1.SCP", "\\SCRIPT\\LE2\\BANK2.SCP",
                           "\\SCRIPT\\LE2\\BANK3.SCP", "\\SCRIPT\\LE2\\BANK4.SCP",
                           "\\SCRIPT\\LE2\\BANK5.SCP", "\\SCRIPT\\LE2\\STAGE1.SCP",
                           "\\SCRIPT\\LE2\\STAGE2.SCP", "\\SCRIPT\\LE2\\SALOON1.SCP",
                           "\\SCRIPT\\LE2\\SALOON2.SCP", "\\SCRIPT\\LE2\\SALOON3.SCP",
                           "\\SCRIPT\\LE2\\SALOON4.SCP", "\\SCRIPT\\LE2\\SALOON5.SCP",
                           "\\SCRIPT\\LE2\\SALOON6.SCP", "\\SCRIPT\\LE2\\SALOON7.SCP",
                           "\\SCRIPT\\LE2\\TRAIN.SCP", "\\SCRIPT\\LE2\\MINE1.SCP",
                           "\\SCRIPT\\LE2\\MINE2.SCP", "\\SCRIPT\\LE2\\MINE3.SCP",
                          "\\SCRIPT\\LE2\\MINE4.SCP", "\\SCRIPT\\LE2\\MINE5.SCP",
                           "\\SCRIPT\\LE2\\MINE6.SCP"}};
   char ScriptBKDType[2][21] = {{0,0,0,0,1,0,0,0,2,0,0,7,3,0,0,0,4,6,0,8},
                                {0,0,0,0,0,0,9,0,0,0,0,0,0,0,10,0,0,0,0,0,0}};
   char *MovieName[6] = {"", "\\MOVIES\\BANK.STR;1",
                         "\\MOVIES\\CHINATWN.STR;1", "\\MOVIES\\HIJACK.STR;1",
                         "\\MOVIES\\DRUGDEAL.STR;1", "\\MOVIES\\CHEMICAL.STR;1"};

   SetDumpMessage (&dbuff);

   dbuff.ClearDrawArea (0,0,0);         // Turn the screen to black
   dbuff.Swap (0);                      //
   dbuff.Swap (0);                      //

   #ifdef TARGETCD
      ResetCallback ();                 // Cd initialisation
      CdInit ();                        //

      #ifdef PLAY_CDXAS                 //
         MemInit ((void *)MemoryP, 65536);
         MemoryP += 65536;              //
         FileSystemInit ();             //
         AudioInit ();                  //
      #endif
   #endif

   //----------------------------------
   MemoryP = (SprCacheInit(MemoryP) + 3) & 0xfffffffc;
   InitFileSystem (&MemoryP);           //
   InitAllocVram ();                    //
   InitPrint ();                        //
   SetFont (LE1orLE2 * 2, MemoryP);     //
   SetFontDB (&dbuff);                  //
   Init_Foreground ();                  //
   SoundInit ();                        //

   Init_Player (&frgnd.Plr1);
   frgnd.Plr1.PlayerNbr = 0;
   Init_Player (&frgnd.Plr2);
   frgnd.Plr2.PlayerNbr = 1;
   Playa[0] = &frgnd.Plr1;
   Playa[1] = &frgnd.Plr2;

   Init_Gun_Library ();

//   VSyncCallback (Intrus);

   #ifdef TARGETCD
      #ifdef PLAY_MOVIES
         PlayMovie ("\\MOVIES\\KONAMI.STR;1", 1, 122, MemoryP, &dbuff, 1);
         PlayMovie ("\\MOVIES\\LETHAL.STR;1", 1, 122, MemoryP, &dbuff, 1);
      #endif
   #endif

   LE1orLE2 = MainTitle (&dbuff, &frgnd, MemoryP);
   SetFont (LE1orLE2 * 2, MemoryP);
   Init_Foreground ();

   #ifdef TARGETCD
      #ifdef PLAY_CDXAS
         if (LE1orLE2)
            CDXACue = AudioLoadCueListFile ((u_char *)"\\CDXA\\LETHAL2.BIN;1");
         else
            CDXACue = AudioLoadCueListFile ((u_char *)"\\CDXA\\LETHAL1.BIN;1");

         // Wait for the end of BIN file loading
         while (AudioWaveTableLoadStatus () == 0);

         if (AudioWaveTableLoadStatus () == -1)
         {
            FntPrint ("Unable to load music information.\n");
            dbuff.Swap (1);
            dbuff.Swap (1);
            while (1);
         }
      #endif
   #endif

   // Load the common sound fx permanently.
   if (LE1orLE2)
      commonvab = LoadSFX ("\\SOUNDFX\\LE2\\COMMON.VAB", &MemoryP);
   else
      commonvab = LoadSFX ("\\SOUNDFX\\COMMON.VAB", &MemoryP);
   LoadInnocent (&MemoryP);
   LoadExplosions (&MemoryP);
   LoadBlood (&MemoryP);
   TopMemory = MemoryP;

   // Lock the permanent sprites into place
   SprCacheSetFirst ();
   
   while (1)
   {
      MemoryP = TopMemory;
      SprCacheReset();
      
      FrameCounter = 0;                 // Initialization for every level...
      Results = 0;                      //
      EndRound = 0;                     //
      InitBulletHoles ();               //
      InitFiring ();                    //
      Buttons = 0;                      //
      GamePause = 0;                    //

      //-----------------------------------
      if (Intro (MemoryP, &dbuff, &frgnd, commonvab))
      {
         DemoMode = 1;
         ActualScript = DemoScript[LE1orLE2][NextDemo];
         if (++NextDemo >= 6)
            NextDemo = 0;
         LastScript = ActualScript + 1;
      }
      else
      {
         frgnd.Plr1.Shots = 0;
         frgnd.Plr1.Hits = 0;
         frgnd.Plr2.Shots = 0;
         frgnd.Plr2.Hits = 0;

         if (GameMode)
         {
            if ((LevelSelected != -1) && (LE1orLE2 == 0))
            {
               CannotSelect[0] = 1;             // Put an X on the selected
               CannotSelect[LevelSelected] = 1; // level and shooting range
               if ((CannotSelect[0] == 1) && (CannotSelect[1] == 1) &&
                   (CannotSelect[2] == 1) && (CannotSelect[3] == 1) &&
                   (CannotSelect[4] == 1) && (CannotSelect[5] == 1))
                  for (i = 0; i < 6; i++)
                     CannotSelect[i] = 0;
            }
            LevelSelected = Select_Screen (MemoryP, &frgnd, &dbuff, commonvab);
         }
         else
            LevelSelected = 1;
         if ((LevelSelected) && (LE1orLE2 == 0)) // Play movie if necessary...
         {
            #ifdef TARGETCD
               #ifdef PLAY_MOVIES
                  PlayMovie (MovieName[LevelSelected], 1, 122, MemoryP, &dbuff, 1);
               #endif
            #endif
         }
         else if (LE1orLE2 == 0)
            PlayShootingRangeIntro (MemoryP, &dbuff, &frgnd);
         ActualScript = FirstScript[LE1orLE2][LevelSelected];
         LastScript = ActualScript + NbrScripts[LE1orLE2][LevelSelected];
      }

      //-- Execute all scripts needed -
      while ((ActualScript < LastScript) && ((frgnd.Plr1.Lifepnt != 0) ||
             (frgnd.Plr2.Lifepnt != 0) || (DemoMode)))
      {
         MemoryP = TopMemory;
         SprCacheReset();
         
         FrameCounter = 0;              // Initialization for every level...
         Results = 0;                   //
         EndRound = 0;                  //
         DynamicDifficulty = 0;         //
         InitBulletHoles ();            //
         InitFiring ();                 //
         Buttons = 0;                   //
         GamePause = 0;                 //
         PassFallen = 0;                //
         HelicoScale = 0;               //
         NightVision = 0;               //
         MissileLaunch = 400;           //
         BossAirportDown = 0;           //
         BossChemicalDead = 0;          //
         ExtraGuyNbr = 86;              //
         BossAirportDead = 0;           //
         CarChaseTimerFar = 0;          //
         CarChaseTimerNear = 0;         //
         MetalBoxUp = 0;                //
         YouLose = 0;                   //
         BarrelUp = 0;                  //
         NextBarrel = 0;                //
         BossStageCoachDead = 0;        //
         for (i = 0; i < 7; i++)        //
         {                              //
            CarKilled[i] = 0;           //
            CarTimer[i] = 0;            //
         }                              //
         Init_Links ();                 //
         Init_Attaches ();              //

         if ((LE1orLE2 == 0) && (LevelSelected == 0))   // Load the percentage
         {                                              // sprites if shooting
            LoadPercent (&MemoryP);                     // range
            SetPercent (100);                           //
         }                                              //

         LoadScript (ScriptName[LE1orLE2][ActualScript], &MemoryP);
         NbrChars = ExecScriptStart (&bkgnd[0], Chars, &MemoryP, &bkdvab, &dbuff);

         bkgnd[0].SetBKDType (ScriptBKDType[LE1orLE2][ActualScript], &MemoryP);
         ActualScript++;

         // If Drug dealer's boat level (level2), attach explosions to barrels
         if (ActualScript == 15)
         {
            AddAttach (Chars[26], Chars[23], -25,-25);
            AddAttach (Chars[27], Chars[23], -25,-25);
            AddAttach (Chars[28], Chars[23], 0,-25);
            AddAttach (Chars[29], Chars[23], 0,-25);
            AddAttach (Chars[30], Chars[23], 25,-25);
            AddAttach (Chars[31], Chars[23], 25,-25);
         }

         actualvol = MusicVol;
         InitDemoMode ();
         InitBlood ();
         ClearEnemyLife ();

         if ((LE1orLE2 == 0) && (LevelSelected == 0))
         {
            #include "include\shooting.h"
         }
         else
         {
         //----------- Main loop ------------
         while ((((frgnd.Plr1.Lifepnt) || (frgnd.Plr1.Counter > -360) ||
                  (frgnd.Plr2.Lifepnt) || (frgnd.Plr2.Counter > -360)) &&
                  (!Results)) || (DemoMode))
         {
            dbuff.ClearDrawArea (0,0,0);

            if ((i = ExecScript (&bkgnd[0], Chars, &FrameCounter)) != 0)
               EndRound = i;

            if ((!EndRound) && (!YouLose))
               Control_Read (&trigger, &frgnd, GamePause ? -1 : commonvab,
                             &Buttons);

            if (Flash[0] || Flash[1])
            {
               while (Flash[0] || Flash[1])
               {
                  if (Flash[0])
                     Flash[0]--;
                  if (Flash[1])
                     Flash[1]--;
                  dbuff.FlashScreen ();
               }
            }

            if ((((frgnd.Plr1.Lifepnt != 0) || (frgnd.Plr2.Lifepnt != 0)) &&
                (!GamePause)) || (DemoMode))
               FrameCounter++;

            #ifdef TARGETCD             // Game over ?  Then play the music
               #ifdef PLAY_CDXAS        // that goes with it
                  if ((frgnd.Plr1.Lifepnt < 1) && (frgnd.Plr2.Lifepnt < 1) &&
                      ((frgnd.Plr1.Counter == -1) || (frgnd.Plr2.Counter == -1)))
                  {
                     AudioStop (CDXAId);
                     AudioPlayCue (SD_Gameover);
                  }
               #endif
            #endif

            //-------------------------
            if ((ActualScript == 7) && (LE1orLE2 == 1))
            {
               if (BossStageCoachDead == 1)
               {
                  BossStageCoachDead++;
                  Chars[0]->ScaleTo (2000, 120);
               }
               else if (BossStageCoachDead == 3)
               {
                  for (i = 0; i < 17; i++)
                     Chars[i]->StopAction ();
                  BossStageCoachDead++;
               }
               else if (((BossStageCoachDead % 15) == 0) && (BossStageCoachDead > 0))
               {
                  BossStageCoachDead++;
                  short ExploDX[7] = {  0,-25, 25,  0,  0,-25, 25};
                  short ExploY[7] =  {150,160,160,140,140,150,150};
                  if ((i = BossStageCoachDead / 15 - 1) < 7)
                  {
                     point miew = Chars[0]->Coordinate ();
                     NewExplosion (miew.x + ExploDX[i], ExploY[i], 4, 4096);
                  }
                  else
                  {
                     BossStageCoachDead = 0;
                     EndRound = 1;
                     Chars[2]->Relive ();
                     Chars[2]->SetCharacteristics (16384);
                     Chars[2]->StartAction (13, 0);
                     Chars[2]->Scale (2048);
                     Chars[2]->SetDepth (13);
                     point ruffle = Chars[2]->Coordinate ();
                     Chars[2]->Set_Location (ruffle.x, 100);
                     Chars[2]->ScaleTo (6000, 180);
                     Chars[2]->MoveTo (160, 50, 180);
                  }
               }
               else if (BossStageCoachDead > 2)
                  BossStageCoachDead++;

               AddAttach (Chars[1], Chars[0], 0, -50);
               if (BarrelUp)
               {
                  if (BarrelUp == 6)
                  {
                     BarrelUp = 0;
                     point puir = Chars[1]->Coordinate ();
                     Chars[7 + NextBarrel]->Set_Location (puir.x, puir.y);
                     Chars[7 + NextBarrel]->SetDepth (11);
                     Chars[7 + NextBarrel]->Scale (Chars[1]->GetScale () >> 1);
                     Chars[7 + NextBarrel]->Relive ();
                     Chars[7 + NextBarrel]->StartAction (0, puir.x < 161 ? 1 : 0);
                     Chars[7 + NextBarrel]->ScaleTo (6200, (6200 - (Chars[1]->GetScale () >> 1)) / 40);
                     Chars[12 + NextBarrel]->Set_Location (puir.x, 120);
                     Chars[12 + NextBarrel]->SetDepth (11);
                     Chars[12 + NextBarrel]->Scale (Chars[1]->GetScale () >> 1);
                     Chars[12 + NextBarrel]->Relive ();
                     Chars[12 + NextBarrel]->StartAction (1, puir.x < 161 ? 1 : 0);
                     Chars[12 + NextBarrel]->ScaleTo (6200, (6200 - (Chars[1]->GetScale () >> 1)) / 40);

                     if (++NextBarrel == 5)
                        NextBarrel = 0;
                  }
                  Chars[1]->Relive ();
                  Chars[1]->StartAction (2, 0);
               }
               else
                  Chars[1]->StopAction ();
            }

            //-------------------------
            else if ((ActualScript == 14) && (LE1orLE2 == 1))
            {
               #include "include\saloon7.h"
            }

            //-------------------------
            else if ((ActualScript == 5) && (LE1orLE2 == 1)) // Bank 5 LE2 ?
               Chars[39]->Set_Location (SmallFireX, SmallFireY - 6);

            //-------------------------
            else if ((ActualScript == 5) && (LE1orLE2 == 0)) // Bank car chase ?
            {
               #include "include\carchase.h"
            }

            //-------------------------
            else if ((ActualScript == 17) && (LE1orLE2 == 0)) // Drug dealer car
            {                                            // chase
               #include "include\drdcarch.h"
            }

            //-------------------------
            else if ((ActualScript == 20) && (LE1orLE2 == 0))
            {
               #include "include\chemicl3.h"
            }

            //-------------------------
            // When the airport's boss is down, guys can appear...
            if ((BossAirportDown) && ((FrameCounter % 100) == 0))
            {
               char whichchtype[25] = {0,1,0,0,1,1,0,1,0,1,0,0,1,
                                       1,0,1,0,1,0,0,1,1,0,1,0};

               Chars[ExtraGuyNbr]->SetDepth (8);
               if (whichchtype[ExtraGuyNbr - 86])  // Worker guy or guerilla guy ?
               {
                  Chars[ExtraGuyNbr]->Set_Location (rand () % 200 + 60, 130);
                  Chars[ExtraGuyNbr]->StartAction (12, 0);
               }
               else
               {
                  Chars[ExtraGuyNbr]->Set_Location (rand () % 200 + 60, 130);
                  Chars[ExtraGuyNbr]->StartAction (2, 0);
               }

               if ((++ExtraGuyNbr) == 111)
                  ExtraGuyNbr = 86;
            }

            // Do the explosions when the airport's boss dies
            if (BossAirportDead)
            {
               u_short explox[16] = {90,225,140,100,255,100,200,190,175,70,195,180,265,140,60,235};
               u_short exploy[16] = {70,80,145,195,160,95,135,220,55,155,170,105,100,78,192,55};
               if ((++AirportEndCnt) > 159)
                  AirportEndCnt = 159;
               else
               {
                  if ((AirportEndCnt % 10) == 0)
                  {
                     int eeee = AirportEndCnt / 10;
                     NewExplosion (explox[eeee], exploy[eeee], 14, 8192);
                  }
               }
               if (AirportEndCnt == 80)   // Erase all bullet holes...
                  InitBulletHoles ();
            }

            //-------------------------
            if (BossChemicalDead)
            {
               short explox[10] = {-25,25,15,5,-15,35,-15,25,5,-15};
               short exploy[10] = {-25,-35,25,-25,5,5,25,25,-5,-15};
               if ((++AirportEndCnt) > 99)
                  AirportEndCnt = 99;
               else
               {
                  if ((AirportEndCnt % 10) == 0)
                  {
                     point pnt = Chars[61]->Coordinate ();
                     int eeee = AirportEndCnt / 10;
                     NewExplosion (explox[eeee] + pnt.x, exploy[eeee] + pnt.y, 14,4096);
                  }
               }
            }

            //-------------------------
            if (DemoMode)
            {
               if (frgnd.Plr1.Lifepnt)
                  Init_Player (&frgnd.Plr1);
               if (frgnd.Plr2.Lifepnt)
                  Init_Player (&frgnd.Plr2);
            }

            if (debug)
            {
               FntPrint ("\n\n\n");
               FntPrint ("Topmemory: 0x%08x\n", MemoryP);
               FntPrint ("FrameCounter: %d\n", FrameCounter);
               FntPrint ("VCnt: %d\n", vcnt);
               Chars[0]->DumpData ();
               Chars[1]->DumpData ();
//               FntPrint ("Gun 0  X:%4d  Y:%4d\n", frgnd.Plr1.GunX, frgnd.Plr1.GunY);
//               FntPrint ("Gun 1  X:%4d  Y:%4d\n", frgnd.Plr2.GunX, frgnd.Plr2.GunY);
//               if (IntrusReload[0])
//                  FntPrint ("Gun 1 Reload!\n");
//               else
//                  FntPrint ("\n");
//               if (IntrusReload[1])
//                  FntPrint ("Gun 2 Reload!\n");
//               else
//                  FntPrint ("\n");
//               FntPrint ("Gun0 sample X:%4d  Y:%4d\n", IntrusGunX[0][0], IntrusGunY[0][0]);
//               FntPrint ("            X:%4d  Y:%4d\n", IntrusGunX[0][1], IntrusGunY[0][1]);
//               FntPrint ("            X:%4d  Y:%4d\n", IntrusGunX[0][2], IntrusGunY[0][2]);
            }

            if (DemoMode)
            {
               SetFontColor (1);
               FontCenterOn (160,120);
               if (VSync (-1) & 64)
                  Print ("Game Over");

               trigger = 0;
               if ((Buttons & 1) || (CurrentMardien == NbrMardien))
               {
                  Results = 1;
                  DemoMode = 0;
               }
               Buttons = 0;
            }

            #include "include\pause.h"

            //-------------------------
            if (BloodyMode)
               DrawBlood (&dbuff, bkgnd[0].Bkd_X (), bkgnd[0].Bkd_Y ());
            DrawBulletHoles (&dbuff, bkgnd[0].Bkd_X (), bkgnd[0].Bkd_Y ());
            bkgnd[0].ChangeClut ();
            if (DemoMode)
               bkgnd[0].Draw (&dbuff, 0);
            else
               bkgnd[0].Draw (&dbuff, ((GamePause) || ((frgnd.Plr1.Lifepnt <= 0) && (frgnd.Plr2.Lifepnt <= 0))));
            Draw_Foreground (&frgnd, &dbuff, 0, commonvab);
            DrawFiring (&dbuff, bkgnd[0].Bkd_X (), bkgnd[0].Bkd_Y (), commonvab);
            DrawPlrFiring (&dbuff);
            DrawInnocent (bkgnd[0].Bkd_X (), bkgnd[0].Bkd_Y (), &dbuff);
            DrawExplosions (bkgnd[0].Bkd_X (), bkgnd[0].Bkd_Y (), &dbuff);
            DrawEnemyLife (&dbuff);

            if ((((frgnd.Plr1.Lifepnt <= 0) && (frgnd.Plr1.Counter < 1200) &&
                (frgnd.Plr2.Lifepnt <= 0) && (frgnd.Plr2.Counter < 1200)) ||
                (GamePause)) && (!DemoMode))
            {  // If both players are dead or the game paused, stop animation
               for (i = 0; i < NbrChars; i++)
                  Chars[i]->DrawFrame (bkgnd[0].Bkd_X (), bkgnd[0].Bkd_Y (),
                                       &dbuff);
            }
            else     // Otherwise, animate
            {
               for (i = 0; i < NbrChars; i++)
               {
                  Chars[i]->ChangeClut (0);
                  shot = Chars[i]->DrawNextFrame (bkgnd[0].Bkd_X (), bkgnd[0].Bkd_Y (),
                                                  &dbuff, &Sfx, &Vab, &posi);
                  if (Sfx != -1)    // Play a character's SFX if needed...
                  {

                     if ((posi > 159) && (posi < 320))      // Right part
                     {
                        voll = (320 - posi) * 127 / 160;
                        PlaySFX (Vab, Sfx, voll,127);
                     }
                     else if ((posi < 160) && (posi > -1))  // Left part
                     {
                        volr = posi * 127 / 160;
                        PlaySFX (Vab, Sfx, 127,volr);
                     }
                  }
                  if (shot != NULL)
                  {
                     DynamicDifficulty = 0; // Reset the dyn. diff. to easy
                     if (shot->GunType != 250)
                     {
                        int GunTypeSFX[10] = {0,28,10,28,0,0,28,0,1,0};
                        int GunTypeSFXOn[10] = {-1, 0, 0, 0,-1,-1, 0,-1,1,-1};
                        if (shot->GunType == 7)
                           bkgnd[0].Shake ();
                        AddFiring (shot, &frgnd, bkgnd[0].Bkd_X (), bkgnd[0].Bkd_Y ());
                        if ((shot->x > 159) && (shot->x < 320)) // Right part
                        {
                           volr = 127;
                           voll = (320 - shot->x) * 127 / 160;
                        }
                        else if ((shot->x < 160) && (shot->x > -1)) // Left part
                        {
                           voll = 127;
                           volr = shot->x * 127 / 160;
                        }
                        if (GunTypeSFXOn[shot->GunType] == 0)
                           PlaySFX (commonvab, GunTypeSFX[shot->GunType],
                                    voll,volr);
                        else if (GunTypeSFXOn[shot->GunType] == 1)
                           PlaySFX (bkdvab, GunTypeSFX[shot->GunType],
                                    voll,volr);
                        // Handle the case where a character is in front of
                        // another character who's shooting (breaking windows)
                        Power = 10;
                        for (j = Chars[i]->GetDepth () + 1; (j < 15) && (Power); j++)
                        {
                           for (k = 0; (k < NbrChars) && (Power); k++)
                           {
                              if (Chars[k]->GetDepth () == j)
                              {
                                 if (Chars[k]->GetHit (shot->x, shot->y, NULL,
                                                       Power, &bkgnd[0], &dbuff))
                                    Power = 0;
                              }
                           }
                        }
                     }
                     else                       // Oups.  Falling object.
                     {
                        RECT *collision = Chars[i]->GetHitBox ();
                        int dpth = Chars[i]->GetDepth ();
                        for (j = 0; j < NbrChars; j++)
                           if (j != i)
                              Chars[j]->Collision (collision, dpth);
                     }
                  }
               }
            }

            if ((!EndRound) && (!GamePause))
               Draw_Gun_Cursor (&frgnd, &dbuff, 0);

            if ((trigger) || (DemoMode))
            {
               if (DemoMode)
               {
                  if (ShotMardien[CurrentMardien - 1].PlayerNbr)
                  {
                     player = &frgnd.Plr2;
                     meu = 1;
                  }
                  else
                  {
                     player = &frgnd.Plr1;
                     meu = 0;
                  }
                  player->GunX = ShotMardien[CurrentMardien - 1].X;
                  player->GunY = ShotMardien[CurrentMardien - 1].Y;
               }
               else if (trigger == 1)
               {
                  player = &frgnd.Plr1;
                  i = 0;
                  trigger--;
                  meu = 0;
               }
               else
               {
                  player = &frgnd.Plr2;
                  i = 3;
                  trigger -= 2;
                  meu = 1;
               }

               if (player->Counter < 59)
                  player->Score = 0;

               if ((player->Bullets > 0) && ((player->Lifepnt > 0) || (DemoMode)))
               {                                           // Shoot a bullet
                  int SfxGun[6][7] = {{1,10,-1,-1,-1,-1,-1}, {1,10,2,-1,-1,2,4},
                                      {1,10,4,-1,1,4,7}, {1,10,2,4,1,2,3},
                                      {1,10,13,14,1,13,-1}, {1,10,5,-1,1,5,3}};
                  int VabGun[7] = {0,0,1,1,0,1,1};

                  player->Shots++;
                  voll = player->PlayerNbr ? 63 : 127;
                  volr = player->PlayerNbr ? 127 : 63;
                  PlaySFX (VabGun[player->BulletType],
                           SfxGun[LevelSelected][player->BulletType], voll,volr);
                  if (player->BulletType == 3)
                     NewExplosion (player->GunX - bkgnd[0].Bkd_X (), player->GunY - bkgnd[0].Bkd_Y (), 15, 3200);
                  else
                     AddPlrFiring (meu, player->BulletType, player->GunX, player->GunY);
                  player->Bullets--;
                  if ((DemoMode) && (player->Bullets == 0))
                     ReloadPlrGun (player, commonvab);
                  if ((!player->BulletType) && (player->Bullets == 1)) //"Reload"
                  {
                     voll = player->PlayerNbr ? 0 : 127;
                     volr = player->PlayerNbr ? 127 : 0;
                     PlaySFX (commonvab, 19, voll,volr);
                  }
                  else if (!player->Bullets)               // "Reload"
                  {
                     voll = player->PlayerNbr ? 0 : 127;
                     volr = player->PlayerNbr ? 127 : 0;
                     PlaySFX (commonvab, 19, voll,volr);
                  }

                  // Check if the player has shot a guy or a wall or whatever
                  Power = GunPower[player->BulletType];
                  for (j = 15; (j && Power); j--)
                  {
                     if ((j == 10) || (j == 5))
                     {
                        if (bkgnd[0].GetHit (j / 5, player->GunX - bkgnd[0].Bkd_X (),
                                          player->GunY - bkgnd[0].Bkd_Y (),
                                          &Sfx, &Vab))
                        {
                           if (Sfx != -1)
                           {
                              if ((posi < 159) && (posi < 320))    // Right part
                              {
                                 volr = (320 - posi) * 127 / 160;
                                 PlaySFX (Vab, Sfx, 127,volr);
                              }
                              else if ((posi < 160) && (posi > -1)) // Left part
                              {
                                 voll = posi * 127 / 160;
                                 PlaySFX (Vab, Sfx, voll,127);
                              }
                           }
                           Power--;
                           shootpnt Shot = {player->GunX - bkgnd[0].Bkd_X (),
                                            player->GunY - bkgnd[0].Bkd_Y (),
                                            player->BulletType, 0};
                           AddBulletHole (&Shot, j);
                        }
                     }
                     else
                     {
                        for (i = 0; (i < NbrChars) && (Power); i++)
                        {
                           if (Chars[i]->GetDepth () == j)
                           {
                              if (zut = Chars[i]->GetHit (player->GunX - bkgnd[0].Bkd_X (),
                                                    player->GunY - bkgnd[0].Bkd_Y (),
                                                    player, Power, &bkgnd[0], &dbuff))
                              {
                                 if (zut == -1)
                                 {
                                    EndRound = 1;
                                    if ((LE1orLE2 == 0) && (LevelSelected == 3))
                                    {
                                       bkgnd[0].BuildDestClut (1);
                                       for (i = 0; i < NbrChars; i++)
                                          if (i != 81)
                                             Chars[i]->BuildDestClut (1);
                                    }
                                    else
                                    {
                                       bkgnd[0].BuildDestClut (0);
                                       for (i = 0; i < NbrChars; i++)
                                          Chars[i]->BuildDestClut (0);
                                    }
                                 }
                                 else if ((ActualScript == 17) &&
                                          (LE1orLE2 == 0) && (i > 70) &&
                                          (i < 76))
                                 {
                                    for (k = 61; k < 71; k++)
                                       Chars[k]->TurnWhite ();
                                 }
                                 if (~Chars[i]->Characteristic () & 32)
                                    Power--;
                                 player->Hits++;
                              }
                           }
                        }
                     }
                  }
               }
            }

            if (EndRound != 0)
            {
               if (shower > 0)
               {
                  if (actualvol)
                  {
                     actualvol -= 2;
                     if (actualvol < 0)
                        actualvol = 0;
                     #ifdef TARGETCD
                        #ifdef PLAY_CDXAS
                           AudioChangeVolume (CDXAId, actualvol);
                        #endif
                     #endif
                  }
               }

               shower--;
            }
            else
               shower = 64;

            if ((EndRound != 0) && (shower == 0))
               Init_Score (MemoryP, EndRound, &frgnd.Plr1, &frgnd.Plr2);

            if ((EndRound != 0) && (shower < 0))
               Results = Show_Results (&frgnd.Plr1, &frgnd.Plr2, &dbuff);

            dbuff.Swap (debug);            // swap double buffer
         }

         }      // End of main while for non shooting range levels

         ClearScore ();

         for (i = 0; i < NbrChars; i++)
            Chars[i]->Clear ();
         bkgnd[0].Clear ();

         dbuff.ClearDrawArea (0,0,0);
         dbuff.Swap (debug);
         dbuff.Swap (debug);
         CloseSFX (bkdvab);

         // If arcade mode, go to the next level when the previous one is done
         if (!GameMode)
         {
            if ((ActualScript == LastScript) && (LevelSelected != 6))
            {
               LevelSelected++;
               ActualScript = FirstScript[LE1orLE2][LevelSelected];
               LastScript = ActualScript + NbrScripts[LE1orLE2][LevelSelected];
               #ifdef TARGETCD
                  #ifdef PLAY_MOVIES
                     PlayMovie (MovieName[LevelSelected], 1, 122, MemoryP, &dbuff, 1);
                  #endif
               #endif
            }
            else if ((ActualScript == LastScript) && (LevelSelected == 6))
            {
               frgnd.Plr1.Lifepnt = 0;
               frgnd.Plr2.Lifepnt = 0;
            }
         }

         // Remove all the X in the stage select screen
         if ((frgnd.Plr1.Lifepnt == 0) && (frgnd.Plr2.Lifepnt == 0))
         {
            for (i = 0; i < 6; i++)
               CannotSelect[i] = 0;
            LevelSelected = -1;
            ActualScript = -1;
         }

//         if ((frgnd.Plr1.Lifepnt == 0) && (frgnd.Plr2.Lifepnt == 0))
//            EnterNameHOF (&frgnd, 0, MemoryP, &dbuff);
      }
   }
}

//-------------------------------------
// Function called 60 times per second
// by the VSync callback (for the gun)
//-------------------------------------
void Intrus (...)
{
   int gunx = Read_Gun_x ();            // Read the coordinate of the gun
   int guny = Read_Gun_y ();

   if ((gun[vcnt]->id == PADID_GUN) && (gun[vcnt]->result == 0))
   {
      if ((gunx != 0) || (guny != 0))
      {
         if (Flash[vcnt])
         {
            IntrusGunX[vcnt][IntrusIndex[vcnt]] = gunx;
            IntrusGunY[vcnt][IntrusIndex[vcnt]] = guny;
//            IntrusIndex[vcnt]++;
            IntrusReload[vcnt] = 0;
         }
      }
      else
         IntrusReload[vcnt] = 1;        // The gun must be OFFSCREEN
   }

   switch (vcnt)
   {
      case 0: SelectGun (0, 1);
              SelectGun (1, 0);
              break;
      case 1: SelectGun (0, 0);
              SelectGun (1, 1);
              break;
   }

   vcnt = (++vcnt) & 1;                 // Alternate between gun 0 & 1
}
