// Header File
// Created 6/17/2007; 2:35:06 PM

#include "defs.h"

enum EnemyBehaviors
{
	COMING, GOING, FLEEING
};

		FATSPRITE				sprites[MAX_NR_SPRITES];
    TEXANIMATION    texanim;
    TEXANIMATION		texanim2;
    TEXANIMATION		texanim3;
    TEXANIMATION		texanim4;
    TEXCONFIG				boss[14];
    TEXCONFIG 			turbine[2];
    TEXCONFIG       textures[86]; // textures 57,58,59 and 66 are dummy texconfigs for 
    TEXCONFIG				cpos[6];      // putting the current frame of wall animation in.
    TEXCONFIG				cyborg[6];    // e.g. computer terminals and such. 
    TEXCONFIG				zombie[6];
    TEXCONFIG				enemydeath[4];
    TEXCONFIG 			barrel[5];
    TEXCONFIG 			shotgun[1];
    TEXCONFIG 			railgun[1];
    TEXCONFIG 			shotgunshells[1];
    TEXCONFIG				ammobox[1];
    TEXCONFIG				healthlarge[1];
    TEXCONFIG				healthsmall[1];
    TEXCONFIG 			imp[6];
    TEXCONFIG				torch[4];
    TEXCONFIG				yellowkey[1];
    TEXCONFIG				bluekey[1];
    TEXCONFIG				column[1];
    TEXCONFIG				skullbox[4];
    TEXCONFIG				pendulum[7];
    TEXCONFIG				fire[6];
    TEXCONFIG				spikes[5];
    TEXCONFIG 			vines[3];
    TEXCONFIG				playerdeath[4];	
    TEXCONFIG				hostage[5];
    TEXCONFIG				arrows[3];
    TEXCONFIG 			portal[3];
    TEXCONFIG				fireball[8];
    TEXCONFIG				rocket[1];
    TEXCONFIG				rocketlauncher[1];
    TEXCONFIG				plasma[1];
    TEXCONFIG				explosion[3];
    TEXCONFIG				plasmagun[1];
    TEXCONFIG				plasmaammo[1];
    TEXCONFIG				rocketammo[1];
    TEXCONFIG 			doomguyfront[4];
    TEXCONFIG 			doomguyback[4];	
    PADSTATES       key    = 0;
    unsigned long* titlescreen1 = NULL;
    unsigned long* titlescreen2 = NULL;
    unsigned long* map_plane1 = NULL;
    unsigned long* map_plane2 = NULL;
    unsigned long* youarehere = NULL;
    unsigned short* plasma_hud1plane1;
    unsigned short* plasma_hud1plane2;
    unsigned short* plasma_hud1mask;
    unsigned short* plasma_hud2plane1;
    unsigned short* plasma_hud2plane2;
    unsigned short* plasma_hud2mask;
    unsigned short* plasma_hud3plane1;
    unsigned short* plasma_hud3plane2;
    unsigned short* plasma_hud3mask;
    unsigned short* rocket_hud1plane1;
    unsigned short* rocket_hud1plane2;
    unsigned short* rocket_hud1mask;
    unsigned short* rocket_hud2plane1;
    unsigned short* rocket_hud2plane2;
    unsigned short* rocket_hud2mask;
    unsigned short* rocket_hud3plane1;
    unsigned short* rocket_hud3plane2;
    unsigned short* rocket_hud3mask;
    unsigned short* rocket_hud4plane1;
    unsigned short* rocket_hud4plane2;
    unsigned short* rocket_hud4mask;
    unsigned short* punch_hud1plane1;
    unsigned short* punch_hud1plane2;
    unsigned short* punch_hud2plane1;
    unsigned short* punch_hud2plane2;
    unsigned short* punch_hud3plane1;
    unsigned short* punch_hud3plane2;
    unsigned short* punch_hudmask1;
    unsigned short* punch_hudmask2;
    unsigned short* punch_hudmask3;
    unsigned long* ztheta1 = NULL;
    unsigned long* ztheta2 = NULL;
    unsigned short*  bg_img = NULL;
    unsigned short* background = NULL;
    unsigned short* dark_background = NULL;
    unsigned short* dark_background2 = NULL;
    unsigned short* hud1_plane1 = NULL;
    unsigned short* hud1_plane2 = NULL;
    unsigned short* hud2_plane1 = NULL;
    unsigned short* hud2_plane2 = NULL;
    unsigned short* hud3_plane1 = NULL;
    unsigned short* hud3_plane2 = NULL;
    unsigned short* hud1mask = NULL;
    unsigned short* hud2mask = NULL;
    unsigned short* hud3mask = NULL;
    unsigned short* shotgun_hud1_plane1 = NULL;
    unsigned short* shotgun_hud1_plane2 = NULL;
    unsigned short* shotgun_hud2_plane1 = NULL;
    unsigned short* shotgun_hud2_plane2 = NULL;
    unsigned short* shotgun_hud3_plane1 = NULL;
    unsigned short* shotgun_hud3_plane2 = NULL;
    unsigned short* shotgun_hud4_plane1 = NULL;
    unsigned short* shotgun_hud4_plane2 = NULL;
    unsigned short* shotgunhud1mask = NULL;
    unsigned short* shotgunhud2mask = NULL;
    unsigned short* shotgunhud3mask = NULL;
    unsigned short* shotgunhud4mask = NULL;
    unsigned short* railgun_hud1_plane1 = NULL;
    unsigned short* railgun_hud1_plane2 = NULL;
    unsigned short* railgun_hud2_plane1 = NULL;
    unsigned short* railgun_hud2_plane2 = NULL;
    unsigned short* railgunhud1mask = NULL;
    unsigned short* railgunhud2mask = NULL;
    unsigned short* pistolhudmove1plane1 = NULL;
    unsigned short* pistolhudmove1plane2 = NULL;
    unsigned short* pistolhudmove2plane1 = NULL;
    unsigned short* pistolhudmove2plane2 = NULL;
    unsigned short* pistolhudmove1mask = NULL;
    unsigned short* pistolhudmove2mask = NULL;
    unsigned short* shotgunhudmove1plane1 = NULL;
    unsigned short* shotgunhudmove1plane2 = NULL;
    unsigned short* shotgunhudmove2plane1 = NULL;
    unsigned short* shotgunhudmove2plane2 = NULL;
    unsigned short* shotgunhudmove1mask = NULL;
    unsigned short* shotgunhudmove2mask = NULL;
    unsigned short* railgunhudmove1plane1 = NULL;
    unsigned short* railgunhudmove1plane2 = NULL;
    unsigned short* railgunhudmove2plane1 = NULL;
    unsigned short* railgunhudmove2plane2 = NULL;
    unsigned short* railgunhudmove1mask = NULL;
    unsigned short* railgunhudmove2mask = NULL;
    unsigned short* facedead;
    unsigned short* facegrin;
    unsigned short* facegrinhurt1;
    unsigned short* facegrinhurt2;
    unsigned short* facepain1;
    unsigned short* facepain2;
    unsigned short* facepain3;
    unsigned short* lookleft1;
    unsigned short* lookright1;
    unsigned short* lookleft2;
    unsigned short* lookright2;
    unsigned short* lookleft3;
    unsigned short* lookright3;
    unsigned short* titlehud1;
    unsigned short* titlehud2;
    short           i,j;
    unsigned short* dest;
    HANDLE          texfile1 = 0;
    HANDLE          texfile2 = 0;
    HANDLE          texfile3 = 0;
    HANDLE          texfile4 = 0;
    HANDLE          texfile5 = 0;
    HANDLE          texfile6 = 0;
    HANDLE          texfile7 = 0;    
    unsigned char*  src     = 0;
    LCD_BUFFER      lcd;
		short           result;

static inline void SetupSwitchComps(FATCONFIG *fc);
void KillProjectile(FATCONFIG *fc,short idx);
void KillFireBall(FATCONFIG *fc,short idx);		
void SetUserFont(unsigned char* pFontGraphics, unsigned char* pFontWidths, short fontHeight);
void GrayUserDrawString8(short x, short y, const char* str);
SYM_ENTRY* GetSymEntry(const char* fileName);
void* OpenFile(const char* fileName);
short CloseFile(const char* fileName);
static inline void InitiateSprite(FATSPRITE* sprites,int index,short x,short y);		
void FindSpecialTile(FATCONFIG *fc);
void RealityFlicker(void);
void Darkness(FATCONFIG *fc,DEPTHDATA* dd);
void SetBackgroundImage(FATCONFIG *fc,unsigned short* background);
void SetBlackBackground(FATCONFIG *fc);
void ShowScrollingText(FATCONFIG *fc,int number);
static inline void ShowMap(short xpos,short ypos);
static inline void PreLevelSwitchTasks(FATCONFIG *fc);
static inline void ClearFacePlane(void);
static inline void UpdateFace(unsigned short* face);
static inline void UpdateFaceTimer();
static inline void Fix3(char *buffer, short value);
static inline void InitGUI(void);
static inline void UnlockHandleOfMapFile();	
static inline void LockHandleOfMapFile(FATCONFIG *fc);  
static inline void LoadTextures();
static inline void LoadExternalLevel(int level, FATCONFIG *fc);
static inline void SwitchLevel(FATCONFIG *fc,char Spawn,char Dissolve);
static inline void PutSprites(FATCONFIG *fc,FATSPRITE *sprites,SpriteStruct *s);
static inline void CreateDoors(FATCONFIG *fc,TEXCONFIG *textures);
static void ShowTitleScreen(void);
static int ShowMenu(FATCONFIG *fc,char menunumber);
static void dissolve(void);
static inline void UpdateDamage(FATCONFIG *fc,register int index);
void PlayerDeath(FATCONFIG *fc);
static inline void LoadConfig(FATCONFIG *fc);
static inline void SaveConfig(FATCONFIG *fc);
static inline void FixSpriteTex(FATCONFIG *fc);
static inline void UpdateSwitchDoors(FATCONFIG *fc);
static inline void UpdateSwitchDoors2(FATCONFIG *fc);
void MessageEnqueue(short message);

static inline void UnlockTexFiles()
{
	if (textures) FAT_UnlockHandleOfFile(texfile1);  // unlock texture file
  if (textures) FAT_UnlockHandleOfFile(texfile2);  // unlock texture file
  if (textures) FAT_UnlockHandleOfFile(texfile3);  // unlock texture file
  if (textures) FAT_UnlockHandleOfFile(texfile4);  // unlock texture file
  if (textures) FAT_UnlockHandleOfFile(texfile5);  // unlock texture file
  if (textures) FAT_UnlockHandleOfFile(texfile6);  // unlock texture file
  if (textures) FAT_UnlockHandleOfFile(texfile7);  // unlock texture file
}

void PostGameCleanup(FATCONFIG *fc,char error_type)
{
			dissolve();
			FontSetSys(F_8x10);
    	GrayUserDrawString8(20+display_offsetx,50+display_offsety,"SHUTTING DOWN...");
    
			if (mapfile_handle && firstrun != 1)PreLevelSwitchTasks(fc);
    	if (mapfile_handle)UnlockHandleOfMapFile(fc);
    	FAT_AllKeysReleased();
    	GrayOff();
    	UnlockTexFiles();
    	FAT_UnloadEngine();
    	RestoreHandlerForINTs();
    	if (bg_img)free(bg_img);
    	OSqclear(kbd_queue());
    	CloseFile("doomfont"); //closes the doom font file. 
    	if (current_map) free(current_map);
    	
    	LCD_restore(lcd);
    	
    	switch (error_type)
			{
				case ERR_NORMAL_EXIT: ST_helpMsg("Doom89 Version 2.02 - Powered by (C)FAT engine"); break;
				case ERR_MEMORY:      ST_helpMsg("ERROR: out of memory"); break;
				case ERR_TEXFILE1: 		ST_helpMsg("ERROR: cannot load textures from doomgfx1"); break;
				case ERR_TEXFILE2: 		ST_helpMsg("ERROR: cannot load textures from doomgfx2"); break;
				case ERR_TEXFILE3: 		ST_helpMsg("ERROR: cannot load textures from doomgfx3"); break;
				case ERR_TEXFILE4: 		ST_helpMsg("ERROR: cannot load textures from doomgfx4"); break;
				case ERR_TEXFILE5: 		ST_helpMsg("ERROR: cannot load textures from doomgfx5"); break;
				case ERR_TEXFILE6: 		ST_helpMsg("ERROR: cannot load textures from doomgfx6"); break;
				case ERR_TEXFILE7: 		ST_helpMsg("ERROR: cannot load textures from doomgfx7"); break;
				case ERR_TEXTFILE1: 		ST_helpMsg("ERROR: doomtext file missing!"); break;
				case ERR_TEXTFILE2: 		ST_helpMsg("ERROR: doomcdts file missing!"); break;
				case ERR_MAPFILE:			ST_helpMsg("ERROR: No mapfile loaded"); break;
				case ERR_FONTFILE:			ST_helpMsg("ERROR: No fontfile loaded"); break;
				default: 							ST_helpMsg("ERROR: Unknown Error Occoured"); break;
			}
			
			exit(0);
}

void Wait(unsigned char wait)
{
	unsigned char a,b,c,d,e;
	for (a=0; a<wait; a++)
	{
		if ((b+1) >= 255)
		{
			b = 0;
		}
		if ((c+2) >= 255)
		{
			c = 0;
		}
		if ((d+4) >= 255)
		{
			d = 0;
		}
		b+=1;
		c+=2;
		d+=4;
			for (e = 0; e<255; e++)
			{
				b = random(255);
			}
		for (e = 0; e<255; e++)
			{
				c = random(255);
			}
		for (e = 0; e<255; e++)
			{
				d = random(255);
			}	
	} 
}


//=============================================================
// CODE curtosy of Malcolm Smith, edited by me.
//=============================================================
void AITurn (FATSPRITE * spr,register short right,register short increment)
{
  spr->orientation += (right) ? increment : -increment;
  // now clamp the camera orientation to the valid range of 0 ... 575
  spr->orientation = FAT_ClampAngle (spr->orientation);
}


//=============================================================
// CODE curtosy of Malcolm Smith, edited by me.
//=============================================================
void AIMove (FATCONFIG * fc, FATSPRITE * spr)
{
	register short stepx;
	register short stepy;
	register short newxpos;
	register short newypos;
		
				
 	stepx = FAT_Cos16384 (spr->orientation) >> 11;
  stepy = FAT_Sin16384 (spr->orientation) >> 11;
  newxpos = spr->xpos + stepx;
  newypos = spr->ypos + stepy;
  
  register short newxmod = newxpos >> 6;
  register short newymod = newypos >> 6;
	
  //-------------------------------------------------------------------------
  // check if we are still within the map
  //-------------------------------------------------------------------------
  
  if (newymod < (fc->map_height - 1) && newymod > 0 &&  newxmod < (fc->map_width - 1) && newxmod > 0) 
  {

    if (!ValidMove (fc, newxpos, newypos))
    {				// if new position is invalid ...
      // ...but old position is OK, we're against a wall to east or west
      
      if (ValidMove (fc, spr->xpos, newypos))
     {
	  // don't change angle if movement is perpendicular to the wall
	  if (stepy != 0)
	    {
	      // if sign(stepx)==sign(stepy), rotate clockwise = turn right
	      if ((stepx > 0) == (stepy > 0)) AITurn (spr, 1, ANGLE_015 / 2);
	      else		AITurn (spr, 0, ANGLE_015 / 2);
	      // still allow movement along y = parallel to wall
	      spr->ypos = newypos;
	    }
	}
      // ...but (new x, old y) is OK, we're against a wall to north or south
      if (ValidMove (fc, newxpos, spr->ypos))
	{
	  // don't change angle if movement is perpendicular to the wall
	  if (stepx != 0)
	    {
	      // if sign(stepx)==sign(stepy), rotate counterclockwise = turn left
	      if ((stepx > 0) == (stepy > 0)) AITurn (spr, 0, ANGLE_015 / 2);
	      else	AITurn (spr, 1, ANGLE_015 / 2);
	      // still allow movement along x = parallel to wall
	      spr->xpos = newxpos;
	    }
	}
		
			AITurn(spr,1,8);
      // ...otherwise we're in a corner, so do nothing
      return;
    }
  //-------------------------------------------------------------------------
  // everything okay -> let's set the new position
  //-------------------------------------------------------------------------
  spr->xpos = newxpos;
  spr->ypos = newypos;
					
	}return;

}

static void UpdateStats(void)
{
	WeaponStruct *curweapon = &weapon;
	FontSetSys(F_4x6);
				GrayFastFillRect_R(GrayGetPlane(LIGHT_PLANE),GrayGetPlane(DARK_PLANE),108+display_offsetx,28+display_offsety,152+display_offsetx,56+display_offsety,0xFFFF);
  			FastOutlineRect(GrayGetPlane(LIGHT_PLANE),107+display_offsetx,30+display_offsety,150+display_offsetx,56+display_offsety,SPRT_XOR);
				DrawGrayStr(108+display_offsetx,32+display_offsety,"lives:",A_XOR);
				DrawGrayStr(108+display_offsetx,38+display_offsety,"health:",A_XOR);
				DrawGrayStr(108+display_offsetx,44+display_offsety,"bullets:",A_XOR);
				if (curweapon->type == ROCKET_LAUNCHER)
				{
					DrawGrayStr(108+display_offsetx,50+display_offsety,"rockets:",A_XOR);
				}
				else if (curweapon->type == PLASMA_GUN)
				{
					DrawGrayStr(108+display_offsetx,50+display_offsety,"plasma:",A_XOR);
				}
				else
				{
					DrawGrayStr(108+display_offsetx,50+display_offsety,"shells:",A_XOR);
				}
				
				char buffer[3];
		Fix3(buffer,gg.lives);
				DrawGrayStr(129+display_offsetx,32+display_offsety,buffer,A_XOR);
		Fix3(buffer,gg.health);
				DrawGrayStr(133+display_offsetx,38+display_offsety,buffer,A_XOR);
		Fix3(buffer,curweapon->ammo);
				DrawGrayStr(137+display_offsetx,44+display_offsety,buffer,A_XOR);
				if (curweapon->type == ROCKET_LAUNCHER)
				{
					Fix3(buffer,curweapon->rockets);
					DrawGrayStr(136+display_offsetx,50+display_offsety,buffer,A_XOR);	
				}
				else if (curweapon->type == PLASMA_GUN)
				{
					Fix3(buffer,curweapon->plasma_ammo);
					DrawGrayStr(136+display_offsetx,50+display_offsety,buffer,A_XOR);	
				}
				else
				{
					Fix3(buffer,curweapon->shells);
					DrawGrayStr(133+display_offsetx,50+display_offsety,buffer,A_XOR);	
				}
		
}


void KillProjectile(FATCONFIG *fc,register short idx)
{
	PlrProj[idx].in_use = SPRITE_FREE;
	PlrProj[idx].exploding = PROJ_NORMAL;
	if (gg.num_plr_proj > 0) gg.num_plr_proj--;
	fc->nr_sprites = gg.num_sprites + gg.num_fireballs + gg.num_plr_proj;
}

 // ========================================================= ///
// ============== BEGIN DAVID RANDALL's CODE ================= ///
//=============================================================///

void SetUserFont(unsigned char* pFontGraphics, unsigned char* pFontWidths, short fontHeight)
{
	userFont.pFont      = pFontGraphics - (32 * fontHeight * 3);
	userFont.pWidth     = pFontWidths;
	userFont.height     = fontHeight;
}

void GrayUserDrawString8(short x, short y, const char* str)
{
	unsigned char* pCharSprite;
	short charAscii;
	short charWidth;
	short charHeight = userFont.height;
	short nextX = x;

	if (y + userFont.height < 128)
	{
		while (*str)
		{
			charAscii = *str;
			charWidth = *(userFont.pWidth + charAscii);

			if ((nextX + charWidth) < 240)
			{
				if (charAscii >= 32)
					pCharSprite = userFont.pFont + (charAscii * charHeight * 3);
				else
					pCharSprite = userFont.pFont;

				GraySprite8_MASK_R(
						nextX,
						y,
						charHeight,
						pCharSprite,
						pCharSprite + charHeight,
						pCharSprite + (charHeight * 2),
						pCharSprite + (charHeight * 2),
						GrayGetPlane(LIGHT_PLANE),
						GrayGetPlane(DARK_PLANE));

				nextX += charWidth;
				str++;
			}
			else
			{
				break;
			}
		}
	}
}

SYM_ENTRY* GetSymEntry(const char* fileName)
{
	SYM_ENTRY* pSymEntry;

	// start the search, search every file in every folder
	pSymEntry = SymFindFirst (SYMSTR (fileName), FO_RECURSE);

	while (pSymEntry)
	{
		if (!strncmp(fileName, pSymEntry->name, 8))
		{
			// we found a matching file name
			break;
		}
		else
		{
			// keep searching the VAT
			pSymEntry = SymFindNext();
		}
	}

	return pSymEntry;
}

void* OpenFile(const char* fileName)
{
	SYM_ENTRY* pSymEntry;
	void* fileAddress = 0;

	pSymEntry = GetSymEntry(fileName);

	if (pSymEntry)
	{
		if (!(pSymEntry->handle))
			HeapLock(pSymEntry->handle);

		fileAddress = HeapDeref (pSymEntry->handle) + 2;
	}

	return fileAddress;
}

short CloseFile(const char* fileName)
{
	SYM_ENTRY* pSymEntry;
	short status = 0;

	pSymEntry = GetSymEntry(fileName);

	if (pSymEntry)
	{
		if (pSymEntry->handle)
			status = HeapUnlock(pSymEntry->handle);
	}

	return status;
}

unsigned char fontWidth[96] =
{
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	4,5,7,7,7,8,7,5, //  !"#$%&'
	6,6,7,7,6,8,5,7, // ()*+,-./
	7,7,7,7,7,7,7,7, // 01234567
	7,7,5,6,8,8,8,8, // 89:;<=>?
	4,8,8,8,8,8,7,8, // @ABCDEFG
	7,3,7,8,7,8,8,8, // HIJKLMNO
	7,8,7,8,7,7,7,8, // PQRSTUVW
	8,7,8,6,7,6,0,0  // XYZ[\]
};


/// ========================================================= ///
// ============== END DAVID RANDALL's CODE ===================///
//=============================================================///




void FindSpecialTile(FATCONFIG *fc)
{
	register short x,y,index;
	index = fc->nr_sprites-=1;
	register SpriteStruct *sprite_data asm("a5") = sprites_extra;
	register char* map_data asm("a6") = fc->map_data;
	SpriteStruct *s = sprite_data;
	
	 for (y=1; y<(fc->map_height-1); ++y) {
        for (x=1; x<(fc->map_width-1); ++x) {
        
        if (map_data[y*fc->map_width+x] == -122)
        {
 					DarkTile.x = x;
 					DarkTile.y = y;       	
        }
        
        if (map_data[y*fc->map_width+x] == -121
        	  || map_data[y*fc->map_width+x] == -119
        	  || map_data[y*fc->map_width+x] == -117)
        	  {
        	  	s[index].staticsprite = 12;
							s[index].src = portal;
							gg.num_sprites++;
							fc->nr_sprites = gg.num_sprites;
							InitiateSprite(sprites,index,x,y);
							if (index < MAX_NR_SPRITES)
              {
              index++;
              }
        	  }
        	  
        if (map_data[y*fc->map_width+x] == -120)
        {
        	Portal[0].x = ((x*64)+32);
        	Portal[0].y = ((y*64)+32);
        } 
        if (map_data[y*fc->map_width+x] == -118)
        {
        	Portal[1].x = ((x*64)+32);
        	Portal[1].y = ((y*64)+32);
        } 
        if (map_data[y*fc->map_width+x] == -116)
        {
        	Portal[2].x = ((x*64)+32);
        	Portal[2].y = ((y*64)+32);
        } 
        	   
        
        }
     }
}

void KillFireBall(FATCONFIG *fc,short idx)
{
	fireballs[idx].in_use = SPRITE_FREE;
	fireballs[idx].exploding = PROJ_NORMAL;
	if (gg.num_fireballs >0) gg.num_fireballs--;
	fc->nr_sprites = gg.num_sprites + gg.num_fireballs + gg.num_plr_proj;
}

void PlayerDeath(FATCONFIG *fc)
{
	register FATSPRITE *sprite asm("4") = sprites;
	register SpriteStruct *sprite_data asm("a5") = sprites_extra;
	SpriteStruct *s = sprite_data;
	WeaponStruct *curweapon = &weapon;
	char i;
	register short x;
	register short y;
	register short orientation;
	int index;
	for (i = 0; i<MAX_NR_FIREBALLS; i++)
	{
		KillFireBall(fc,i);
	}
	
	fc->nr_sprites++;
	index = (fc->nr_sprites-1);
	
			FAT_SetHUD(NULL,NULL,NULL);
		  ClearFacePlane();
      UpdateFace(facedead);	
      UpdateStats();
      
      x = fc->cam_xpos;
      y = fc->cam_ypos;
      
      s[index].src = playerdeath;
      
      FAT_InitSprite(&sprite[index]);
      sprite[index].drawmode    = SPRITEMODE_SIZE64;
      sprite[index].nr_textures = 1;
    	sprite[index].textures = s[index].src;
    	sprite[index].xpos = (x);
      sprite[index].ypos = (y);
    	sprite[index].orientation = 0;
    	sprite[index].angle = 0;
      
      for (i = 0; i < 5; i++)
      {
      	PlayerMove(fc,0x0002,0,0);
      	FAT_Render(fc);
      }
      
      orientation = (FAT_GetArcTanYX(sprite[index].ypos - fc->cam_ypos ,sprite[index].xpos - fc->cam_xpos));
      
      while (!(fc->cam_orientation <= (orientation+ANGLE_015) && fc->cam_orientation >= (orientation-ANGLE_015)))
      {
      	if (fc->cam_orientation > orientation)
      	PlayerTurn(fc,0x0008,ANGLE_015); //turn right;
      	if (fc->cam_orientation < orientation)
      	PlayerTurn(fc,0x0008,ANGLE_015); //turn left;
      	FAT_Render(fc);
      }
      
      while (sprite[index].textures < s[index].src +3)
      {
      	sprite[index].textures++;
      	FAT_Render(fc);
      }
      
    //  FAT_AllKeysReleased();
    //  FAT_WaitKeyPressed();
     // FAT_AllKeysReleased();
      
     
      
      if (curweapon->type == PISTOL)
      FAT_SetLowerHUD(hud1_plane1+288,hud1_plane2+288,hud1mask+288);
      if (curweapon->type == SHOTGUN)
      FAT_SetLowerHUD(shotgun_hud1_plane1+288,shotgun_hud1_plane2+288,shotgunhud1mask+288);
      if (curweapon->type == RAILGUN)
      FAT_SetLowerHUD(railgun_hud1_plane1+288,railgun_hud1_plane2+288,railgunhud1mask+288);
      if (curweapon->type == FIST)
      FAT_SetLowerHUD(punch_hud1plane1+288,punch_hud1plane2+288,punch_hudmask1+288);
      if (curweapon->type == ROCKET_LAUNCHER)
      FAT_SetHUD(rocket_hud1plane1,rocket_hud1plane2,rocket_hud1mask);
      
      
      
      if (gg.lives > 0)
      {
      	gg.health = 100;
      	curweapon->ammo = 100;
      	gg.lives-=1;
      	gg.current_level -= 1;
      	SwitchLevel(fc,1,1);
      	UpdateStats();
      }
      else if (gg.lives <= 0)
      {
      	gg.current_level = (-1);
      	gg.health = 100;
      	curweapon->ammo = 100;
      	curweapon->shells = 0;
      	gg.lives = 5;
      	gg.shotgun = 0;
      	gg.railgun = 0;
      	SwitchLevel(fc,1,1);
      	UpdateStats();
      	FAT_SetLowerHUD(hud1_plane1+288,hud1_plane2+288,hud1mask+288);
      }
      	
}

void Darkness(FATCONFIG *fc,DEPTHDATA* dd) {
		short i;
    register const long val = 0xffffffffL;

    fc = fc; // just to make the compiler happy. otherwise it will complain
             // about the unused parameter fc
//0-100: nothing
//101-200: light
//201-300: dark
//301+: black
    for (i=0;i<ANGLE_060;i++) {
        if (dd->distance[i] < 101) continue;
        if (dd->distance[i] < 201) {
            dd->lightdata[i<<1]     = val;
            dd->lightdata[(i<<1)+1] = val;
        }
        else if (dd->distance[i] < 301) {
            dd->darkdata[i<<1]     = val;
            dd->darkdata[(i<<1)+1] = val;
        }
        else {
            dd->lightdata[i<<1]     = val;
            dd->lightdata[(i<<1)+1] = val;
            dd->darkdata[i<<1]      = val;
            dd->darkdata[(i<<1)+1]  = val;
        }
    }
}

void SetBackgroundImage(FATCONFIG *fc,unsigned short* background)
{
	 memset(bg_img,0,1152*2);

    dest = bg_img;

    for (i=0;i<6;i++) {
        unsigned short* src = background+i;
        for (j=0;j<96;j++,dest++,src+=6) {
            *dest = *src;
            *(dest+576) = *(src+576);
        }
    }
    fc->background = bg_img;
}

void SetBlackBackground(FATCONFIG *fc)
{
	memset(bg_img,0xFFFF,1152*2);
	fc->background = bg_img;
}

void RealityFlicker(void)
{
	char lightning;
	
	lightning = random(2);
	if (lightning == 1) 
	{
		FAT_SetPredrawCallback((void*)Darkness);
	}
	else
	{
		FAT_SetPredrawCallback(NULL);
	}
	lightning = random(2);
	if (lightning == 1)
	{
		GrayInvertRect(display_offsetx,display_offsety,96+display_offsetx,96+display_offsety);
	}
	
	
	
}

void ShowScrollingText(FATCONFIG *fc,int number)
{
	char a,b;
	FILE *fsPtr;
 //open he file in read mode
 	ClearGrayScreen();
 	char buffer[2] = " \0";
 	char check[2] = " \0";
 	short x = 1,y = 90;
 	FontSetSys(F_4x6);
  if (!(fsPtr = (fopen ("doomtext","r"))))
  PostGameCleanup(fc,ERR_TEXTFILE1);
  char scroll = 0;
  short wait = 0;
  
  switch (number)
  {
  	case 1:
  		check[0] = '1';
  	break;
  	case 2:
  		check[0] = '2';
  	break;
  	case 3:
  		check[0] = '3';
  	break;
  	case 4:
			check[0] = '4';
  	break;
  	case 5:
  		check[0] = '5';
  	break;
  	case 6:
			check[0] = '6';
  	break;
  	case 7:
			check[0] = '7';
  	break;
  	case 8:
 			check[0] = '8';
  	break;
  	case 9:
			check[0] = '@';
  	break;
  	case 10:
			check[0] = '#';
  	break;
  	case 11:
			check[0] = '*';
  	break;
  	case 12:
  		check[0] = '^';
  	break;
  	case 13:
  		check[0] = '(';
  	break;
  	case 14:
  		check[0] = ')';
  	break;
  	
  	default:
  	break;
  }
  
  while (buffer[0] != check[0])
  		{
  			buffer[0] = getc(fsPtr);
  		}

  
 while (buffer[0] != '%' && !_keytest(RR_ESC))
 {
 	
 	if (_keytest(RR_ENTER))
 	{
 	  FAT_AllKeysReleased();
 	  FAT_WaitKeyPressed();
 	  FAT_AllKeysReleased();	
 	}
 	
 	
 	// just to slow the processor down a bit. 
 	while (wait < 600)
 	{
 		a = random(30); 
 		b = random(40);
 		wait++;
 	}
 	wait = 0;
 		
 			buffer[0] = getc(fsPtr);
 			
 			if (buffer[0] != '\r' && buffer[0] != '<')
 			{
 				if (buffer[0] != '%' && buffer[0] != '1' 
 				 && buffer[0] != '2' && buffer[0] != '3'
 				 && buffer[0] != '4' && buffer[0] != '5')
 				{
 				DrawGrayStr(x+display_offsetx,y+display_offsety,buffer,A_NORMAL);
 				x+=4;	
 				}
 			}
 			else if (buffer[0] == '\r')
	 		{	
	 			if (display_offset == 0)
	 			{
	 				for (scroll = 0; scroll < 6; scroll++)
	 				{
 						ScrollUp160((GrayGetPlane(LIGHT_PLANE)),100);
 						ScrollUp160((GrayGetPlane(DARK_PLANE)),100);
	 				}
	 			}
	 			else
	 			{
	 				for (scroll = 0; scroll < 6; scroll++)
	 				{
 						ScrollUp240((GrayGetPlane(LIGHT_PLANE)),128);
 						ScrollUp240((GrayGetPlane(DARK_PLANE)),128);
	 				}
	 			}
	 			
 				x = 1;
 			}
 			else if (buffer[0] == '<')
 			{
 				Wait(50);
 			} 
 }
 
 Wait(115);
 fclose(fsPtr);
 
 return;
}

static inline void ShowMap(short xpos,short ypos)
{
		short x,y;
    short tilewidth  = 32;
    short vcount     = 3;
    short hcount     = 5;
    short i;
    if (!GrayOn()) return;
    memset(GetPlane(0),0,LCD_SIZE);
    memset(GetPlane(1),0,LCD_SIZE);
    FastFillScreen_R(GrayGetPlane(LIGHT_PLANE));
  	FastFillScreen_R(GrayGetPlane(DARK_PLANE));
    for (y=0;y<vcount;y++) {
        for (x=0;x<hcount;x++) { 
            short nr = y*hcount+x;
            for (i=0;i<2;i++) {
                Sprite32(x*tilewidth+(display_offsetx),y*tilewidth+(display_offsety),32,map_plane1+(nr*32),GrayGetPlane(LIGHT_PLANE),SPRT_AND);
                Sprite32(x*tilewidth+(display_offsetx),y*tilewidth+(display_offsety),32,map_plane2+(nr*32),GrayGetPlane(DARK_PLANE),SPRT_AND);
            }
        }
    }
    
    GrayUserDrawString8(xpos+display_offsetx,ypos+display_offsety,"YOU ARE");
    GrayUserDrawString8(xpos+8+display_offsetx,ypos+8+display_offsety,"HERE");
    Wait(75);
}

static inline void PreLevelSwitchTasks(FATCONFIG *fc)
{
	register int i;
    
 for (i = 0; i<MAX_NR_FIREBALLS; i++)
	{
		fireballs[i].in_use = SPRITE_FREE;
		fireballs[i].fbspr.textures = NULL;
		fireballs[i].fbspr.xpos = 1;
		fireballs[i].fbspr.ypos = 1;
		fireballs[i].fbspr.orientation = 0;
		fireballs[i].fbspr.drawmode = SPRITEMODE_UNUSED;
		fireballs[i].xpos = 1;
		fireballs[i].ypos = 1;
		fireballs[i].speed = 0;
		fireballs[i].orientation = 0;
		fireballs[i].src = NULL;
		fireballs[i].exploding = PROJ_NORMAL;
	}
	for (i = 0; i<MAX_NR_PLR_PROJECTILES; i++)
	{
		PlrProj[i].in_use = SPRITE_FREE;
		PlrProj[i].pjspr.textures = NULL;
		PlrProj[i].pjspr.xpos = 1;
		PlrProj[i].pjspr.ypos = 1;
		PlrProj[i].pjspr.orientation = 0;
		PlrProj[i].pjspr.drawmode = SPRITEMODE_UNUSED;
		PlrProj[i].xpos = 1;
		PlrProj[i].ypos = 1;
		PlrProj[i].speed = 0;
		PlrProj[i].orientation = 0;
		PlrProj[i].src = NULL;
		PlrProj[i].type = PROJ_UNUSED;
		PlrProj[i].exploding = PROJ_NORMAL;
	}
    
  for (i = 0; i<MAX_NR_FIREBALLS; i++)
	{
		KillFireBall(fc,i);
	}
	for (i = 0; i<MAX_NR_PLR_PROJECTILES; i++)
	{
		KillProjectile(fc,i);	
	}

}


static inline void ClearFacePlane(void)
{
	FastFilledRect_Erase_R(GrayGetPlane(LIGHT_PLANE),112+display_offsetx,58+display_offsety,144+display_offsetx,91+display_offsety);
	FastFilledRect_Erase_R(GrayGetPlane(DARK_PLANE),112+display_offsetx,58+display_offsety,144+display_offsetx,91+display_offsety);
}

static inline void UpdateFace(unsigned short* face)
{
GraySprite32_XOR(112+display_offsetx,60+display_offsety,32,(unsigned long*)face,(unsigned long*)face+32,GrayGetPlane(LIGHT_PLANE),GrayGetPlane(DARK_PLANE));
}

static inline void UpdateFaceTimer()
{
	if (timer == 1)
	{
		if (gg.health > 75)
		{
			ClearFacePlane();
			UpdateFace(lookright1);
		}
		if (gg.health >= 50 && gg.health < 75)
		{
			ClearFacePlane();
			UpdateFace(lookright2);
		}
		if (gg.health < 50)
		{
			ClearFacePlane();
			UpdateFace(lookright3);
		}
	}
	
	if (timer == 2)
	{
		if (gg.health > 75)
		{
			ClearFacePlane();
			UpdateFace(lookleft1);
		}
		if (gg.health >= 50 && gg.health < 75)
		{
			ClearFacePlane();
			UpdateFace(lookleft2);
		}
		if (gg.health < 50)
		{
			ClearFacePlane();
			UpdateFace(lookleft3);
		}	
	}
	timer++;
	if (timer >=3) timer = 0;
}


//=============================================================
// CODE curtosy of Malcolm Smith, edited by me.
//=============================================================
static inline void Fix3(char *buffer, short value)
{
    buffer[3] = 0;
    if(value == -1) strcpy(buffer,"---");
    else
    {
        buffer[2] = '0' + value % 10;
        buffer[1] = '0' + (value/10) % 10;
        buffer[0] = '0' + (value/100) % 10;
    }
}

static inline void InitGUI(void) {
	WeaponStruct *curweapon = &weapon;
  FontSetSys(F_4x6);
  			FastFillScreen_R(GrayGetPlane(LIGHT_PLANE));
  			FastFillScreen_R(GrayGetPlane(DARK_PLANE));
  			GraySprite32_AND(96+display_offsetx,1+display_offsety,32,(unsigned long*)titlehud1,(unsigned long*)titlehud1+32,GrayGetPlane(DARK_PLANE),GrayGetPlane(LIGHT_PLANE));
				GraySprite32_AND(128+display_offsetx,1+display_offsety,32,(unsigned long*)titlehud2,(unsigned long*)titlehud2+32,GrayGetPlane(DARK_PLANE),GrayGetPlane(LIGHT_PLANE));
  			GrayFastFillRect_R(GrayGetPlane(LIGHT_PLANE),GrayGetPlane(DARK_PLANE),96+display_offsetx,32+display_offsety,160+display_offsetx,100+display_offsety,0xFFFF);
  			GrayFastFillRect_R(GrayGetPlane(LIGHT_PLANE),GrayGetPlane(DARK_PLANE),108+display_offsetx,28+display_offsety,152+display_offsetx,56+display_offsety,0xFFFF);
  			FastOutlineRect(GrayGetPlane(LIGHT_PLANE),107+display_offsetx,30+display_offsety,150+display_offsetx,56+display_offsety,SPRT_XOR);
				DrawGrayStr(108+display_offsetx,32+display_offsety,"lives:",A_XOR);
				DrawGrayStr(108+display_offsetx,38+display_offsety,"health:",A_XOR);
				DrawGrayStr(108+display_offsetx,44+display_offsety,"bullets:",A_XOR);
				DrawGrayStr(108+display_offsetx,50+display_offsety,"shells:",A_XOR);
				DrawGrayStr(100+display_offsetx,42+display_offsety,"L",A_XOR);
				DrawGrayStr(100+display_offsetx,49+display_offsety,"E",A_XOR);
				DrawGrayStr(100+display_offsetx,56+display_offsety,"V",A_XOR);
				DrawGrayStr(100+display_offsetx,63+display_offsety,"E",A_XOR);
				DrawGrayStr(100+display_offsetx,70+display_offsety,"L",A_XOR);
				GrayUserDrawString8(104+display_offsetx,8+display_offsety,"DOOM 89");
				
								char buffer[3];
		Fix3(buffer,(gg.current_level+1));
				DrawGrayStr(98+display_offsetx,82+display_offsety,buffer,A_XOR);
		Fix3(buffer,gg.lives);
				DrawGrayStr(129+display_offsetx,32+display_offsety,buffer,A_XOR);
		Fix3(buffer,gg.health);
				DrawGrayStr(133+display_offsetx,38+display_offsety,buffer,A_XOR);
		Fix3(buffer,curweapon->ammo);
				DrawGrayStr(137+display_offsetx,44+display_offsety,buffer,A_XOR);
		Fix3(buffer,curweapon->shells);
				DrawGrayStr(133+display_offsetx,50+display_offsety,buffer,A_XOR);
		UpdateFaceTimer();
}


static inline void UnlockHandleOfMapFile()
{
		if (mapfile_handle) CloseFile("doamaps");
}

static inline void LockHandleOfMapFile(FATCONFIG *fc)
{
		if (!(mapfile_handle = OpenFile("doommaps")))
    {
    	PostGameCleanup(fc,ERR_MAPFILE);
   	}
 
}
    
static inline void SetupSpawnPoint(FATCONFIG *fc)
{
	short x,y;
	register char* map_data asm("a6") = fc->map_data;
	for (y=1; y<(fc->map_height-1); ++y) {
        for (x=1; x<(fc->map_width-1); ++x) {
           if (map_data[y*fc->map_width+x] == -128)
           {
           		fc->cam_xpos = (x*64)+32;
           		fc->cam_ypos = (y*64)+32;
           }
    	}
		}
}

void SaveDoors(short nr_doors)
{
	FATDOOR *src = FAT_GetDoorsArray();
	short i;
	for (i = 0; i < MAX_NR_DOORS; i++)
	{
		PartialDoors[i].state = DOOR_OPEN;
		PartialDoors[i].position = 0;
	}
	for (i = 0; i < nr_doors; i++,src++)
	{
		PartialDoors[i].state = src->state;
		PartialDoors[i].position = src->position;	
	}
}

void Save(FATCONFIG *fc)
{
 FAT_AllKeysReleased(); 
 SetupSwitchComps(fc);
 //define the file structure
 FILE *fsPtr;
 SYM_ENTRY *file;
 
 short nr_doors = FAT_GetNrDoors();
 
 SaveDoors(nr_doors);
 
 short size_level = 0;
 size_level = (fc->map_width * fc->map_height);

	char stnl = 0;
 
 if ((file = GetSymEntry("doomsave")))
 {
 	 if (file->flags.bits.archived == 1)
 	 EM_moveSymFromExtMem (SYMSTR("doomsave"),HS_NULL);
 }
 
 if (!(fsPtr = fopen("doomsave","w")))
 PostGameCleanup(fc,ERR_UNKNOWN);
 
 fwrite(&fc->cam_orientation,sizeof(short),1,fsPtr);
 fwrite(&fc->cam_xpos,sizeof(short),1,fsPtr);
 fwrite(&fc->cam_ypos,sizeof(short),1,fsPtr);
 fwrite(&weapon,sizeof(weapon),1,fsPtr);
 fwrite(&sprites,sizeof(sprites),1,fsPtr);
 fwrite(&sprites_extra,sizeof(sprites_extra),1,fsPtr);
 fwrite(&gg,sizeof(gameglobals),1,fsPtr);
 fwrite(&size_level,sizeof(short),1,fsPtr);
 fwrite(fc->map_data,size_level,1,fsPtr);
 fwrite(switchdoors1,sizeof(switchdoors1),1,fsPtr);
 fwrite(switchdoors2,sizeof(switchdoors2),1,fsPtr);
 fwrite(&nr_doors,sizeof(short),1,fsPtr);
 fwrite(PartialDoors,sizeof(PartialDoors),1,fsPtr);
 fwrite(doortimers,(sizeof(char)*MAX_NR_DOORS),1,fsPtr);
 fwrite(deadtimers,sizeof(deadtimers),1,fsPtr);
				  
 //close the file
 fclose(fsPtr);

try_archive:
stnl++;
 if (EM_findEmptySlot(sizeof(SymFind(SYMSTR ("doomsave")))))
 {
 	EM_moveSymToExtMem (SYMSTR("doomsave"),HS_NULL);
 }
 else
 {
 	UnlockTexFiles();
	EM_GC(FALSE);
	LoadTextures(fc);
	FixSpriteTex(fc);
	if (stnl >= 10) PostGameCleanup(fc,ERR_UNKNOWN);
	goto try_archive;
 }

}

static inline void FixSpriteTex(FATCONFIG *fc)
{
	int i;
	register FATSPRITE *sprite asm("4") = sprites;
	register SpriteStruct *sprite_data asm("a5") = sprites_extra;
	for (i = 0; i < fc->nr_sprites; i++)
	{
		switch (sprite_data[i].type)
		{
			case SP_CPOS:
				sprite_data[i].src = cpos;
				sprite[i].textures = sprite_data[i].src;
				if (sprite_data[i].life <= 0)
				{
				sprite_data[i].src = enemydeath+3;
				sprite[i].drawmode = SPRITEMODE_LOWER32;
				sprite[i].textures = sprite_data[i].src;
				}
			break;
			case SP_CYBORG:
				sprite_data[i].src = cyborg;
				sprite[i].textures = sprite_data[i].src;
				if (sprite_data[i].life <= 0)
				{
				sprite_data[i].src = enemydeath+3;
				sprite[i].drawmode = SPRITEMODE_LOWER32;
				sprite[i].textures = sprite_data[i].src;
				}
			break;
			case SP_ZOMBIE:
				sprite_data[i].src = zombie;
				sprite[i].textures = sprite_data[i].src;
				if (sprite_data[i].life <= 0)
				{
				sprite_data[i].src = enemydeath+3;
				sprite[i].drawmode = SPRITEMODE_LOWER32;
				sprite[i].textures = sprite_data[i].src;
				}
			break;
			case SP_BARREL:
				sprite_data[i].src = barrel;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_SHOTGUN:
				sprite_data[i].src = shotgun;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_RAILGUN:
				sprite_data[i].src = railgun;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_HEALTH_LARGE:
				sprite_data[i].src = healthlarge;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_HEALTH_SMALL:
				sprite_data[i].src = healthsmall;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_AMMOBOX:
				sprite_data[i].src = ammobox;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_SHOTGUN_SHELLS:
				sprite_data[i].src = shotgunshells;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_IMP:
				sprite_data[i].src = imp;
				sprite[i].textures = sprite_data[i].src;
				if (sprite_data[i].life <= 0)
				{
				sprite_data[i].src = enemydeath+3;
				sprite[i].drawmode = SPRITEMODE_LOWER32;
				sprite[i].textures = sprite_data[i].src;
				}
			break;
			case SP_TORCH:
				sprite_data[i].src = torch;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_YELLOW_KEY:
				sprite_data[i].src = yellowkey;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_BLUE_KEY:
				sprite_data[i].src = bluekey;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_COLUMN:
				sprite_data[i].src = column;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_TURBINE:
				sprite_data[i].src = turbine;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_BOSS:
				sprite_data[i].src = boss;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_SKULL_BOX:
				sprite_data[i].src = skullbox;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_PENDULUM:
				sprite_data[i].src = pendulum;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_FIRE:
				sprite_data[i].src = fire;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_SPIKES:
				sprite_data[i].src = spikes;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_VINES_1:
				sprite_data[i].src = vines;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_VINES_2:
				sprite_data[i].src = vines+1;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_VINES_3:
				sprite_data[i].src = vines+2;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_HOSTAGE:
				sprite_data[i].src = hostage;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_ARROWS:
				sprite_data[i].src = arrows;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_PLASMA_AMMO:
				sprite_data[i].src = plasmaammo;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_ROCKET_AMMO:
				sprite_data[i].src = rocketammo;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_ROCKET_LAUNCHER:
				sprite_data[i].src = rocketlauncher;
				sprite[i].textures = sprite_data[i].src;
			break;
			case SP_PLASMA_GUN:
				sprite_data[i].src = plasmagun;
				sprite[i].textures = sprite_data[i].src;
			break;
			default:
			break;
		}
	}
}

void CopyDoors(short nr_doors)
{
	FATDOOR *dest = FAT_GetDoorsArray();
	short i;
	for (i = 0; i < nr_doors; i++,dest++)
	{
		dest->state = PartialDoors[i].state;
		dest->position = PartialDoors[i].position;	
	}
}


int Load(FATCONFIG *fc)
{
 FAT_AllKeysReleased();
 //define the file structure
 FILE *fsPtr;
 FATDOOR* door;
 
 short size_level;
 short nr_doors;
 
 unsigned short *temp;
 
 size_level = 0;

	char stnl = 0;
	
 //open the file in read mode
if (!(fsPtr = fopen("doomsave","r")))
 return 0;

 fread(&fc->cam_orientation,sizeof(short),1,fsPtr);
 fread(&fc->cam_xpos,sizeof(short),1,fsPtr);
 fread(&fc->cam_ypos,sizeof(short),1,fsPtr);
 fread(&weapon,sizeof(weapon),1,fsPtr);
 fread(&sprites,sizeof(sprites),1,fsPtr);
 fread(&sprites_extra,sizeof(sprites_extra),1,fsPtr);
 fread(&gg,sizeof(gameglobals),1,fsPtr);
 fread(&size_level,sizeof(short),1,fsPtr);
 
 if (!(temp = (unsigned short*)malloc(size_level))) {
        fclose(fsPtr);
        PostGameCleanup(fc,ERR_MEMORY);
    }
 
 fread(temp,size_level,1,fsPtr);
 
 fread(switchdoors1,sizeof(switchdoors1),1,fsPtr);
 fread(switchdoors2,sizeof(switchdoors2),1,fsPtr);
 fread(&nr_doors,sizeof(short),1,fsPtr);
 fread(PartialDoors,sizeof(PartialDoors),1,fsPtr);
 fread(doortimers,(sizeof(char)*MAX_NR_DOORS),1,fsPtr);
 fread(deadtimers,sizeof(deadtimers),1,fsPtr);
   
 //close the file
 fclose(fsPtr);
 
 gg.current_level-=1;
 
if (gg.darkness == 1)
{
 	if (gg.AETC == TURN_OFF_SWITCHES && gg.number_switches_on <=0) gg.AETC = 0;
 	else if (gg.AETC == DESTROY_TURBINES && gg.number_turbines <= 0) gg.AETC = 0;
	else if (gg.AETC == DESTROY_COMPUTERS && gg.number_computers <= 0) gg.AETC = 0;

 		SetBlackBackground(fc);
		FAT_SetPredrawCallback(NULL);
		FAT_SetPredrawCallback((void*)Darkness);
}

fc->nr_sprites = gg.num_sprites;
gg.num_fireballs = 0;
gg.num_plr_proj = 0;

FixSpriteTex(fc); // reset pointers to textures.
SwitchLevel(fc,0,1); // bring us to the level we saved at. 
CopyDoors(nr_doors); // reload the previous doors stuff.
if (gg.switch_doors1) UpdateSwitchDoors(fc);
if (gg.switch_doors2) UpdateSwitchDoors2(fc);

memcpy(current_map,temp,size_level);
free(temp);

fc->map_data = (char*)(current_map);

if ((door = FAT_GetDoor((fc->cam_xpos/64),(fc->cam_ypos/64))))
door->state = DOOR_OPENING;

try_archive:
stnl++;
 if (EM_findEmptySlot(sizeof(SymFind(SYMSTR ("doomsave")))))
 {
 	EM_moveSymToExtMem (SYMSTR("doomsave"),HS_NULL);
 }
 else
 {
	UnlockTexFiles();
	EM_GC(FALSE);
	LoadTextures(fc);
	if (stnl >= 10) PostGameCleanup(fc,ERR_UNKNOWN);
	goto try_archive;
 }

return 1;
}

static void dissolve(void) {
	unsigned short  seq = 1;
	unsigned char   pixmask;
	unsigned short  byteoffset;

	do {
		pixmask    = seq & 0x7;
		byteoffset = seq >> 3;

        if (byteoffset < LCD_SIZE) {
            pixmask = 0x80 >> pixmask;

            //-------------------------------------
            // if pixel in plane1 is set, delete it
            // otherwise set it
            //-------------------------------------
        	if (*(unsigned char *)(GetPlane(LIGHT_PLANE)+byteoffset) & pixmask) {
          	    *(unsigned char *)(GetPlane(LIGHT_PLANE)+byteoffset) &= ~pixmask;
            }
        	else {
          	    *(unsigned char *)(GetPlane(LIGHT_PLANE)+byteoffset) |= pixmask;
            }

            //-------------------------------------
            // if pixel in plane2 is set, delete it
            // otherwise set it
            //-------------------------------------
        	if (*(unsigned char *)(GetPlane(DARK_PLANE)+byteoffset) & pixmask) {
          	    *(unsigned char *)(GetPlane(DARK_PLANE)+byteoffset) &= ~pixmask;
          	}
        	else {
          	    *(unsigned char *)(GetPlane(DARK_PLANE)+byteoffset) |= pixmask;
            }

        }

        if (seq & 1) seq = (seq>>1)^0x6000;
        else         seq = seq>>1;
    }
    while (seq != 1);
}

static inline void FindSwitchDoors(FATCONFIG *fc)
{
	register int idx1 = 0,idx2 = 0, i = 0;
	register short x,y;
	register char* map_data asm("a6") = fc->map_data;
	
	for (i = 0; i < MAX_NR_DOORS; i++)
	{
		switchdoors1[i][0] = 0;
		switchdoors1[i][1] = 0;
		switchdoors2[i][0] = 0;
		switchdoors2[i][1] = 0;
	}
	
	for (y=0; y<(fc->map_height-1); ++y) {
        for (x=0; x<(fc->map_width-1); ++x) {
        	if (map_data[y*fc->map_width+x] == -123)
            {
            	if (map_data[y*fc->map_width+(x-1)]>0)
            	{
            		map_data[y*fc->map_width+x] = map_data[y*fc->map_width+(x-1)];
            	}
            	else if (map_data[y*fc->map_width+(x+1)]>0)
            	{
            		map_data[y*fc->map_width+x] = map_data[y*fc->map_width+(x+1)];
            	}
            	else if (map_data[(y-1)*fc->map_width+(x)]>0)
            	{
            		map_data[y*fc->map_width+x] = map_data[(y-1)*fc->map_width+(x)];
            	}
            	else if (map_data[(y+1)*fc->map_width+(x)]>0)
            	{
            		map_data[y*fc->map_width+x] = map_data[(y+1)*fc->map_width+(x)];
            	}
            	switchdoors1[idx1][0] = x;
              switchdoors1[idx1][1] = y;
              idx1++;
            }
            
          if (map_data[y*fc->map_width+x] ==-124)
            {
            	if (map_data[y*fc->map_width+(x-1)]>0)
            	{
            		map_data[y*fc->map_width+x] = map_data[y*fc->map_width+(x-1)];
            	}
            	else if (map_data[y*fc->map_width+(x+1)]>0)
            	{
            		map_data[y*fc->map_width+x] = map_data[y*fc->map_width+(x+1)];
            	}
            	else if (map_data[(y-1)*fc->map_width+(x)]>0)
            	{
            		map_data[y*fc->map_width+x] = map_data[(y-1)*fc->map_width+(x)];
            	}
            	else if (map_data[(y+1)*fc->map_width+(x)]>0)
            	{
            		map_data[y*fc->map_width+x] = map_data[(y+1)*fc->map_width+(x)];
            	}
            	switchdoors2[idx2][0] = x;
              switchdoors2[idx2][1] = y;
              idx2++;
            }		
        }
      }
}

static inline void DrawOptionChoices()
{
	short fix_x = 0;
	short fix_y = 0;
	int idx,y_offset;

	if ((TI89))
	{
		fix_x = 2;
		fix_y = 12;
	}
	else
	{
		fix_x = 48;
		fix_y = 23;
	}
	 
	GrayDrawStr(6+fix_x,4+fix_y,"Auto Aim:",A_REPLACE);
	if (TI89)GrayFastFillRect_R(GrayGetPlane(LIGHT_PLANE),GrayGetPlane(DARK_PLANE),102,4+fix_y,102+54,4+fix_y+7,COLOR_BLACK);
	else GrayFastFillRect_R(GrayGetPlane(LIGHT_PLANE),GrayGetPlane(DARK_PLANE),148,4+fix_y,148+23,4+fix_y+7,COLOR_BLACK);
	GrayDrawStr(104+fix_x,4+fix_y,AutoAimStr[(short)gg.Auto_Aim],A_XOR);

	for (idx = 0,y_offset = 13; idx < 7; idx++,y_offset+=9)
	{
	  	GrayDrawStr(6+fix_x,y_offset+fix_y,OptionChoices[idx],A_REPLACE);
	  	  if (TI89) 
	  	  {
	  	  	GrayFastFillRect_R(GrayGetPlane(LIGHT_PLANE),GrayGetPlane(DARK_PLANE),102,y_offset+fix_y,102+54,y_offset+fix_y+7,COLOR_BLACK);
					GrayDrawStr(100+fix_x,y_offset+fix_y,Keys160.Keys[Controls.cur_keys[idx]],A_XOR);
				}
				else
				{
				  GrayFastFillRect_R(GrayGetPlane(LIGHT_PLANE),GrayGetPlane(DARK_PLANE),148,y_offset+fix_y,148+23,y_offset+fix_y+7,COLOR_BLACK);
					GrayDrawStr(100+fix_x,y_offset+fix_y,Keys240.Keys[Controls.cur_keys[idx]],A_XOR);
				}
	}
}


static inline short InvertOption(short y,short inv)
{
 
 if (TI89) GrayInvertRect2B(102,y,102+54,y+7,GrayDBufGetHiddenPlane(LIGHT_PLANE),GrayDBufGetHiddenPlane(DARK_PLANE));
 else GrayInvertRect2B(148,y,148+23,y+7,GrayDBufGetHiddenPlane(LIGHT_PLANE),GrayDBufGetHiddenPlane(DARK_PLANE));
	if (inv == 0)
		return 1;
	else
		return 0;
}

static inline void SetChoice (int choice, int field)
{
	switch((field))
	{
		case 0:
		  Controls.switch_weapon = ControlValue[choice];
			Controls.cur_keys[0] = choice;
		break;
		
		case 1:
		  Controls.shoot = ControlValue[choice];
			Controls.cur_keys[1] = choice;
		break;
		
		case 2:
			Controls.strafe = ControlValue[choice];
			Controls.cur_keys[2] = choice;
		break;
		
		case 3:
			Controls.run = ControlValue[choice];
			Controls.cur_keys[3] = choice;
		break;
		
		case 4:
			Controls.action = ControlValue[choice];
			Controls.cur_keys[4] = choice;	
		break;
		
		case 5:
			Controls.contrast_up = ControlValue[choice];
			Controls.cur_keys[5] = choice;
		break;
		
		case 6:
			Controls.contrast_dn = ControlValue[choice];
			Controls.cur_keys[6] = choice;
		break;
		
		default:
		break;
	}
}

static inline void CheckSameSet(int field, int forward)
{
	int i;
	int n;
	
	if (Controls.cont_choice >= 10 || Controls.cont_choice < 0) Controls.cont_choice = 0;
	
	  
			for (n = 0; n < 7; n++)
			{
				for (i = 0; i < 7; i++)
	  		{
					if ((Controls.cont_choice) == (Controls.cur_keys[i]))
					{
						if(forward)
						{
							if (Controls.cont_choice < 9) 
							{
								Controls.cont_choice++;
							}
							else
							{
								Controls.cont_choice = 0;
						 	 continue;
							}
						}
						else
						{
							if (Controls.cont_choice > 0) 
							{
								Controls.cont_choice--;
							}
							else
							{
								Controls.cont_choice = 9;
						 	  continue;
							}
						}
					}
				}
			}
			
	SetChoice(Controls.cont_choice,field);
}


void ShowOptions(FATCONFIG *fc)
{
	register short fix_x = 0;
	register short fix_y = 0;
	register short y = 4;
	register short inv = 0;
	int field;

	field = -1;
	
	ClearGrayScreen();
	FastFillScreen_R(GrayGetPlane(LIGHT_PLANE));
  FastFillScreen_R(GrayGetPlane(DARK_PLANE));

	if ((TI89))
	{
		fix_x = 102;
		fix_y = 16;
	}
	else
	{
		fix_x = 148;
		fix_y = 27;
	}
	
	FontSetSys(F_6x8);
	
	y = (fix_y);
	
	DrawOptionChoices();

	while (1)
	{
		Wait(6);
		inv = InvertOption(y,inv);
		if ((key = FAT_GetPadState())) {
			
			if (key & PADSTATE_RIGHT)
			{	 
				if (inv) inv = InvertOption(y,inv);
					if (field > -1)
					{
						Controls.cont_choice++;
							CheckSameSet(field,1);	
						DrawOptionChoices();
					}
					else
					{
						if (gg.Auto_Aim == 1) gg.Auto_Aim = 0;
						else gg.Auto_Aim = 1;
						DrawOptionChoices();
					}																
					
			}
			
			if (key & PADSTATE_LEFT)
			{	 
				if (inv) inv = InvertOption(y,inv);
					if (field > -1)
					{
						Controls.cont_choice--;
							CheckSameSet(field,0);	
						DrawOptionChoices();
					}
					else
					{
						if (gg.Auto_Aim == 1) gg.Auto_Aim = 0;
						else gg.Auto_Aim = 1;
						DrawOptionChoices();
					}										
			}
			
			if (key & PADSTATE_UP)
			{
				if (inv) inv = InvertOption(y,inv);
				if (y > (fix_y) && field > -1)
				{
					y -=9;
					field--;
					Controls.cont_choice = Controls.cur_keys[field];
				}
			}
			
			if (key & PADSTATE_DOWN)
			{
				if (inv) inv = InvertOption(y,inv);
				if (y < (54+9+fix_y) && field < 7)
				{
					y +=9;
					field++;	
					Controls.cont_choice = Controls.cur_keys[field];
				}	
			}
			
			if (key & PADSTATE_ESC)
			{
				FAT_AllKeysReleased();
				SaveConfig(fc);
				break;
			}
			
		}
	}
	FAT_AllKeysReleased();
	ClearGrayScreen();
}

static inline void ShowTitleScreen(void)
{
		short x,y;
    short tilewidth  = 32;
    short vcount     = 3;
    short hcount     = 5;
    short i;
    
    dissolve();
    
    if (!GrayOn()) return;
    memset(GetPlane(0),0,LCD_SIZE);
    memset(GetPlane(1),0,LCD_SIZE);
    FastFillScreen_R(GrayGetPlane(LIGHT_PLANE));
  	FastFillScreen_R(GrayGetPlane(DARK_PLANE));
    for (y=0;y<vcount;y++) {
        for (x=0;x<hcount;x++) { 
            short nr = y*hcount+x;
            for (i=0;i<2;i++) {
                Sprite32(x*tilewidth+(display_offsetx),y*tilewidth+(display_offsety),32,ztheta1+(nr*32),GrayGetPlane(LIGHT_PLANE),SPRT_AND);
                Sprite32(x*tilewidth+(display_offsetx),y*tilewidth+(display_offsety),32,ztheta2+(nr*32),GrayGetPlane(DARK_PLANE),SPRT_AND);
            }
        }
    }
    
    Wait(75);
    dissolve();
  	
    if (!GrayOn()) return;
    memset(GetPlane(0),0,LCD_SIZE);
    memset(GetPlane(1),0,LCD_SIZE);
    FastFillScreen_R(GrayGetPlane(LIGHT_PLANE));
  	FastFillScreen_R(GrayGetPlane(DARK_PLANE));
    for (y=0;y<vcount;y++) {
        for (x=0;x<hcount;x++) { 
            short nr = y*hcount+x;
            for (i=0;i<2;i++) {
                Sprite32(x*tilewidth+(display_offsetx),y*tilewidth+(display_offsety),32,titlescreen1+(nr*32),GrayGetPlane(LIGHT_PLANE),SPRT_AND);
                Sprite32(x*tilewidth+(display_offsetx),y*tilewidth+(display_offsety),32,titlescreen2+(nr*32),GrayGetPlane(DARK_PLANE),SPRT_AND);
            }
        }
    }
    
    Wait(75);
    dissolve();
    
}

static inline void ClearSmallRect(short x,short y)
{
	GrayFastFillRect_R(
    				GrayGetPlane(LIGHT_PLANE),
    				GrayGetPlane(DARK_PLANE),
    				x+display_offsetx,
    				y+display_offsety,
    				x+6+display_offsetx,
    				y+7+display_offsety,
    				0x0000);
}

static inline int ShowMenu(FATCONFIG *fc,char menunumber)
{
		
		unsigned char* pDoomFont;

	  // open and lock the font file
	   pDoomFont = OpenFile("doomfont");

	  // if the font file does not exist then exit
	  if (!pDoomFont)
		PostGameCleanup(fc,ERR_FONTFILE);

  	int skullx;
    int skully;
    if (!GrayOn()) return 0;
		int min;
		int max;
		char menu_choice = 1;
		
    
  if (menunumber == 1)
  {
		skullx = 32;
		skully = 28;
		SetUserFont(pDoomFont, &fontWidth[0], 8);
  	if (firstrun == 1)
  	{
  		min = 28;
  		max = 68;
  		ClearGrayScreen();
   	  GrayUserDrawString8(40+display_offsetx,28+display_offsety,"NEW GAME");
		  GrayUserDrawString8(40+display_offsetx,38+display_offsety,"LOAD GAME");
		  GrayUserDrawString8(40+display_offsetx,48+display_offsety,"SAVE GAME");
		  GrayUserDrawString8(40+display_offsetx,58+display_offsety,"END GAME");
		  GrayUserDrawString8(40+display_offsetx,68+display_offsety,"OPTIONS");
		  GrayUserDrawString8(skullx+display_offsetx,skully+display_offsety,"@"); //skull character;
  	}
  	else
  	{
  		ClearGrayScreen();
  		InitGUI();
  		FAT_Render(fc);
  		min = 16;
  		max = 56;
  		skullx = 2;
		  skully = 16;
		  GrayUserDrawString8(11+display_offsetx,16+display_offsety,"NEW GAME");
		  GrayUserDrawString8(11+display_offsetx,26+display_offsety,"LOAD GAME");
		  GrayUserDrawString8(11+display_offsetx,36+display_offsety,"SAVE GAME");
		  GrayUserDrawString8(11+display_offsetx,46+display_offsety,"END GAME");
		  GrayUserDrawString8(11+display_offsetx,56+display_offsety,"OPTIONS");
		  ClearSmallRect(skullx,skully);
		  ClearSmallRect(skullx,skully+10);
		  ClearSmallRect(skullx,skully+20);
		  ClearSmallRect(skullx,skully+30);
		  ClearSmallRect(skullx,skully+40);
		  GrayUserDrawString8(skullx+display_offsetx,skully+display_offsety,"@"); //skull character;
  	}
  	
		
    do
    {
    	if ((key = FAT_GetPadState()))
    	{
    		if (key & PADSTATE_UP && skully>min)
    		{
    			FAT_AllKeysReleased();
    			ClearSmallRect(skullx,skully);
    			skully -= 10;
    			if (menu_choice > 1) menu_choice--;
    			GrayUserDrawString8(skullx+display_offsetx,skully+display_offsety,"@"); //skull character;
    		}
    		if (key & PADSTATE_DOWN && skully<max)
    		{
    			FAT_AllKeysReleased();
    			ClearSmallRect(skullx,skully);
    			skully += 10;
    			if (menu_choice < 5) menu_choice++;
    			GrayUserDrawString8(skullx+display_offsetx,skully+display_offsety,"@"); //skull character;
    		}
    		if (key & Controls.shoot)
    		{
    			FAT_AllKeysReleased();
    			return (menu_choice);
    		}
    		if (key & PADSTATE_ESC)
    		{
    			FAT_AllKeysReleased();
    			return 0;
    		}
    	}
    }
    while (1);
  }
  
  if (menunumber == 2)
  {
  	skullx = 8;
  	skully = 28;
  	SetUserFont(pDoomFont, &fontWidth[0], 8);
  	if (firstrun == 1)
  	{
  		min = 28;
  		max = 58;
  		ClearGrayScreen();
   	  GrayUserDrawString8(16+display_offsetx,28+display_offsety,"I'M TOO YOUNG TO DIE!");
		  GrayUserDrawString8(16+display_offsetx,38+display_offsety,"HEY, NOT TOO ROUGH!");
		  GrayUserDrawString8(16+display_offsetx,48+display_offsety,"HURT ME PLENTY!");
		  GrayUserDrawString8(16+display_offsetx,58+display_offsety,"NIGHTMARE!!!");
		  GrayUserDrawString8(skullx+display_offsetx,skully+display_offsety,"@"); //skull character;
  	}
  	else
  	{
  		ClearGrayScreen();
  		InitGUI();
  		FAT_Render(fc);
  		min = 16;
  		max = 46;
  		skullx = 2;
		  skully = 16;
		  GrayUserDrawString8(11+display_offsetx,16+display_offsety,"I'M TOO YOUNG TO DIE!");
		  GrayUserDrawString8(11+display_offsetx,26+display_offsety,"HEY, NOT TOO ROUGH!");
		  GrayUserDrawString8(11+display_offsetx,36+display_offsety,"HURT ME PLENTY!");
		  GrayUserDrawString8(11+display_offsetx,46+display_offsety,"NIGHTMARE!!!");
		  ClearSmallRect(skullx,skully);
		  ClearSmallRect(skullx,skully+10);
		  ClearSmallRect(skullx,skully+20);
		  ClearSmallRect(skullx,skully+30);
		  GrayUserDrawString8(skullx+display_offsetx,skully+display_offsety,"@"); //skull character;  
  	}
    
    do
    {
    	if ((key = FAT_GetPadState()))
    	{
    		if (key & PADSTATE_UP && skully>min)
    		{
    			FAT_AllKeysReleased();
    			ClearSmallRect(skullx,skully);
    			skully -= 10;
    			if (menu_choice > 1) menu_choice--;
    			GrayUserDrawString8(skullx+display_offsetx,skully+display_offsety,"@"); //skull character;
    		}
    		if (key & PADSTATE_DOWN && skully<max)
    		{
    			FAT_AllKeysReleased();
    			ClearSmallRect(skullx,skully);
    			skully += 10;
    			if (menu_choice < 5) menu_choice++;
    			GrayUserDrawString8(skullx+display_offsetx,skully+display_offsety,"@"); //skull character;
    		}
    		if (key & Controls.shoot)
    		{
    			FAT_AllKeysReleased();
    		  return (menu_choice);
    		}
    		if (key & PADSTATE_ESC)
    		{
    			FAT_AllKeysReleased();
    			return 0;
    		}
    	}
    }
    while (1);
  }
  
  
  
  return 0;
}


void ShowMenus(FATCONFIG *fc)
{
	int result = 0;
show_menus_start:	
	result = ShowMenu(fc,1);
	switch (result)
	{
		case 1:
				result = ShowMenu(fc,2);
					switch (result)
					{
						case 1:
							if (firstrun == 1)
							{
							FAT_AllKeysReleased();
							gg.difficulty = 1;
							SwitchLevel(fc,1,1);	
							}
							else
							{
								FAT_AllKeysReleased();
								ClearGrayScreen();
    						InitGUI();
								gg.difficulty = 1;
								gg.current_level = (-1);
								ResetGameGlobals();
								SwitchLevel(fc,1,1);
							}
								firstrun = 0;
						break;
						case 2:
							if (firstrun == 1)
						  {
						  FAT_AllKeysReleased();
						  gg.difficulty = 2;
							SwitchLevel(fc,1,1);	
							}
							else
							{
								FAT_AllKeysReleased();
								ClearGrayScreen();
    						InitGUI();
								gg.difficulty = 2;
								gg.current_level = (-1);
								ResetGameGlobals();
								SwitchLevel(fc,1,1);
							}
								firstrun = 0;
						break;
						case 3:
							if (firstrun == 1)
							{
							FAT_AllKeysReleased();
							gg.difficulty = 3;
							SwitchLevel(fc,1,1);	
							}
							else
							{
								FAT_AllKeysReleased();
								ClearGrayScreen();
    						InitGUI();
								gg.difficulty = 3;
								gg.current_level = (-1);
								ResetGameGlobals();
								SwitchLevel(fc,1,1);
							}
								firstrun = 0;
						break;
						case 4:
							if (firstrun == 1)
							{
							FAT_AllKeysReleased();
							gg.difficulty = 4;
							SwitchLevel(fc,1,1);	
							}
							else
							{
								FAT_AllKeysReleased();
								ClearGrayScreen();
    						InitGUI();
								gg.difficulty = 4;
								gg.current_level = (-1);
								ResetGameGlobals();
								SwitchLevel(fc,1,1);
							}
								firstrun = 0;
						break;
						case 5:
							ShowOptions(fc);
							if (firstrun !=1)
							{
								FAT_AllKeysReleased();
								ClearGrayScreen();
								FAT_Render(fc);
								InitGUI();
								return;
							}
							else goto show_menus_start;
						break;
						case 0:
						goto show_menus_start;
						break;
						default:
						break;
					}
		break;
		case 2:
		FAT_AllKeysReleased();
		ClearGrayScreen();
    InitGUI();
			if (!(Load(fc)))
			goto show_menus_start;
		firstrun = 0;
		break;
		case 3:
		if (firstrun!=1)
		{
		FAT_AllKeysReleased();
		Save(fc);
		ClearGrayScreen();
    InitGUI();
		}
		else
		{
		 goto show_menus_start;
		}
		break;

    case 4:
			PostGameCleanup(fc,ERR_NORMAL_EXIT);
		break;
		
		case 5:
			ShowOptions(fc);
			if (firstrun !=1)
			{
			FAT_AllKeysReleased();
			ClearGrayScreen();
			FAT_Render(fc);
			InitGUI();
			return;
			}
			else goto show_menus_start;
		break;

		case 0:
		if (firstrun !=1)
		{
		FAT_AllKeysReleased();
		ClearGrayScreen();
		FAT_Render(fc);
		InitGUI();
		return;
		}
		else
		{
			PostGameCleanup(fc,ERR_NORMAL_EXIT);
		}
		break;
		default:
		break;
	}
	return;
}



static inline void LoadTextures(FATCONFIG *fc)
{
	
    //-------------------------------------------------------------------------
    // try to load the used textures from fatdtx ...
    //-------------------------------------------------------------------------
    if ((texfile1 = FAT_GetHandleOfFile("doomgfx1"))) {
        if ((src = FAT_LockHandleOfFile(texfile1))) {
        	 
        	  if (!FAT_LoadTextures(portal,src+2,TEXIDX_PORTAL1,3)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(textures+67,src+2,TEXIDX_DRAIN1,3)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(cpos,src+2,TEXIDX_CPOS1,4)) {
                src = 0; // just to indicate something went wrong
            }
             if (!FAT_LoadTextures(cyborg,src+2,TEXIDX_CYBORG1,4)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(zombie,src+2,TEXIDX_ZOMBIE1,4)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(enemydeath,src+2,TEXIDX_ENEMYDEATH1,4)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(barrel,src+2,TEXIDX_BARREL1,5)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(rocketammo,src+2,TEXIDX_ROCKETS,1)) {
                src = 0; // just to indicate something went wrong
            }
            if (!src || !(hud1_plane1=FAT_GetGenericData(src+2,GENIDX_HUDPLANE1,288))) {
                src = 0;
            }
             if (!src || !(hud1_plane2=FAT_GetGenericData(src+2,GENIDX_HUDPLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(hud1mask=FAT_GetGenericData(src+2,GENIDX_HUDMASK1,288))) {
                src = 0;
            }
            if (!src || !(hud2_plane1=FAT_GetGenericData(src+2,GENIDX_HUD2PLANE1,288))) {
                src = 0;
            }
             if (!src || !(hud2_plane2=FAT_GetGenericData(src+2,GENIDX_HUD2PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(hud2mask=FAT_GetGenericData(src+2,GENIDX_HUDMASK2,288))) {
                src = 0;
            }
            if (!src || !(hud3_plane1=FAT_GetGenericData(src+2,GENIDX_HUD3PLANE1,288))) {
                src = 0;
            }
             if (!src || !(hud3_plane2=FAT_GetGenericData(src+2,GENIDX_HUD3PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(hud3mask=FAT_GetGenericData(src+2,GENIDX_HUDMASK3,288))) {
                src = 0;
            }
            if (!src || !(map_plane1=FAT_GetGenericData(src+2,GENIDX_MAPPLANE1,480))) {
                src = 0;
            }
            if (!src || !(map_plane2=FAT_GetGenericData(src+2,GENIDX_MAPPLANE2,480))) {
                src = 0;
            }
            if (!src || !(youarehere=FAT_GetGenericData(src+2,GENIDX_YOUAREHERE,48))) {
                src = 0;
            }
            if (!src || !(rocket_hud1plane1=FAT_GetGenericData(src+2,GENIDX_ROCKETHUD1PLANE1,288))) {
                src = 0;
            }
            if (!src || !(rocket_hud1plane2=FAT_GetGenericData(src+2,GENIDX_ROCKETHUD1PLANE2,288))) {
                src = 0;
            }
            if (!src || !(rocket_hud1mask=FAT_GetGenericData(src+2,GENIDX_ROCKETHUD1MASK,288))) {
                src = 0;
            }
            if (!src || !(rocket_hud2plane1=FAT_GetGenericData(src+2,GENIDX_ROCKETHUD2PLANE1,288))) {
                src = 0;
            }
            if (!src || !(rocket_hud2plane2=FAT_GetGenericData(src+2,GENIDX_ROCKETHUD2PLANE2,288))) {
                src = 0;
            }
            if (!src || !(rocket_hud2mask=FAT_GetGenericData(src+2,GENIDX_ROCKETHUD2MASK,288))) {
                src = 0;
            }
            // load door texture
        }
    }
  
  if (!texfile1 || !src) {
        PostGameCleanup(fc,ERR_TEXFILE1);
    }
  
  if ((texfile2 = FAT_GetHandleOfFile("doomgfx2"))) {
        if ((src = FAT_LockHandleOfFile(texfile2))) {
        	
        	  if (!FAT_LoadTextures(arrows,src+2,TEXIDX_ARROWS1,3)) {
                src = 0; // just to indicate something went wrong
            }
  			  	if (!FAT_LoadTextures(textures,src+2,TEXIDX_COBBLESTONE,26)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(ammobox,src+2,TEXIDX_AMMOBOX,1)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(shotgunshells,src+2,TEXIDX_SHOTGUNSHELLS,1)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(healthlarge,src+2,TEXIDX_HEALTHLARGE,1)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(healthsmall,src+2,TEXIDX_HEALTHSMALL,1)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(imp,src+2,TEXIDX_IMP1,4)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(torch,src+2,TEXIDX_TORCH1,4)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(yellowkey,src+2,TEXIDX_YELLOWKEY,1)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(bluekey,src+2,TEXIDX_BLUEKEY,1)) {
                src = 0; // just to indicate something went wrong
            }
            if (!src || !(rocket_hud3plane1=FAT_GetGenericData(src+2,GENIDX_ROCKETHUD3PLANE1,288))) {
                src = 0;
            }
            if (!src || !(rocket_hud3plane2=FAT_GetGenericData(src+2,GENIDX_ROCKETHUD3PLANE2,288))) {
                src = 0;
            }
            if (!src || !(rocket_hud3mask=FAT_GetGenericData(src+2,GENIDX_ROCKETHUD3MASK,288))) {
                src = 0;
            }
            if (!src || !(rocket_hud4plane1=FAT_GetGenericData(src+2,GENIDX_ROCKETHUD4PLANE1,288))) {
                src = 0;
            }
            if (!src || !(rocket_hud4plane2=FAT_GetGenericData(src+2,GENIDX_ROCKETHUD4PLANE2,288))) {
                src = 0;
            }
            if (!src || !(rocket_hud4mask=FAT_GetGenericData(src+2,GENIDX_ROCKETHUD4MASK,288))) {
                src = 0;
            }
            if (!src || !(dark_background2=FAT_GetGenericData(src+2,GENIDX_BACKGROUND3,2304))) {
                src = 0;
            }
				}
		}
		
	
    //-------------------------------------------------------------------------
    // check if loading failed ...
    //-------------------------------------------------------------------------
    if (!texfile2 || !src) {
        PostGameCleanup(fc,ERR_TEXFILE2);
    }

    if ((texfile3 = FAT_GetHandleOfFile("doomgfx3"))) {
        if ((src = FAT_LockHandleOfFile(texfile3))) {
        	
          if (!FAT_LoadTextures(rocket,src+2,TEXIDX_ROCKET1,1)) {
                src = 0; // just to indicate something went wrong
            }
  				if (!FAT_LoadTextures(shotgun,src+2,TEXIDX_SHOTGUN,1)) {
                src = 0; // just to indicate something went wrong
            }
          if (!FAT_LoadTextures(railgun,src+2,TEXIDX_RAILGUN,1)) {
                src = 0; // just to indicate something went wrong
            }
           if (!FAT_LoadTextures(skullbox,src+2,TEXIDX_SKULLBOX1,4)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(fireball,src+2,TEXIDX_FIREBALL1,8)) {
                src = 0; // just to indicate something went wrong
            }
            	if (!FAT_LoadTextures(plasma,src+2,TEXIDX_PLASMA,1)) {
                src = 0; // just to indicate something went wrong
            }         
            if (!src || !(titlescreen1=FAT_GetGenericData(src+2,GENIDX_TITLESCREEN1,480))) {
                src = 0;
            }
            if (!src || !(titlescreen2=FAT_GetGenericData(src+2,GENIDX_TITLESCREEN2,480))) {
                src = 0;
            }
				if (!src || !(shotgun_hud1_plane1=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUDPLANE1,288))) {
                src = 0;
            }
             if (!src || !(shotgun_hud1_plane2=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUDPLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(shotgunhud1mask=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUDMASK1,288))) {
                src = 0;
            }
            
         if (!src || !(shotgun_hud2_plane1=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUD2PLANE1,288))) {
                src = 0;
            }
             if (!src || !(shotgun_hud2_plane2=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUD2PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(shotgunhud2mask=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUDMASK2,288))) {
                src = 0;
            }
            
         if (!src || !(shotgun_hud3_plane1=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUD3PLANE1,288))) {
                src = 0;
            }
             if (!src || !(shotgun_hud3_plane2=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUD3PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(shotgunhud3mask=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUDMASK3,288))) {
                src = 0;
            }
            
            if (!src || !(shotgun_hud4_plane1=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUD4PLANE1,288))) {
                src = 0;
            }
             if (!src || !(shotgun_hud4_plane2=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUD4PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(shotgunhud4mask=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUDMASK4,288))) {
                src = 0;
            }
            
            if (!src || !(railgun_hud1_plane1=FAT_GetGenericData(src+2,GENIDX_RAILGUNHUDPLANE1,288))) {
                src = 0;
            }
             if (!src || !(railgun_hud1_plane2=FAT_GetGenericData(src+2,GENIDX_RAILGUNHUDPLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(railgunhud1mask=FAT_GetGenericData(src+2,GENIDX_RAILGUNHUDMASK1,288))) {
                src = 0;
            }
            
         if (!src || !(railgun_hud2_plane1=FAT_GetGenericData(src+2,GENIDX_RAILGUNHUD2PLANE1,288))) {
                src = 0;
            }
             if (!src || !(railgun_hud2_plane2=FAT_GetGenericData(src+2,GENIDX_RAILGUNHUD2PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(railgunhud2mask=FAT_GetGenericData(src+2,GENIDX_RAILGUNHUDMASK2,288))) {
                src = 0;
            }
            
            if (!src || !(punch_hud1plane1=FAT_GetGenericData(src+2,GENIDX_PUNCHHUD1PLANE1,288))) {
                src = 0;
            }
             if (!src || !(punch_hud1plane2=FAT_GetGenericData(src+2,GENIDX_PUNCHHUD1PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(punch_hudmask1=FAT_GetGenericData(src+2,GENIDX_PUNCHHUDMASK1,288))) {
                src = 0;
            }
            
            if (!src || !(punch_hud2plane1=FAT_GetGenericData(src+2,GENIDX_PUNCHHUD2PLANE1,288))) {
                src = 0;
            }
             if (!src || !(punch_hud2plane2=FAT_GetGenericData(src+2,GENIDX_PUNCHHUD2PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(punch_hudmask2=FAT_GetGenericData(src+2,GENIDX_PUNCHHUDMASK2,288))) {
                src = 0;
            }
            
            if (!src || !(punch_hud3plane1=FAT_GetGenericData(src+2,GENIDX_PUNCHHUD3PLANE1,288))) {
                src = 0;
            }
             if (!src || !(punch_hud3plane2=FAT_GetGenericData(src+2,GENIDX_PUNCHHUD3PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(punch_hudmask3=FAT_GetGenericData(src+2,GENIDX_PUNCHHUDMASK3,288))) {
                src = 0;
            }
            
            if (!src || !(plasma_hud3plane1=FAT_GetGenericData(src+2,GENIDX_PLASMAHUD3PLANE1,288))) {
                src = 0;
            }
             if (!src || !(plasma_hud3plane2=FAT_GetGenericData(src+2,GENIDX_PLASMAHUD3PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(plasma_hud3mask=FAT_GetGenericData(src+2,GENIDX_PLASMAHUD3MASK,288))) {
                src = 0;
            }
            
          }  
		}
		
		if (!texfile3 || !src) {
        PostGameCleanup(fc,ERR_TEXFILE3);
    }
    
    if ((texfile4 = FAT_GetHandleOfFile("doomgfx4"))) {
        if ((src = FAT_LockHandleOfFile(texfile4))) {
        	
        	if (!FAT_LoadTextures(explosion,src+2,TEXIDX_EXPLOSION1,3)) {
                src = 0; // just to indicate something went wrong
            }
  				if (!FAT_LoadTextures(textures+26,src+2,TEXIDX_C1,30)) {
                src = 0; // just to indicate something went wrong
            }
          if (!FAT_LoadTextures(textures+59,src+2,TEXIDX_ROCKWALL,7)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(column,src+2,TEXIDX_COLUMN,1)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(rocketlauncher,src+2,TEXIDX_ROCKETLAUNCHER,1)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(textures+70,src+2,TEXIDX_SKIN1,5)) {
                src = 0; // just to indicate something went wrong
            }
            if (!src || !(facedead=FAT_GetGenericData(src+2,GENIDX_FACEDEAD,64))) {
                src = 0;
            }
            if (!src || !(facegrin=FAT_GetGenericData(src+2,GENIDX_FACEGRIN,64))) {
                src = 0;
            }
            if (!src || !(facegrinhurt1=FAT_GetGenericData(src+2,GENIDX_FACEGRINHURT1,64))) {
                src = 0;
            }
            if (!src || !(facegrinhurt2=FAT_GetGenericData(src+2,GENIDX_FACEGRINHURT2,64))) {
                src = 0;
            }
            if (!src || !(facepain1=FAT_GetGenericData(src+2,GENIDX_FACEPAIN1,64))) {
                src = 0;
            }
            if (!src || !(facepain2=FAT_GetGenericData(src+2,GENIDX_FACEPAIN2,64))) {
                src = 0;
            }
            if (!src || !(facepain3=FAT_GetGenericData(src+2,GENIDX_FACEPAIN3,64))) {
                src = 0;
            }
            if (!src || !(lookleft1=FAT_GetGenericData(src+2,GENIDX_LOOKLEFT1,64))) {
                src = 0;
            }
            if (!src || !(lookright1=FAT_GetGenericData(src+2,GENIDX_LOOKRIGHT1,64))) {
                src = 0;
            }
            if (!src || !(lookleft2=FAT_GetGenericData(src+2,GENIDX_LOOKLEFT2,64))) {
                src = 0;
            }
            if (!src || !(lookright2=FAT_GetGenericData(src+2,GENIDX_LOOKRIGHT2,64))) {
                src = 0;
            }
            if (!src || !(lookleft3=FAT_GetGenericData(src+2,GENIDX_LOOKLEFT3,64))) {
                src = 0;
            }
            if (!src || !(lookright3=FAT_GetGenericData(src+2,GENIDX_LOOKRIGHT3,64))) {
                src = 0;
            }
            if (!src || !(titlehud1=FAT_GetGenericData(src+2,GENIDX_TITLEHUD1,64))) {
                src = 0;
            }
            if (!src || !(titlehud2=FAT_GetGenericData(src+2,GENIDX_TITLEHUD2,64))) {
                src = 0;
            }
            
            if (!src || !(plasma_hud1plane1=FAT_GetGenericData(src+2,GENIDX_PLASMAHUD1PLANE1,288))) {
                src = 0;
            }
             if (!src || !(plasma_hud1plane2=FAT_GetGenericData(src+2,GENIDX_PLASMAHUD1PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(plasma_hud1mask=FAT_GetGenericData(src+2,GENIDX_PLASMAHUD1MASK,288))) {
                src = 0;
            }
            
            if (!src || !(plasma_hud2plane1=FAT_GetGenericData(src+2,GENIDX_PLASMAHUD2PLANE1,288))) {
                src = 0;
            }
             if (!src || !(plasma_hud2plane2=FAT_GetGenericData(src+2,GENIDX_PLASMAHUD2PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(plasma_hud2mask=FAT_GetGenericData(src+2,GENIDX_PLASMAHUD2MASK,288))) {
                src = 0;
            }
            
          }
    		}
    		
    if (!texfile4 || !src) {
        PostGameCleanup(fc,ERR_TEXFILE4);
    }

    if ((texfile5 = FAT_GetHandleOfFile("doomgfx5"))) {
        if ((src = FAT_LockHandleOfFile(texfile5))) {
        	
        		if (!FAT_LoadTextures(boss,src+2,TEXIDX_BOSS1,14)) {
                src = 0; // just to indicate something went wrong
            }
						if (!FAT_LoadTextures(turbine,src+2,TEXIDX_TURBINE1,2)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(cpos+4,src+2,TEXIDX_CPOSSHOOT1,2)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(cyborg+4,src+2,TEXIDX_CYBORGSHOOT1,2)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(imp+4,src+2,TEXIDX_IMPSHOOT1,2)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(zombie+4,src+2,TEXIDX_ZOMBIESHOOT1,2)) {
                src = 0; // just to indicate something went wrong
            }
        		if (!src || !(pistolhudmove1plane1=FAT_GetGenericData(src+2,GENIDX_PISTOLHUDMOVE1PLANE1,288))) {
                src = 0;
            }
             if (!src || !(pistolhudmove1plane2=FAT_GetGenericData(src+2,GENIDX_PISTOLHUDMOVE1PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(pistolhudmove1mask=FAT_GetGenericData(src+2,GENIDX_PISTOLHUDMOVE1MASK,288))) {
                src = 0;
            }
            	if (!src || !(pistolhudmove2plane1=FAT_GetGenericData(src+2,GENIDX_PISTOLHUDMOVE2PLANE1,288))) {
                src = 0;
            }
             if (!src || !(pistolhudmove2plane2=FAT_GetGenericData(src+2,GENIDX_PISTOLHUDMOVE2PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(pistolhudmove2mask=FAT_GetGenericData(src+2,GENIDX_PISTOLHUDMOVE2MASK,288))) {
                src = 0;
            }
            
            if (!src || !(shotgunhudmove1plane1=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUDMOVE1PLANE1,288))) {
                src = 0;
            }
             if (!src || !(shotgunhudmove1plane2=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUDMOVE1PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(shotgunhudmove1mask=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUDMOVE1MASK,288))) {
                src = 0;
            }
            	if (!src || !(shotgunhudmove2plane1=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUDMOVE2PLANE1,288))) {
                src = 0;
            }
             if (!src || !(shotgunhudmove2plane2=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUDMOVE2PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(shotgunhudmove2mask=FAT_GetGenericData(src+2,GENIDX_SHOTGUNHUDMOVE2MASK,288))) {
                src = 0;
            }
            
            if (!src || !(railgunhudmove1plane1=FAT_GetGenericData(src+2,GENIDX_RAILGUNHUDMOVE1PLANE1,288))) {
                src = 0;
            }
             if (!src || !(railgunhudmove1plane2=FAT_GetGenericData(src+2,GENIDX_RAILGUNHUDMOVE1PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(railgunhudmove1mask=FAT_GetGenericData(src+2,GENIDX_RAILGUNHUDMOVE1MASK,288))) {
                src = 0;
            }
            	if (!src || !(railgunhudmove2plane1=FAT_GetGenericData(src+2,GENIDX_RAILGUNHUDMOVE2PLANE1,288))) {
                src = 0;
            }
             if (!src || !(railgunhudmove2plane2=FAT_GetGenericData(src+2,GENIDX_RAILGUNHUDMOVE2PLANE2,288))) {
                src = 0;
            }
          	 if (!src || !(railgunhudmove2mask=FAT_GetGenericData(src+2,GENIDX_RAILGUNHUDMOVE2MASK,288))) {
                src = 0;
            }
            if (!src || !(background=FAT_GetGenericData(src+2,GENIDX_BACKGROUND,2304))) {
                src = 0;
            }
            if (!src || !(dark_background=FAT_GetGenericData(src+2,GENIDX_BACKGROUND2,2304))) {
                src = 0;
            }          
  			}
  	}
  	
  	if (!texfile5 || !src) {
        PostGameCleanup(fc,ERR_TEXFILE5);
    }

	if ((texfile6 = FAT_GetHandleOfFile("doomgfx6"))) {
        if ((src = FAT_LockHandleOfFile(texfile6))) {
        		
        		if (!FAT_LoadTextures(hostage,src+2,TEXIDX_CAPTAIN1,5)) {
                src = 0; // just to indicate something went wrong
            }
        		if (!FAT_LoadTextures(playerdeath,src+2,TEXIDX_DOOMGUY1,4)) {
                src = 0; // just to indicate something went wrong
            }
        		if (!FAT_LoadTextures(pendulum,src+2,TEXIDX_PENDULUM1,7)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(fire,src+2,TEXIDX_FIRE1,6)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(vines,src+2,TEXIDX_VINE1,3)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(spikes,src+2,TEXIDX_SPIKES1,5)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(textures+75,src+2,TEXIDX_SKULLWALL,9)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(plasmagun,src+2,TEXIDX_PLASMARIFLE,1)) {
                src = 0; // just to indicate something went wrong
            }
            if (!FAT_LoadTextures(plasmaammo,src+2,TEXIDX_PLASMAAMMO,1)) {
                src = 0; // just to indicate something went wrong
            }
            if (!src || !(ztheta1=FAT_GetGenericData(src+2,GENIDX_ZTHETA1,480))) {
                src = 0;
            }
            if (!src || !(ztheta2=FAT_GetGenericData(src+2,GENIDX_ZTHETA2,480))) {
                src = 0;
            }
         }
      }
            
            
    if (!texfile6 || !src) {
        PostGameCleanup(fc,ERR_TEXFILE6);
    }
    
    	if ((texfile7 = FAT_GetHandleOfFile("doomgfx7"))) {
        if ((src = FAT_LockHandleOfFile(texfile7))) {
        	
        	if (!FAT_LoadTextures(doomguyfront,src+2,TEXIDX_DOOMGUYRUN1,4)) {
                src = 0; // just to indicate something went wrong
            }
            
         if (!FAT_LoadTextures(doomguyback,src+2,TEXIDX_DOOMGUYBACKRUN1,4)) {
                src = 0; // just to indicate something went wrong
            }
            
         if (!FAT_LoadTextures(textures+84,src+2,TEXIDX_MOONTILE,2)) {
                src = 0; // just to indicate something went wrong
            }
       }
     }
        
        
    if (!texfile7 || !src) {
        PostGameCleanup(fc,ERR_TEXFILE7);
    }

}    

//=============================================================================
// add all doors defined in map
//=============================================================================

    
static inline void CreateDoors(FATCONFIG *fc,TEXCONFIG *textures) {
    short x, y, i, v, k;
    register char* map_data asm("a6") = fc->map_data;
    i = 0;
    v = 0;
    TEXCONFIG* tex_side = NULL;
    FAT_RemoveAllDoors();
    
    for (k = 0; k < MAX_NR_DOORS; k++)
    {
    	yellow_key_doors[k][0] = 0;
      yellow_key_doors[k][1] = 0;
      blue_key_doors[k][0] = 0;
      blue_key_doors[k][1] = 0;
    }
        
   for (y=1; y<(fc->map_height-1); y++) {
        for (x=1; x<(fc->map_width-1); x++) {
        	
        				if (map_data[y*fc->map_width+x] == 126)
            		{
		            	yellow_key_doors[i][0] = x;
		            	yellow_key_doors[i][1] = y;
		            	map_data[y*fc->map_width+x] = 127;
		            	i++;
		            }	
		          	else if (map_data[y*fc->map_width+x] == 125)
		            {
		            	blue_key_doors[v][0] = x;
		            	blue_key_doors[v][1] = y;
		            	map_data[y*fc->map_width+x] = 127;
		            	v++;            
		            }
        		
        			if (map_data[y*fc->map_width+(x-1)]>0)
            	{
            		tex_side = &textures[(map_data[y*fc->map_width+(x-1)])-1];
            	}
            	if (map_data[y*fc->map_width+(x+1)]>0)
            	{
            		tex_side = &textures[(map_data[y*fc->map_width+(x+1)])-1];
            	}
            	if (map_data[(y-1)*fc->map_width+(x)]>0)
            	{
            		tex_side = &textures[(map_data[(y-1)*fc->map_width+(x)])-1];
            	}
            	if (map_data[(y+1)*fc->map_width+(x)]>0)
            	{
            		tex_side = &textures[(map_data[(y+1)*fc->map_width+(x)])-1];
            	}
            int ran;
            if (map_data[y*fc->map_width+x] == 127) {
            	ran = random(3);
            	if (ran == 0)
            	{
            		 FAT_AddDoor(x, y, DOOR_HORIZONTAL, DOOR_CLOSED, 0,&textures[TEXIDX_QUAKE], tex_side, NULL);
            	}
            	else if (ran == 1)
            	{
            		 FAT_AddDoor(x, y, DOOR_HORIZONTAL, DOOR_CLOSED, 0,&textures[TEXIDX_YELLOWDOOR], tex_side, NULL);
            	}
            	else if (ran == 2)
            	{
            		 FAT_AddDoor(x, y, DOOR_HORIZONTAL, DOOR_CLOSED, 0,&textures[TEXIDX_BLUEDOOR], tex_side, NULL);
            	} 				  
            }
        }
    }
    
#if defined(FAT_USEDEBUG)
    y=0;
    FATDOOR* doors     = FAT_GetDoorsArray();
    short    doorcount = FAT_GetNrDoors();
    for (x=0,y=0;x<doorcount;x++,y+=5) {
        FAT_DebugUseSlot(y+0,"d.x",&(doors[x].xtile),FAT_DBG_SHORT_DEC);
        FAT_DebugUseSlot(y+1,"d.y",&(doors[x].ytile),FAT_DBG_SHORT_DEC);
        FAT_DebugUseSlot(y+2,"d.orient'n",&(doors[x].type),FAT_DBG_UCHAR_DEC);
        FAT_DebugUseSlot(y+3,"d.state",&(doors[x].state),FAT_DBG_UCHAR_DEC);
        FAT_DebugUseSlot(y+4,"d.position",&(doors[x].position),FAT_DBG_SHORT_DEC);
    }
#endif
}
    
static inline void InitiateSprite(FATSPRITE* sprites,int index,short x,short y)
{
	register FATSPRITE *sprite asm("4") = sprites;
	register SpriteStruct *sprite_data asm("a5") = sprites_extra;
	SpriteStruct *s = sprite_data;
	
										FAT_InitSprite(&sprite[index]);
   								  sprite[index].drawmode    = SPRITEMODE_SIZE64;
    								sprite[index].nr_textures = 1;
    								sprite[index].textures = s[index].src;
    								sprite[index].xpos = ((x*64)+32);
              		  sprite[index].ypos = ((y*64)+32);
    								sprite[index].orientation = 0;
    								sprite[index].angle = 0;
    								if ((s[index].staticsprite >= 2 && s[index].staticsprite <= 7 && s[index].staticsprite != 200) || s[index].staticsprite == -3)
    								sprite[index].drawmode = SPRITEMODE_LOWER32; 
	
}
		
    



static void PutSprites(FATCONFIG *fc,FATSPRITE *sprites,SpriteStruct *s)
{	
	gg.num_sprites = 0;
	fc->nr_sprites = 0;
	gg.number_skullboxes = 0;
	gg.number_enemies = 0;
	NumberHostages = 0;
	register short x, y, index = 0, value, i;
	register char* map_data asm("a6") = fc->map_data;
	
		for (i = 0; i<MAX_NR_LVL_SPRITES; i++)
		{
			s[i].type = 0;
			s[i].life = 0;
			s[i].moving = 0;
			s[i].speed = 0;
			s[i].src = NULL;
			s[i].staticsprite = 0;
			s[i].desire = 0;
			s[i].dead = DEAD;
		} 
	
    for (y=1; y<(fc->map_height-1); ++y) {
        for (x=1; x<(fc->map_width-1); ++x) {
        		for (value = 0; value > -37; value--)
        		{
        				if (map_data[y*fc->map_width+x] == value)
        				{
        				  if ((fc->nr_sprites < MAX_NR_LVL_SPRITES) && (index < MAX_NR_LVL_SPRITES))
										{
											switch ((abs(value)-1))
											{
												case 0:
													s[index].life = 5;
									 			  s[index].staticsprite = 0;
									  		  s[index].src = cpos;
									 				s[index].type = SP_CPOS;
									 				s[index].desire = INSTANT_HIT;
									 				s[index].dead = ALIVE;
									 				switch (gg.difficulty)
									 				{
									 					case 1:
									 						s[index].damage = 1;
									 					break;
									 					
									 					case 2:
									 						s[index].damage = 2;
											 			break;
									 				
									 					case 3:
									 						s[index].damage = 3;
									 					break;
									 			
											 			case 4:
											 				s[index].damage = 4;
											 			break;
											 			
											 			default:
											 			break;
											 		}
											 		fc->nr_sprites ++;
											 		InitiateSprite(sprites,index,x,y);
              				  	index++;
              				  	gg.number_enemies++;
												break;
										
												case 1:
														s[index].life = 20;
											 			s[index].staticsprite = 0;
											 			s[index].src = cyborg;
											 			s[index].type = SP_CYBORG;
											 			s[index].desire = INSTANT_HIT;
											 			s[index].dead = ALIVE;
											 			switch (gg.difficulty)
											 			{
											 				case 1:
											 					s[index].damage = 2;
											 				break;
									 			
											 				case 2:
											 					s[index].damage = 3;
											 				break;
									 			
											 				case 3:
											 					s[index].damage = 4;
											 				break;
									 			
											 				case 4:
											 					s[index].damage = 5;
											 				break;
									 			
											 				default:
											 				break;
											 			}
											 			fc->nr_sprites ++;
											 			InitiateSprite(sprites,index,x,y);
            		  		  		gg.number_enemies++;
            		  		  		index++;           		 			
												break;
										
												case 2:
														s[index].life = 4;
											 			s[index].staticsprite = 0;
											 			s[index].src = zombie;
											 			s[index].type = SP_ZOMBIE;
											 			s[index].desire = INSTANT_HIT;
											 			s[index].dead = ALIVE;
											 			switch (gg.difficulty)
											 			{
											 				case 1:
											 					s[index].damage = 1;
											 				break;
									 			
									 						case 2:
									 							s[index].damage = 2;
									 						break;
									 			
									 						case 3:
									 							s[index].damage = 3;
									 						break;
									 			
									 						case 4:
									 							s[index].damage = 4;
									 						break;
									 			
									 						default:
									 						break;
									 					}
									 					fc->nr_sprites ++;
									 					InitiateSprite(sprites,index,x,y);
              		  				gg.number_enemies++;
              		  				index++;
												break;
										
												case 3:
														s[index].life = 3;
									 					s[index].staticsprite = 1;
									 					s[index].src = barrel;
									 					s[index].dead = ALIVE;
									 					s[index].type = SP_BARREL;
									 					fc->nr_sprites ++;
									 					InitiateSprite(sprites,index,x,y);
              		  				index++;
												break;
										
												case 4:
														s[index].staticsprite = 2;
									 					s[index].src = shotgun;
									 					s[index].type = SP_SHOTGUN;
									 					fc->nr_sprites ++;
									 					InitiateSprite(sprites,index,x,y);
              		 			 		index++;
												break;
										
												case 5:
														s[index].staticsprite = 3;
									 					s[index].src = railgun;
									 					s[index].type = SP_RAILGUN;
									 					fc->nr_sprites ++;
									 					InitiateSprite(sprites,index,x,y);
              						  index++;
												break;
										
												case 6:
														s[index].staticsprite = 4;
									 					s[index].src = healthlarge;
									 					s[index].type = SP_HEALTH_LARGE;
									 					fc->nr_sprites ++;
									 					InitiateSprite(sprites,index,x,y);
              		 					index++;
												break;
										
												case 7:
														s[index].staticsprite = 5;
									 					s[index].src = healthsmall;
									 					s[index].type = SP_HEALTH_SMALL;
									 					fc->nr_sprites ++;
									 					InitiateSprite(sprites,index,x,y);
              		 				  index++;
												break;
										
												case 8:
														s[index].staticsprite = 6;
									 					s[index].src = ammobox;
									 					s[index].type = SP_AMMOBOX;
									 					fc->nr_sprites ++;
									 					InitiateSprite(sprites,index,x,y);
              				 		 index++;
              				 	break;
										
												case 9:
														s[index].staticsprite = 7;
									 					s[index].src = shotgunshells;
									 					s[index].type = SP_SHOTGUN_SHELLS;
									 					fc->nr_sprites ++;
									 					InitiateSprite(sprites,index,x,y);
              		 		  		index++;
												break;
										
												case 10:
														s[index].life = 3;
									 					s[index].staticsprite = 0;
									 					s[index].src = imp;
									 					s[index].type = SP_IMP;
									 					s[index].desire = THROW_FIREBALL;
									 					s[index].dead = ALIVE;
									 					switch (gg.difficulty)
									 					{
									 						case 1:
									 							s[index].damage = 1;
									 						break;
									 			
									 						case 2:
									 							s[index].damage = 2;
									 						break;
									 			
									 						case 3:
									 							s[index].damage = 3;
									 						break;
									 			
									 						case 4:
									 							s[index].damage = 4;
									 						break;
									 			
									 						default:
									 						break;
									 					}
									 					fc->nr_sprites ++;
									 					InitiateSprite(sprites,index,x,y);
              		 		  		index++;
              		 		  		gg.number_enemies++;
												break;
										
												case 11:
														s[index].staticsprite = 200;
									 					s[index].src = torch;
									 					s[index].type = SP_TORCH;
									 					fc->nr_sprites ++;
									 					InitiateSprite(sprites,index,x,y);
              		 				  index++;
												break;
										
												case 12:
														s[index].staticsprite = 8;
									 					s[index].src = yellowkey;
									 					s[index].type = SP_YELLOW_KEY;
									 					fc->nr_sprites ++;
									 					InitiateSprite(sprites,index,x,y);
              		 				  index++;
												break;
										
												case 13:
														s[index].staticsprite = 9;
									 					s[index].src = bluekey;
									 					s[index].type = SP_BLUE_KEY;
									 					fc->nr_sprites ++;
									 					InitiateSprite(sprites,index,x,y);
              		 		  		index++;
												break;
										
												case 14:
														s[index].staticsprite = 100;
									 					s[index].src = column;
									 					s[index].type = SP_COLUMN;
									 					fc->nr_sprites ++;
									 					InitiateSprite(sprites,index,x,y);
	              		 				index++;  	            		 		
												break;
										
												case 15:
														s[index].staticsprite = -1;
									 					s[index].src = turbine;
									 					s[index].life = 20;
									 					s[index].type = SP_TURBINE;
									 					fc->nr_sprites ++;
									 					gg.number_turbines++;
									 					InitiateSprite(sprites,index,x,y);
              		 		 		 index++;
 												break;
										
												case 16:
														s[index].staticsprite = -2;
									 					s[index].src = boss;
									 					s[index].life = 300;
									 					s[index].desire = INSTANT_HIT;
									 					s[index].type = SP_BOSS;
									 					fc->nr_sprites ++;
									 					gg.number_turbines++;
											 			InitiateSprite(sprites,index,x,y);
              				 		  index++;			
												break;
										
												case 17:
														s[index].staticsprite = -3;
									 					s[index].src = skullbox;
									 					s[index].type = SP_SKULL_BOX;
									 					fc->nr_sprites ++;
											 			gg.number_skullboxes++;
											 			InitiateSprite(sprites,index,x,y);
              				 		  index++;
 												break;
										
												case 18:
														s[index].staticsprite = -4;
														s[index].src = pendulum;
														s[index].type = SP_PENDULUM;
														s[index].desire = 1;
														fc->nr_sprites ++;
														InitiateSprite(sprites,index,x,y);
              						  index++;
												break;
										
												case 19:
														s[index].staticsprite = -5;
														s[index].src = fire;
														s[index].type = SP_FIRE;
														s[index].desire = 1;
														fc->nr_sprites ++;
														InitiateSprite(sprites,index,x,y);
              				  		index++;
												break;
										
												case 20:
														s[index].staticsprite = -6;
														s[index].src = spikes;
														s[index].type = SP_SPIKES;
														s[index].desire = 1;
														fc->nr_sprites ++;
														InitiateSprite(sprites,index,x,y);
              				  		index++;
												break;
										
												case 21:
														s[index].staticsprite = -7;
														s[index].src = vines;
														s[index].type = SP_VINES_1;
														fc->nr_sprites ++;
														InitiateSprite(sprites,index,x,y);
              				  		index++;           		 		  
												break;
										
												case 22:
														s[index].staticsprite = -8;
														s[index].src = vines+1;
														s[index].type = SP_VINES_2;
														fc->nr_sprites ++;
														InitiateSprite(sprites,index,x,y);
              				  		index++;
												break;
										
												case 23:
														s[index].staticsprite = -9;
														s[index].src = vines+2;
														s[index].type = SP_VINES_3;
														fc->nr_sprites ++;
														InitiateSprite(sprites,index,x,y);
              				  		index++;
												break;
										
												case 25:
														s[index].staticsprite = -11;
														s[index].src = hostage;
														s[index].type = SP_HOSTAGE;
														fc->nr_sprites ++;
														InitiateSprite(sprites,index,x,y);
														NumberHostages++;
              				  		index++;
												break;
										
												case 26:					
														s[index].staticsprite = -12;
														s[index].src = arrows;
														s[index].type = SP_ARROWS;
														fc->nr_sprites ++;
														InitiateSprite(sprites,index,x,y);												
              				  		index++;
												break;
										
												case 27:
														s[index].staticsprite = 13;
														s[index].src = plasmaammo;
														s[index].type = SP_PLASMA_AMMO;
														fc->nr_sprites ++;
														InitiateSprite(sprites,index,x,y);												
              				  		index++;
												break;
										
												case 28:
														s[index].staticsprite = 14;
														s[index].src = rocketammo;
														s[index].type = SP_ROCKET_AMMO;
														fc->nr_sprites ++;
														InitiateSprite(sprites,index,x,y);												
              				 		 index++;
												break;
										
												case 29:
														s[index].staticsprite = 15;
														s[index].src = rocketlauncher;
														s[index].type = SP_ROCKET_LAUNCHER;
														fc->nr_sprites ++;
														InitiateSprite(sprites,index,x,y);												
              						  index++;
												break;
										
												case 30:
														s[index].staticsprite = 16;
														s[index].src = plasmagun;
														s[index].type = SP_PLASMA_GUN;
														fc->nr_sprites ++;
														InitiateSprite(sprites,index,x,y);												
              						  index++;
												break;
										
												case 31:
														s[index].staticsprite = 17;
														s[index].src = explosion;
														s[index].type = SP_EXPLOSION;
														fc->nr_sprites ++;
														InitiateSprite(sprites,index,x,y);												
              				 		  index++;
												break;
										
												case 32:
												break;
										
												case 33:
														s[index].staticsprite = 18;
														s[index].src = doomguyfront;
														s[index].type = SP_DOOMGUY_FRONT;
														fc->nr_sprites ++;
														InitiateSprite(sprites,index,x,y);												
              				 		  index++;
												break;
										
												case 34:
														s[index].staticsprite = 19;
														s[index].src = doomguyback;
														s[index].type = SP_DOOMGUY_BACK;
														fc->nr_sprites ++;
														InitiateSprite(sprites,index,x,y);												
              				  		index++;
												break;
										
												case 35:
												break;
										
												default:
												break;
											}
										}
										else
	              		{
		              		 return;
		              	}
		          		}
		        	 }
		        }
		   }
		   
		   gg.num_sprites = fc->nr_sprites;
}

void AllocMapMem(FATCONFIG *fc)
{
	if (current_map) free(current_map);
	
	if (!(current_map = (unsigned short*)malloc((64*64))))
	{
		PostGameCleanup(fc,ERR_MEMORY);
	}
	memset(current_map,0,(64*64));
}

//=============================================================================
// CODE: help with this code was from several people on the TIGCC message boards.
// The code was originally written by Ranman from the Tifreakware message boards,
// and edited by me. 
//=============================================================================
static inline void LoadExternalLevel(int level, FATCONFIG *fc)
{
 int i;
 int mapSize;
 MapHeader *header;
 unsigned long headerAddress;
 // we assume that gg.ptr points to the very first map header
 // otherwise this algorithm will not work.
 header = (MapHeader*)(mapfile_handle); 

 headerAddress = (unsigned long)header;

 // find the level
 for (i = 0; i < level; i++)
 {
   // we must account for the entire map data
   mapSize = (header->xsize * header->ysize);

   // we must also account for the entire map header
   mapSize += sizeof(MapHeader);

   headerAddress += mapSize;

   header = (MapHeader*)headerAddress;
 }
 fc->map_width  = header->xsize;
 fc->map_height = header->ysize;
 memcpy(current_map,(((unsigned short*)header + sizeof(MapHeader))-1),(fc->map_width*fc->map_height));
 fc->map_data   = (char*)(current_map);
}

static inline void SetupSwitchComps(FATCONFIG *fc)
{
  short x,y;
  register char* map_data asm("a6") = fc->map_data;

	gg.number_switches_on = 0;
  gg.number_computers = 0;

    for (y=0; y<=(fc->map_height-1); ++y) {
        for (x=0; x<=(fc->map_width-1); ++x) {

			    if (map_data[y*fc->map_width+x] == (TEXIDX_COBBSWITCH2+1))
					{
					 		gg.number_switches_on += 1;
					}
					if (map_data[y*fc->map_width+x] == 57 || 
         	map_data[y*fc->map_width+x] == 58)
         	{
         	 		gg.number_computers += 1;
        	}
			
				}
			}

}

static void SwitchLevel(FATCONFIG *fc,char Spawn,char Dissolve) 
{
register short i;
register SpriteStruct *sprite_data asm("a5") = sprites_extra;
SetBackgroundImage(fc,background);
FAT_SetPredrawCallback(NULL);
FAT_SetPreHUDCallback(NULL);
motion_background = 0;
background_number = 0; 
SpriteStruct *s = sprite_data;
if (Dissolve) dissolve();

if (Spawn) gg.yellow_key = 0;
if (Spawn) gg.blue_key = 0;

if (Dissolve) FontSetSys(F_8x10);
if (Dissolve) GrayUserDrawString8(5+display_offsetx,50+display_offsety,"LOADING...");
if (Dissolve) FontSetSys(F_4x6);

if (firstrun!=1)
{
  PreLevelSwitchTasks(fc);
}
else
{
	for (i = 0; i<MAX_NR_FIREBALLS; i++)
	{
		fireballs[i].in_use = SPRITE_FREE;
		fireballs[i].fbspr.textures = NULL;
		fireballs[i].fbspr.xpos = 1;
		fireballs[i].fbspr.ypos = 1;
		fireballs[i].fbspr.orientation = 0;
		fireballs[i].fbspr.drawmode = SPRITEMODE_UNUSED;
		fireballs[i].xpos = 1;
		fireballs[i].ypos = 1;
		fireballs[i].speed = 0;
		fireballs[i].orientation = 0;
		fireballs[i].src = NULL;
		fireballs[i].exploding = PROJ_NORMAL;
	}
	for (i = 0; i<MAX_NR_PLR_PROJECTILES; i++)
	{
		PlrProj[i].in_use = SPRITE_FREE;
		PlrProj[i].pjspr.textures = NULL;
		PlrProj[i].pjspr.xpos = 1;
		PlrProj[i].pjspr.ypos = 1;
		PlrProj[i].pjspr.orientation = 0;
		PlrProj[i].pjspr.drawmode = SPRITEMODE_UNUSED;
		PlrProj[i].xpos = 1;
		PlrProj[i].ypos = 1;
		PlrProj[i].speed = 0;
		PlrProj[i].orientation = 0;
		PlrProj[i].src = NULL;
		PlrProj[i].type = PROJ_UNUSED;
		PlrProj[i].exploding = PROJ_NORMAL;
	}
}

DarkTile.darkness = 0;

if (Spawn) gg.darkness = 0;

gg.current_level++;
if (gg.current_level > 34) gg.current_level = 0;
LoadExternalLevel(gg.current_level,fc);
if (Spawn) PutSprites(fc,sprites,s);
if (Spawn) SetupSpawnPoint(fc);
if (Spawn) gg.switch_doors1 = 0;
if (Spawn) gg.switch_doors2 = 0;
if (Dissolve && Spawn) FindSwitchDoors(fc);
CreateDoors(fc,textures);
SetupSwitchComps(fc);
if (Dissolve) dissolve();
if (Dissolve) InitGUI();
if (Dissolve) UpdateStats();

// current level values are one less than actual level value.
	switch (gg.current_level)
	{
		case 0:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_SOUTH;
		if (Spawn) ShowMap(69,77);
		if (Spawn) ShowScrollingText(fc,1);
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 1:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_SOUTH;
		break;
		
		case 2:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_EAST;
		break;
		
		case 3:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_EAST;
		break;
		
		case 4:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_SOUTH;
		break;
		
		case 5:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_WEST;
		if (Spawn) ShowMap(49,62);
		if (Spawn) ShowScrollingText(fc,2);
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 6:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_NORTH;
		break;
		
		case 7:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_EAST;
		break;
		
		case 8:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_WEST;
		break;
		
		case 9:
		if (Spawn) fc->cam_orientation = ANGLE_EAST;
		MessageEnqueue(4);
		if (Spawn) gg.AETC = DESTROY_ENEMIES;
		if (Spawn) ShowMap(16,54);
		if (Spawn) ShowScrollingText(fc,3);
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 10:
		if (Spawn) fc->cam_orientation = ANGLE_SOUTH;
		MessageEnqueue(4);
		if (Spawn) gg.AETC = DESTROY_ENEMIES;
		break;
		
		case 11:
		if (Spawn) fc->cam_orientation = ANGLE_SOUTH;
		MessageEnqueue(4);
		if (Spawn) gg.AETC = DESTROY_ENEMIES;
		break;
		
		case 12:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_EAST;
		break;
		
		case 13:
		if (Spawn) fc->cam_orientation = ANGLE_NORTH;
		MessageEnqueue(5);
		if (Spawn) gg.AETC = TURN_OFF_SWITCHES;
		if (Spawn) ShowScrollingText(fc,4);
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 14:
		gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_SOUTH;
		break;
		
		case 15:
		if (Spawn) fc->cam_orientation = ANGLE_EAST;
		MessageEnqueue(6);
		if (Spawn) gg.AETC = DESTROY_TURBINES;
		if (Spawn) ShowScrollingText(fc,5);
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 16:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_NORTH;
		break;
		
		case 17:
		if (Spawn) fc->cam_orientation = ANGLE_NORTH;
		MessageEnqueue(7);
		if (Spawn) gg.AETC = FIND_BOXES;
		if (Spawn) ShowMap(36,36);
		if (Spawn) ShowScrollingText(fc,6);
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 18:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_WEST;
		if (Spawn) ShowScrollingText(fc,7);
		SetBlackBackground(fc);
		FAT_SetPredrawCallback((void*)Darkness);
		gg.darkness = 1;
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 19:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_WEST;
		break;
		
		case 20:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_EAST;
		if (Spawn) ShowScrollingText(fc,8);
		SetBlackBackground(fc);
		FAT_SetPredrawCallback((void*)Darkness);
		gg.darkness = 1;
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 21:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_EAST;
		SetBlackBackground(fc);
		FAT_SetPredrawCallback((void*)Darkness);
		gg.darkness = 1;
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 22:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_NORTH;
		SetBlackBackground(fc);
		FAT_SetPredrawCallback((void*)Darkness);
		gg.darkness = 1;
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 23:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_EAST;
		SetBlackBackground(fc);
		FAT_SetPredrawCallback((void*)Darkness);
		gg.darkness = 1;
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 24:
		if (Spawn) gg.AETC = DESTROY_COMPUTERS;
		MessageEnqueue(8);
		if (Spawn) fc->cam_orientation = ANGLE_SOUTH;
		if (Spawn) ShowScrollingText(fc,9);
		ClearGrayScreen();
		InitGUI();
		FAT_SetPreHUDCallback((void*)RealityFlicker);
		break;
		
		case 25:
		if (Spawn) gg.AETC = FREE_HOSTAGES;
		MessageEnqueue(9);
		if (Spawn) fc->cam_orientation = ANGLE_SOUTH;
		if (Spawn) ShowScrollingText(fc,10);
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 26:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_SOUTH;
		if (Spawn) ShowMap(17,9);
		if (Spawn) ShowScrollingText(fc,11);
		FindSpecialTile(fc);
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 27:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		if (Spawn) fc->cam_orientation = ANGLE_EAST;
		if (Spawn) ShowScrollingText(fc,12);
		FindSpecialTile(fc);
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 28:
		SetBackgroundImage(fc,dark_background);
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		motion_background = 1;
		background_number = 0;
		if (Spawn) fc->cam_orientation = ANGLE_SOUTH;
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 29:
		SetBackgroundImage(fc,dark_background);
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		motion_background = 1;
		background_number = 0;
		if (Spawn) ShowMap(72,16);
		if (Spawn) fc->cam_orientation = ANGLE_SOUTH;
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 30:
		SetBackgroundImage(fc,dark_background);
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		motion_background = 1;
		background_number = 0;
		if (Spawn) fc->cam_orientation = ANGLE_SOUTH;
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 31:
		SetBackgroundImage(fc,background);
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		motion_background = 0;
		background_number = 0;
		if (Spawn) ShowMap(95,40);
		if (Spawn) fc->cam_orientation = ANGLE_SOUTH;
		if (Spawn) ShowScrollingText(fc,13);
		ClearGrayScreen();
		InitGUI();
		break;
		
		case 32:
		SetBackgroundImage(fc,background);
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		motion_background = 0;
		background_number = 0;
		if (Spawn) fc->cam_orientation = ANGLE_NORTH;
		break;
		
		case 33:
		SetBackgroundImage(fc,background);
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		motion_background = 0;
		background_number = 0;
		if (Spawn) fc->cam_orientation = ANGLE_SOUTH;
		break;
		
		case 34:
		SetBlackBackground(fc);
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		motion_background = 0;
		background_number = 0;
		if (Spawn) fc->cam_orientation = ANGLE_NORTH;
		break;
		
		default:
		if (Spawn) gg.AETC = NORMAL_LEVEL;
		break;
	}
}

static inline void UpdateDamage(FATCONFIG *fc,register int index)
{
	register SpriteStruct *sprite_data asm("a5") = sprites_extra;
	
 		gg.health -= sprite_data[index].damage;	
                         	
   if (gg.health <= 0)
    {
      PlayerDeath(fc);	
    }
   UpdateStats();
   if (gg.health > 75)
	 {
		ClearFacePlane();
		UpdateFace(facepain1);
	 }
	if (gg.health >= 50 && gg.health < 75)
	{
	ClearFacePlane();
	UpdateFace(facepain2);
	}
	if (gg.health < 50)
	{
	ClearFacePlane();
	UpdateFace(facepain3);
	}	                          
}

