/* MTL Stuff*/
/*#include "gam/mtl/mtl.h"*/
 
#if defined(WIN32)
#include <direct.h>
#include <io.h>
#endif /* WIN32 */
 
#include "FIL_CPA.h"
 
#define D_FIL_StructureDefine
 
#include "ErmFil.h"
 
#include "FIL_Pub.h"
#include "FIL_Priv.h"
 
/* dlassonde - 2 Sep 1998*/
/* Global handle to avoid repeated allocations and deallocations*/
FIL_tdxHandleToFileInConcatFile FIL_g_hHandleToFileInConcatFile = NULL; 
/*extern int FIL_fn_iOpenFileInConcatFile(FIL_tdxHandleToConcatFile hConcatFile,char *p_szPath,char *p_szFilename, FIL_tdxHandleToFileInConcatFile hHandleToFile);*/
 
#include"FIL_Conc.h"
 
/**************************************************************************/
void FIL_fn_vSaveGFInFile
(
	char				*p_szFileName,
	unsigned char		ucNumberOfBytesInSource,
	FIL_tdstGF			*_p_stSrcGF
	)
{
	unsigned long       ulCodeNumber[256];
	unsigned long       i,j;
	FILE                *p_stFile;
	struct FIL_tdstGF_  stGF;
	long                c;
	unsigned char       ucCodeNumber;
	
	stGF.stFileHeader.ucRLECode          = 0;
	stGF.stFileHeader.ulWidth            = _p_stSrcGF->stFileHeader.ulWidth;
	stGF.stFileHeader.ulHeight           = _p_stSrcGF->stFileHeader.ulHeight;
	stGF.stFileHeader.ucBpp				 = _p_stSrcGF->stFileHeader.ucBpp;
	stGF.stFileHeader.uwNbColorInPalette = _p_stSrcGF->stFileHeader.uwNbColorInPalette;
	stGF.stFileHeader.ucBpcInPalette	 = _p_stSrcGF->stFileHeader.ucBpcInPalette;
	stGF.p_ucPalette						= _p_stSrcGF->p_ucPalette;
	stGF.stFileHeader.ucRed					= _p_stSrcGF->stFileHeader.ucRed;
	stGF.stFileHeader.ucGreen			  = _p_stSrcGF->stFileHeader.ucGreen;
	stGF.stFileHeader.ucBlue			  = _p_stSrcGF->stFileHeader.ucBlue;
	stGF.stFileHeader.lChromakeyIndex	  = _p_stSrcGF->stFileHeader.lChromakeyIndex;
	stGF.stFileHeader.ulImageSize		  = _p_stSrcGF->stFileHeader.ulImageSize;
	stGF.stFileHeader.ucFormat			  = _p_stSrcGF->stFileHeader.ucFormat;
	stGF.stFileHeader.ucVersion		  = GF_VERSION;
	
	
	/**** Copy the picture for processing ****/
	stGF.p_ucBitMap  = (unsigned char *) TMP_M_p_Malloc( _p_stSrcGF->stFileHeader.ulImageSize * ucNumberOfBytesInSource );
	memcpy( stGF.p_ucBitMap, _p_stSrcGF->p_ucBitMap, _p_stSrcGF->stFileHeader.ulImageSize * ucNumberOfBytesInSource );
	
	/**** Search for the useless bytes ****/
	memset( ulCodeNumber, 0, 256 * 4 );
	for( i=0; i < ucNumberOfBytesInSource * _p_stSrcGF->stFileHeader.ulImageSize; i++ )
	{
		/*   ulCodeNumber[ p_ucSource[i] ]++;*/
		ulCodeNumber[ _p_stSrcGF->p_ucBitMap[i] ]++;
	}
	
	for( i=0; i < 256; i++ )
	{
		if( ulCodeNumber[i] < ulCodeNumber[stGF.stFileHeader.ucRLECode] )
		{
			stGF.stFileHeader.ucRLECode = (unsigned char) i;
		}
	}
	
	/**** Save file ****/
	FIL_fn_bValidatePath("",p_szFileName);
	if( (p_stFile = fopen(p_szFileName,"wb")) !=NULL )
	{
		/* write header*/
		fwrite( &stGF.stFileHeader, 
			sizeof(struct FIL_tdstFileHeader_), 
			1, 
			p_stFile );
		
		/* write palette, if one*/
		
		if( stGF.stFileHeader.uwNbColorInPalette != 0  &&  
			stGF.stFileHeader.ucBpcInPalette != 0 )
		{
			fwrite( stGF.p_ucPalette,
				stGF.stFileHeader.ucBpcInPalette,
				stGF.stFileHeader.uwNbColorInPalette,
				p_stFile );
		}
		
		for( c=0; c < _p_stSrcGF->stFileHeader.ucBpp; c++ )
		{
			for( i=0; i <_p_stSrcGF->stFileHeader.ulImageSize; )
			{
				/**** If byte is RLECode ****/
				if( stGF.p_ucBitMap[i*_p_stSrcGF->stFileHeader.ucBpp+c] == stGF.stFileHeader.ucRLECode )
				{
					if( i < _p_stSrcGF->stFileHeader.ulImageSize - 1 )
					{
						for( j=1; 
						j < 256 
							&& i + j < _p_stSrcGF->stFileHeader.ulImageSize 
							&& stGF.p_ucBitMap[ (i + j) * _p_stSrcGF->stFileHeader.ucBpp + c ] == 
							stGF.p_ucBitMap[( i + j - 1) * _p_stSrcGF->stFileHeader.ucBpp + c];
						j++)
						{
							/* do nothing */
						}
						
						if( j == 256  ||  i + j == _p_stSrcGF->stFileHeader.ulImageSize )
						{
							j--;
						}
						
						ucCodeNumber = (unsigned char) j;
						fwrite( &stGF.stFileHeader.ucRLECode, sizeof(unsigned char), 1, p_stFile );
						fwrite( &stGF.p_ucBitMap[ i * _p_stSrcGF->stFileHeader.ucBpp + c], sizeof(unsigned char), 1, p_stFile );
						fwrite( &ucCodeNumber, sizeof(unsigned char), 1, p_stFile );
						i += ucCodeNumber;
					}
					else
					{
						ucCodeNumber = 1;
						fwrite( &stGF.stFileHeader.ucRLECode, sizeof(unsigned char), 1, p_stFile );
						fwrite( &stGF.p_ucBitMap[ i * _p_stSrcGF->stFileHeader.ucBpp + c], sizeof(unsigned char), 1, p_stFile );
						fwrite( &ucCodeNumber, sizeof(unsigned char), 1, p_stFile );
						i += ucCodeNumber;
					}
				}
				else
				{
					/**** If byte number is not 4 above the end ****/
					if (i<_p_stSrcGF->stFileHeader.ulImageSize-4)
					{
						if (  stGF.p_ucBitMap[i*_p_stSrcGF->stFileHeader.ucBpp+c]==stGF.p_ucBitMap[(i+1)*_p_stSrcGF->stFileHeader.ucBpp+c]
							&&stGF.p_ucBitMap[i*_p_stSrcGF->stFileHeader.ucBpp+c]==stGF.p_ucBitMap[(i+2)*_p_stSrcGF->stFileHeader.ucBpp+c]
							&&stGF.p_ucBitMap[i*_p_stSrcGF->stFileHeader.ucBpp+c]==stGF.p_ucBitMap[(i+3)*_p_stSrcGF->stFileHeader.ucBpp+c])
						{
							for (j=1;stGF.p_ucBitMap[(i+j)*_p_stSrcGF->stFileHeader.ucBpp+c]==stGF.p_ucBitMap[(i+j-1)*_p_stSrcGF->stFileHeader.ucBpp+c]&&j<256&&i+j<_p_stSrcGF->stFileHeader.ulImageSize;j++);
							if (j==256)
								j--;
							if (i+j==_p_stSrcGF->stFileHeader.ulImageSize)
								j--;
							ucCodeNumber = (unsigned char)j;
							fwrite(&stGF.stFileHeader.ucRLECode,sizeof(unsigned char),1,p_stFile);
							fwrite(&stGF.p_ucBitMap[i*_p_stSrcGF->stFileHeader.ucBpp+c],sizeof(unsigned char),1,p_stFile);
							fwrite(&ucCodeNumber,sizeof(unsigned char),1,p_stFile);
							i+=ucCodeNumber;
						}
						else
						{
							fwrite(&stGF.p_ucBitMap[i*_p_stSrcGF->stFileHeader.ucBpp+c],sizeof(unsigned char),1,p_stFile);
							i++;
						}
					}
					else
					{
						fwrite(&stGF.p_ucBitMap[i*_p_stSrcGF->stFileHeader.ucBpp+c],sizeof(unsigned char),1,p_stFile);
						i++;
					}
				}
				
			}
		}
		fclose(p_stFile);
	}
	
	TMP_M_Free(stGF.p_ucBitMap);
}
 
 
/**************************************************************************/
void FIL_fn_vLoadGFInformationFromFile(
									   char					*p_szPath,
									   char					*p_szFileName,
									   ACP_tdxBool			*p_bTextureInPalette,
									   struct FIL_tdstGF_	*_p_stGF
									   )
{
	FILE						*p_stFile;
	char						szCompleteName[_MAX_PATH];
	struct FIL_tdstFileHeader_ *p_stGFHeader = &(_p_stGF -> stFileHeader);
	
	sprintf(szCompleteName,"%s\\%s",p_szPath,p_szFileName);
	
	p_stGFHeader->ucBpp	 = 0;
	p_stGFHeader->ulWidth    = 0;
	p_stGFHeader->ulHeight   = 0;
	*p_bTextureInPalette     = 0;
	
	
	if( (p_stFile = fopen(szCompleteName,"rb")) != NULL )
	{
		fread(p_stGFHeader,sizeof(struct FIL_tdstFileHeader_),1,p_stFile);
		
		*p_bTextureInPalette = (ACP_tdxBool)( p_stGFHeader->uwNbColorInPalette != 0 );
		
		if(p_stGFHeader->ucVersion != GF_VERSION)
		{
			char ErrorMessage[60];
			sprintf(ErrorMessage,"File is Version: %d, Expected version: %d",p_stGFHeader->ucVersion, GF_VERSION);
			M_FILFatalErrorWithMessage(E_uwFILInvalidGFVersion, ErrorMessage);
		}
		if(p_stGFHeader->lChromakeyIndex == 0xffffffff)
		{
			p_stGFHeader->ucRed   = 0;
			p_stGFHeader->ucGreen = 0;
			p_stGFHeader->ucBlue  = 0;
		}
		
		fclose(p_stFile);
	}
}
 
 
/**************************************************************************/
void FIL_fn_vLoadGFFromFileWithInvertPicture(
											 char					*p_szPath,
											 char					*p_szFileName,
											 struct FIL_tdstGF_	*_p_stGF)
{
	struct FIL_tdstFileHeader_ *p_stGFHeader = &(_p_stGF -> stFileHeader);
	
	FIL_fn_vLoadGFFromFileWithoutInvertPicture(
		p_szPath,
		p_szFileName,
		_p_stGF);
	
	if (_p_stGF->p_ucBitMap!=NULL)
	{
		FIL_fn_vInvertGF(_p_stGF->p_ucBitMap, p_stGFHeader->ucBpp, p_stGFHeader->ulWidth, p_stGFHeader->ulHeight);
	}
}
 
 
/**************************************************************************/
void FIL_fn_vLoadGFFromFileWithoutInvertPicture(
												char					*p_szPath,
												char					*p_szFileName,
												struct FIL_tdstGF_	*_p_stGF)
{
	FILE						*p_stFile;
	char						szCompleteName[_MAX_PATH];
	unsigned long				c,i,j;
	unsigned char				ucCode;
	unsigned char				ucColor;
	unsigned char				ucNumber;
	struct FIL_tdstFileHeader_ *p_stGFHeader = &(_p_stGF -> stFileHeader);
    /*VLHorror*/
    FIL_tdstRealGFFileHeader    stGFRealHeader;
    /*EVL*/
	
	sprintf(szCompleteName,"%s\\%s",p_szPath,p_szFileName);
	
	/* set default values */
    memset( _p_stGF, 0, sizeof( FIL_tdstGF ) );
	p_stGFHeader->ucFormat	= 0xff;
	
	if( (p_stFile = fopen(szCompleteName,"rb")) != NULL )
	{
        /*VLHorror*/
		/* read file header*/
		/*fread( p_stGFHeader, sizeof(struct FIL_tdstFileHeader_), 1, p_stFile );*/
        fread( &stGFRealHeader, sizeof( FIL_tdstRealGFFileHeader ), 1, p_stFile );
        p_stGFHeader->ulWidth       = stGFRealHeader.ulWidth;
        p_stGFHeader->ulHeight      = stGFRealHeader.ulHeight;
        p_stGFHeader->ulImageSize   = stGFRealHeader.ulWidth * stGFRealHeader.ulHeight;
        p_stGFHeader->ucBpp         = stGFRealHeader.ucBpp;
        p_stGFHeader->ucRLECode     = stGFRealHeader.ucRLECode;
        p_stGFHeader->ucVersion     = GF_VERSION;
        if (p_stGFHeader->ucBpp == 1)
        {
            p_stGFHeader->uwNbColorInPalette = 256;
            p_stGFHeader->ucBpcInPalette     = 4;
        }
        /*EVL*/
		
		/* set return values*/
		if(p_stGFHeader->ucVersion != GF_VERSION)
		{
			char ErrorMessage[60];
			sprintf(ErrorMessage,"File is Version: %d, Expected version: %d",p_stGFHeader->ucVersion, GF_VERSION);
			M_FILFatalErrorWithMessage(E_uwFILInvalidGFVersion, ErrorMessage);
		}
		
		if(p_stGFHeader->lChromakeyIndex == 0xffffffff)
		{
			p_stGFHeader->ucRed   = 0;
			p_stGFHeader->ucGreen = 0;
			p_stGFHeader->ucBlue  = 0;
		}
		
		
		_p_stGF->p_ucBitMap  = (unsigned char *) TMP_M_p_Malloc( p_stGFHeader->ulImageSize * p_stGFHeader->ucBpp );
		
		if( p_stGFHeader->uwNbColorInPalette != 0  &&  p_stGFHeader->ucBpcInPalette != 0 )
		{
			_p_stGF->p_ucPalette = (unsigned char *) TMP_M_p_Malloc( p_stGFHeader->uwNbColorInPalette * p_stGFHeader->ucBpcInPalette );
			fread( _p_stGF->p_ucPalette, p_stGFHeader->ucBpcInPalette, p_stGFHeader->uwNbColorInPalette, p_stFile );
		}
		
		
		for( c=0; c < p_stGFHeader->ucBpp; c++ )
		{
			for( i=0; i < p_stGFHeader->ulImageSize; ) 
			{
				fread(&ucCode,sizeof(unsigned char),1,p_stFile);
				
				if( ucCode == p_stGFHeader->ucRLECode )
				{
					fread( &ucColor,  sizeof(unsigned char), 1, p_stFile );
					fread( &ucNumber, sizeof(unsigned char), 1, p_stFile );
					
					for( j=0; j < ucNumber; j++ )
					{
						_p_stGF->p_ucBitMap[ (i + j) * (p_stGFHeader->ucBpp) + c ] = ucColor;
					}
					
					i += ucNumber;
				}
				else
				{
					_p_stGF->p_ucBitMap[i * p_stGFHeader->ucBpp + c] = ucCode;
					i++;
				}
			}
		}
		fclose(p_stFile);
	}
}
 
 
/**************************************************************************/
/* dlassonde - 2 Sep 1998 */
/* I renamed the function Old because the optimized one is just below and */
/*	if the file wanted is not in the big file, it will call the old function*/
/* to load it*/
void FIL_fn_vOldLoadGFInformationFromConcatFile( 
												FIL_tdxHandleToConcatFile  hConcatFile,
												char                       *p_szPath,
												char                       *p_szFileName,
												ACP_tdxBool                *p_bTextureInPalette,
												struct FIL_tdstGF_		 *_p_stGF)
{
	FIL_tdxHandleToFileInConcatFile hHandleToFile;
	struct FIL_tdstFileHeader_		*p_stGFHeader = &(_p_stGF -> stFileHeader);
	/*VLHorror*/
    FIL_tdstRealGFFileHeader    stGFRealHeader;
    /*EVL*/
	
	p_stGFHeader->ucBpp = 0;
	p_stGFHeader->ulWidth  = 0;
	p_stGFHeader->ulHeight = 0;
	*p_bTextureInPalette = FALSE;
	
	if( (hHandleToFile = FIL_fn_hOpenFileInConcatFile(hConcatFile,p_szPath,p_szFileName)) != NULL )
	{
        /*VLHorror*/
		/* read file header*/
		/*FIL_fn_lReadFileInConcatFile(p_stGFHeader,sizeof(struct FIL_tdstFileHeader_),1,hHandleToFile);*/
        FIL_fn_lReadFileInConcatFile( &stGFRealHeader, sizeof( FIL_tdstRealGFFileHeader ), 1, hHandleToFile );
        p_stGFHeader->ulWidth       = stGFRealHeader.ulWidth;
        p_stGFHeader->ulHeight      = stGFRealHeader.ulHeight;
        p_stGFHeader->ulImageSize   = stGFRealHeader.ulWidth * stGFRealHeader.ulHeight;
        p_stGFHeader->ucBpp         = stGFRealHeader.ucBpp;
        p_stGFHeader->ucRLECode     = stGFRealHeader.ucRLECode;
        p_stGFHeader->ucVersion     = GF_VERSION;
        if (p_stGFHeader->ucBpp == 1)
        {
            p_stGFHeader->uwNbColorInPalette = 256;
            p_stGFHeader->ucBpcInPalette     = 4;
        }
        /*EVL*/
				
		*p_bTextureInPalette = (ACP_tdxBool)( p_stGFHeader->uwNbColorInPalette!= 0 );
		FIL_fn_vCloseFileInConcatFile(&hHandleToFile);
		
		if(p_stGFHeader->ucVersion != GF_VERSION)
		{
			char ErrorMessage[60];
			sprintf(ErrorMessage,"File is Version: %d, Expected version: %d",p_stGFHeader->ucVersion, GF_VERSION);
			M_FILFatalErrorWithMessage(E_uwFILInvalidGFVersion, ErrorMessage);
		}
		
		
		if(p_stGFHeader->lChromakeyIndex == 0xffffffff)
		{
			p_stGFHeader->ucRed   = 0;
			p_stGFHeader->ucGreen = 0;
			p_stGFHeader->ucBlue  = 0;
		}
		
		
	}
	
}
 
/*------------------------------------------------------------------------*/
/**/
/* Author			David Lassonde*/
/* Date				2 Sep 1998*/
/* */
/* Prototype		FIL_fn_vLoadGFInformationFromConcatFile*/
/* Parameters		hConcatFile : */
/*					p_szPath : */
/*					p_szFileName : */
/*					p_ucNumberOfBytesInDest : */
/*					p_ulWidth : */
/*					p_ulHeight : */
/*					p_bTextureInPalette : */
/* Return Type		void*/
/* */
/* Description		*/
 
/*	The same as the function above but the file handle is not allocated each time*/
/* a file is read from the big file... We use a global handle instead*/
/* */
/*------------------------------------------------------------------------*/
void FIL_fn_vLoadGFInformationFromConcatFile
    (
        FIL_tdxHandleToConcatFile  hConcatFile,
		char                       *p_szPath,
		char                       *p_szFileName,
		ACP_tdxBool                *p_bTextureInPalette,
		struct FIL_tdstGF_			*_p_stGF
    )
{
	struct FIL_tdstFileHeader_		*p_stGFHeader = &(_p_stGF -> stFileHeader);
    /*VLHorror*/
    FIL_tdstRealGFFileHeader    stGFRealHeader;
    /*EVL*/
	
	*p_bTextureInPalette = FALSE;
	p_stGFHeader->uwNbColorInPalette	= 0;
	p_stGFHeader->ulWidth				= 0;
	p_stGFHeader->ulHeight              = 0;
	p_stGFHeader->ucBpp					= 0;
	p_stGFHeader->ucBpcInPalette		= 0;
	p_stGFHeader->ulImageSize			= 0;
	p_stGFHeader->ucFormat				= 0xff;
	
	/* if the global handle is not valid, call the old function*/
	if (FIL_g_hHandleToFileInConcatFile == NULL || hConcatFile == NULL)
	{
		FIL_fn_vOldLoadGFInformationFromConcatFile(hConcatFile, 
			p_szPath, 
			p_szFileName, 
			p_bTextureInPalette,
			_p_stGF);
		return;
	}
	
	/* let the handle point to the right big file*/
	FIL_g_hHandleToFileInConcatFile->p_stFile = hConcatFile->p_stFile;
    	
	if (FIL_fn_iOpenFileInConcatFile(hConcatFile,p_szPath,p_szFileName, FIL_g_hHandleToFileInConcatFile ) == -1)
	{
		/* if the file is not in the big file, we use the old function...*/
		FIL_fn_vOldLoadGFInformationFromConcatFile(hConcatFile, 
			p_szPath, 
			p_szFileName, 
			p_bTextureInPalette,
			_p_stGF);
		
		return;
	}
	
    /*VLHorror*/
	/* read file header*/
	/*FIL_fn_lReadFileInConcatFile(p_stGFHeader,sizeof(struct FIL_tdstFileHeader_),1,FIL_g_hHandleToFileInConcatFile );*/
    FIL_fn_lReadFileInConcatFile( &stGFRealHeader, sizeof( FIL_tdstRealGFFileHeader ), 1, FIL_g_hHandleToFileInConcatFile );
    p_stGFHeader->ulWidth       = stGFRealHeader.ulWidth;
    p_stGFHeader->ulHeight      = stGFRealHeader.ulHeight;
    p_stGFHeader->ulImageSize   = stGFRealHeader.ulWidth * stGFRealHeader.ulHeight;
    p_stGFHeader->ucBpp         = stGFRealHeader.ucBpp;
    p_stGFHeader->ucRLECode     = stGFRealHeader.ucRLECode;
    p_stGFHeader->ucVersion     = GF_VERSION;
    if (p_stGFHeader->ucBpp == 1)
    {
        p_stGFHeader->uwNbColorInPalette = 256;
        p_stGFHeader->ucBpcInPalette     = 4;
    }
    /*EVL*/
	
	*p_bTextureInPalette = (ACP_tdxBool)( p_stGFHeader->uwNbColorInPalette != 0 );
	
	if(p_stGFHeader->ucVersion != GF_VERSION)
	{
		char ErrorMessage[60];
		sprintf(ErrorMessage,"File is Version: %d, Expected version: %d",p_stGFHeader->ucVersion, GF_VERSION);
		M_FILFatalErrorWithMessage(E_uwFILInvalidGFVersion, ErrorMessage);
	}
	
	
	/* we reset the cache...*/
	FIL_g_hHandleToFileInConcatFile->ulCacheCheckSum = 0;
	FIL_g_hHandleToFileInConcatFile->ulCacheSize = FIL_C_MaxConcatCacheSize;
	FIL_g_hHandleToFileInConcatFile->ulCacheSeek = FIL_g_hHandleToFileInConcatFile ->ulCacheSize;
	
    if(p_stGFHeader->lChromakeyIndex == 0xffffffff)
	{
		p_stGFHeader->ucRed   = 0;
		p_stGFHeader->ucGreen = 0;
		p_stGFHeader->ucBlue  = 0;
    }
}
 
/**************************************************************************/
void FIL_fn_vLoadGFFromConcatFileWithInvertPicture(
												   FIL_tdxHandleToConcatFile hConcatFile,
												   char						*p_szPath,
												   char						*p_szFileName,
												   struct FIL_tdstGF_		*_p_stGF)
{
	struct FIL_tdstFileHeader_ *p_stGFHeader = &(_p_stGF -> stFileHeader);
	
	FIL_fn_vLoadGFFromConcatFileWithoutInvertPicture(
		hConcatFile,
		p_szPath,
		p_szFileName,
		_p_stGF);
	
	if(_p_stGF->p_ucBitMap!=NULL)
	{
		FIL_fn_vInvertGF(_p_stGF->p_ucBitMap, p_stGFHeader->ucBpp, p_stGFHeader->ulWidth, p_stGFHeader->ulHeight);
	}
}
 
 
/**************************************************************************/
void FIL_fn_vLoadGFFromConcatFileWithoutInvertPicture(
													  FIL_tdxHandleToConcatFile  hConcatFile,
													  char                       *p_szPath,
													  char                       *p_szFileName,
													  struct FIL_tdstGF_		 *_p_stGF)
{
	FIL_tdxHandleToFileInConcatFile	hHandleToFile;
	unsigned long						c,i,j;
	unsigned char						ucCode;
	unsigned char						ucColor;
	unsigned char						ucNumber;
	struct FIL_tdstFileHeader_			*p_stGFHeader = &(_p_stGF -> stFileHeader);
    /*VLHorror*/
    FIL_tdstRealGFFileHeader    stGFRealHeader;
    /*EVL*/
 
	
	/* set default values*/
	_p_stGF->p_ucBitMap      = NULL;
	_p_stGF->p_ucPalette       = NULL;
	p_stGFHeader->uwNbColorInPalette	= 0;
	p_stGFHeader->ulWidth				= 0;
	p_stGFHeader->ulHeight             = 0;
	p_stGFHeader->ucBpp		        = 0;
	p_stGFHeader->ucBpcInPalette		= 0;
	p_stGFHeader->ulImageSize			= 0;
	p_stGFHeader->ucFormat				= 0xff;
	
	if( (hHandleToFile = FIL_fn_hOpenFileInConcatFile(hConcatFile,p_szPath,p_szFileName)) != NULL )
	{
        /*VLHorror*/
	    /* read file header*/
	    /*FIL_fn_lReadFileInConcatFile( p_stGFHeader, sizeof(struct FIL_tdstFileHeader_), 1, hHandleToFile );*/
        FIL_fn_lReadFileInConcatFile( &stGFRealHeader, sizeof( FIL_tdstRealGFFileHeader ), 1, hHandleToFile );
        p_stGFHeader->ulWidth       = stGFRealHeader.ulWidth;
        p_stGFHeader->ulHeight      = stGFRealHeader.ulHeight;
        p_stGFHeader->ulImageSize   = stGFRealHeader.ulWidth * stGFRealHeader.ulHeight;
        p_stGFHeader->ucBpp         = stGFRealHeader.ucBpp;
        p_stGFHeader->ucRLECode     = stGFRealHeader.ucRLECode;
        p_stGFHeader->ucVersion     = GF_VERSION;
        if (p_stGFHeader->ucBpp == 1)
        {
            p_stGFHeader->uwNbColorInPalette = 256;
            p_stGFHeader->ucBpcInPalette     = 4;
        }
        /*EVL*/
		
		/* set return values*/
		if(p_stGFHeader->ucVersion != GF_VERSION)
		{
			char ErrorMessage[60];
			sprintf(ErrorMessage,"File is Version: %d, Expected version: %d",p_stGFHeader->ucVersion, GF_VERSION);
			M_FILFatalErrorWithMessage(E_uwFILInvalidGFVersion, ErrorMessage);
		}
		
		
		if(p_stGFHeader->lChromakeyIndex == 0xffffffff)
		{
			p_stGFHeader->ucRed   = 0;
			p_stGFHeader->ucGreen = 0;
			p_stGFHeader->ucBlue  = 0;
		}
		
		_p_stGF->p_ucBitMap  = (unsigned char *) TMP_M_p_Malloc( p_stGFHeader->ulImageSize * p_stGFHeader->ucBpp );
		
		/* read palette, if one*/
		if( p_stGFHeader->uwNbColorInPalette != 0  &&  p_stGFHeader->ucBpcInPalette != 0 )
		{
			_p_stGF->p_ucPalette = (unsigned char *) TMP_M_p_Malloc( p_stGFHeader->uwNbColorInPalette * p_stGFHeader->ucBpcInPalette );
			FIL_fn_lReadFileInConcatFile( _p_stGF->p_ucPalette, (long)p_stGFHeader->ucBpcInPalette, p_stGFHeader->uwNbColorInPalette, hHandleToFile );
		}
		
		/* read bitmap and decompress it*/
		for( c=0; c < p_stGFHeader->ucBpp; c++ )
		{
			for( i=0; i < p_stGFHeader->ulImageSize; )
			{
				FIL_fn_lReadFileInConcatFile(&ucCode,sizeof(unsigned char),1,hHandleToFile);
				if( ucCode == p_stGFHeader->ucRLECode )
				{
					FIL_fn_lReadFileInConcatFile(&ucColor,sizeof(unsigned char),1,hHandleToFile);
					FIL_fn_lReadFileInConcatFile(&ucNumber,sizeof(unsigned char),1,hHandleToFile);
					
					for( j=0; j < ucNumber; j++ )
					{
						_p_stGF->p_ucBitMap[ ( i + j ) * p_stGFHeader->ucBpp + c ] = ucColor;
					}
					
					i += ucNumber;
				}
				else
				{
					_p_stGF->p_ucBitMap[ i * p_stGFHeader->ucBpp + c ] = ucCode;
					i++;
				}
			}
		}
		FIL_fn_vCloseFileInConcatFile(&hHandleToFile);
	}
}
 
 
/**************************************************************************/
void FIL_fn_vFreeGF( unsigned char **pp_ucBitMap, unsigned char **pp_ucPalette )
{
	if( *pp_ucBitMap != NULL )
	{
		TMP_M_Free( *pp_ucBitMap );
		*pp_ucBitMap = NULL;
	}
	
	if( *pp_ucPalette != NULL )
	{
		TMP_M_Free( *pp_ucPalette );
		*pp_ucPalette = NULL;
	}
}
 
 
/**************************************************************************/
void FIL_fn_vInvertGF(
					  unsigned char  *p_ucDest,
					  unsigned char  ucNumberOfBytesInDest,
					  unsigned long  ulWidth,
					  unsigned long  ulHeight )
{
	unsigned char *p_ucOneLine;
	unsigned long y;
	
	p_ucOneLine = (unsigned char *)TMP_M_p_Malloc(ulWidth*ucNumberOfBytesInDest);
	
	for (y=0;y<ulHeight/2;y++)
	{
		memcpy(p_ucOneLine,p_ucDest+y*ulWidth*ucNumberOfBytesInDest,ulWidth*ucNumberOfBytesInDest);
		memcpy(p_ucDest+y*ulWidth*ucNumberOfBytesInDest,p_ucDest+(ulHeight-1-y)*ulWidth*ucNumberOfBytesInDest,ulWidth*ucNumberOfBytesInDest);
		memcpy(p_ucDest+(ulHeight-1-y)*ulWidth*ucNumberOfBytesInDest,p_ucOneLine,ulWidth*ucNumberOfBytesInDest);
	}
	
	TMP_M_Free(p_ucOneLine);
}
 
 
/**************************************************************************/
 
 
 
 
 
/*------------------------------------------------------------------------*/
/**/
/* Author			David Lassonde*/
/* Date				2 Sep 1998*/
/* */
/* Prototype		FIL_fn_vInitGlobalHandleToConcatFiles*/
/* Return Type		void*/
/* */
/* Description		*/
/* */
/*	Initializes the global handle*/
/* To be called before textures are loaded (before each map is loaded but also*/
/* when the engine initializes (vignettes...)*/
/*------------------------------------------------------------------------*/
 
void FIL_fn_vInitGlobalHandleToFileInConcatFile()
{
	if (FIL_g_hHandleToFileInConcatFile != NULL)/*|| GLI_g_hConcatTexturesFile == NULL)*/
		return;
	
	FIL_g_hHandleToFileInConcatFile  = (FIL_tdxHandleToFileInConcatFile)TMP_M_p_Malloc(sizeof(FIL_tdstFileInConcatFile));
	FIL_g_hHandleToFileInConcatFile  ->bUseConcatFile = TRUE;
	
	/* cache initialization*/
	FIL_g_hHandleToFileInConcatFile ->ulCacheCheckSum = 0;
	FIL_g_hHandleToFileInConcatFile ->p_ucCache = (unsigned char *)TMP_M_p_Malloc(FIL_C_MaxConcatCacheSize*sizeof(unsigned char));
	FIL_g_hHandleToFileInConcatFile ->ulCacheSize = FIL_C_MaxConcatCacheSize;
	FIL_g_hHandleToFileInConcatFile ->ulCacheSeek = FIL_g_hHandleToFileInConcatFile ->ulCacheSize;
}
 
 
/*------------------------------------------------------------------------*/
/**/
/* Author			David Lassonde*/
/* Date				3 Sep 1998*/
/* */
/* Prototype		FIL_fn_vFreeGlobalHandleToFileInConcatFile*/
/* Return Type		void*/
/* */
/* Description		*/
/**/
/*	Frees the global handle when loading is completed*/
/*------------------------------------------------------------------------*/
 
void FIL_fn_vFreeGlobalHandleToFileInConcatFile()
{
	if (FIL_g_hHandleToFileInConcatFile != NULL)
	{
		/* we reset the cache*/
		FIL_g_hHandleToFileInConcatFile->ulCacheCheckSum = FIL_g_hHandleToFileInConcatFile->ulFileCheckSum;
		FIL_g_hHandleToFileInConcatFile->ulCacheSize = FIL_C_MaxConcatCacheSize;
		FIL_g_hHandleToFileInConcatFile->ulCacheSeek = FIL_g_hHandleToFileInConcatFile ->ulCacheSize;
		FIL_fn_vCloseFileInConcatFile(&FIL_g_hHandleToFileInConcatFile);
	}
}
/**************************************************************************/
void FIL_fn_vGFLoadInformationFromConcatFile
(
 FIL_tdxHandleToConcatFile	hConcatFile,
 char						*p_szPath,
 char						*p_szFileName,
 FIL_tdstGF					 *_p_stGF)
{
    FIL_tdxHandleToFileInConcatFile hHandleToFile;
    struct FIL_tdstFileHeader_	*p_stGFHeader = &(_p_stGF -> stFileHeader);
    /*VLHorror*/
    FIL_tdstRealGFFileHeader    stGFRealHeader;
 
    memset( &stGFRealHeader, 0, sizeof( FIL_tdstRealGFFileHeader ) );
    /*EVL*/
 
	
    p_stGFHeader->ucBpp = 0;
    p_stGFHeader->ulWidth = 0;
    p_stGFHeader->ulHeight = 0;
	
    if ((hHandleToFile = FIL_fn_hOpenFileInConcatFile(hConcatFile,p_szPath,p_szFileName))!=NULL)
    {
        /*VLHorror*/
	    /* read file header*/
	    /*FIL_fn_lReadFileInConcatFile(p_stGFHeader,sizeof(struct FIL_tdstFileHeader_),1,hHandleToFile);*/
        FIL_fn_lReadFileInConcatFile( &stGFRealHeader, sizeof( FIL_tdstRealGFFileHeader ), 1, hHandleToFile );
        p_stGFHeader->ulWidth       = stGFRealHeader.ulWidth;
        p_stGFHeader->ulHeight      = stGFRealHeader.ulHeight;
        p_stGFHeader->ucBpp         = stGFRealHeader.ucBpp;
        /*EVL*/
 
        FIL_fn_vCloseFileInConcatFile(&hHandleToFile);
    }
}
