#include <io.h>
 
#include "FIL_CPA.h"
 
#define D_FIL_StructureDefine
 
#include "ErmFil.h"
 
#include "FIL_GF.h"
#include "FIL_Pub.h"
#include "FIL_Priv.h"
#include "FIL_Conc.h"
 
#include "MMG.h"
/**************************************************************************/
FIL_tdxHandleToConcatFile FIL_fn_hCreateConcatFileHandle(unsigned long ulNumberOfPath,unsigned long ulNumberOfFiles)
{
 FIL_tdstConcatFile *p_stConcatFile = NULL;
 
 MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeConcatFile , NULL);
 p_stConcatFile = (FIL_tdstConcatFile *)TMP_M_p_Malloc(sizeof(FIL_tdstConcatFile));
 
 p_stConcatFile->ulNumberOfPath = ulNumberOfPath;
 p_stConcatFile->ulNumberOfFile = ulNumberOfFiles;
 
 if (ulNumberOfPath)
 {
  MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeConcatFile , NULL);	
  p_stConcatFile->d_szPathList = (char **)TMP_M_p_Malloc(ulNumberOfPath*sizeof(char *));
 }
 else
  p_stConcatFile->d_szPathList = NULL;
 
 MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeConcatFile , NULL);
 p_stConcatFile->d_stConcatFileElement = (FIL_tdstConcatFileElement *)TMP_M_p_Malloc(ulNumberOfFiles*sizeof(struct FIL_tdstConcatFileElement_));
 
 return(p_stConcatFile);
}
/**************************************************************************/
void fn_vDestroyConcatFileHandle(FIL_tdxHandleToConcatFile hConcatFile)
{
 unsigned long i;
 
 if (hConcatFile->d_szPathList!=NULL)
 {
  for (i=0;i<hConcatFile->ulNumberOfPath;i++)
   TMP_M_Free(hConcatFile->d_szPathList[i]);
  TMP_M_Free(hConcatFile->d_szPathList);
 }
 if (hConcatFile->d_stConcatFileElement!=NULL)
 {
  for (i=0;i<hConcatFile->ulNumberOfFile;i++)
   TMP_M_Free(hConcatFile->d_stConcatFileElement[i].p_szFileName);
  TMP_M_Free(hConcatFile->d_stConcatFileElement);
 }
 
 TMP_M_Free(hConcatFile);
}
/**************************************************************************/
unsigned char FIL_fn_bSetConcatPathElement(FIL_tdxHandleToConcatFile hConcatFile,unsigned long ulPathNumber,char *p_szPathName)
{
 unsigned char bReturn = FALSE;
 
 if (ulPathNumber<hConcatFile->ulNumberOfPath)
 {
  MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeConcatFile , NULL);
  hConcatFile->d_szPathList[ulPathNumber] = (char *)TMP_M_p_Malloc((strlen(p_szPathName)+1)*sizeof(char));
  strcpy(hConcatFile->d_szPathList[ulPathNumber],p_szPathName);
  bReturn = TRUE;
 }
 return(bReturn);
}
/**************************************************************************/
unsigned char FIL_fn_bSetConcatFileElementWithoutPath(FIL_tdxHandleToConcatFile hConcatFile,unsigned long ulFileNumber,char *p_szFileName)
{
 unsigned char bReturn = FALSE;
 
 if (ulFileNumber<hConcatFile->ulNumberOfFile)
 {
  MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeConcatFile , NULL);
  hConcatFile->d_stConcatFileElement[ulFileNumber].p_szFileName = (char *)TMP_M_p_Malloc((strlen(p_szFileName)+1)*sizeof(char));
  strcpy(hConcatFile->d_stConcatFileElement[ulFileNumber].p_szFileName,p_szFileName);
  bReturn = TRUE;
 }
 return(bReturn);
}
/**************************************************************************/
unsigned char FIL_fn_bSetConcatFileElement(FIL_tdxHandleToConcatFile hConcatFile,unsigned long ulFileNumber,char *p_szFileName)
{
 char szTemp[_MAX_PATH];
 unsigned char bReturn = FALSE;
 unsigned long i;
 
 if (ulFileNumber<hConcatFile->ulNumberOfFile)
 {
  if (strrchr(p_szFileName,'\\')==NULL)
  {
   MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeConcatFile , NULL);
   hConcatFile->d_stConcatFileElement[ulFileNumber].p_szFileName = (char *)TMP_M_p_Malloc((strlen(p_szFileName)+1)*sizeof(char));
   strcpy(hConcatFile->d_stConcatFileElement[ulFileNumber].p_szFileName,p_szFileName);
   hConcatFile->d_stConcatFileElement[ulFileNumber].lPathNumber = -1;
   bReturn = TRUE;
  }
  else
  {
   strcpy(szTemp,p_szFileName);
   *strrchr(szTemp,'\\')=0;
   for (i=0;i<hConcatFile->ulNumberOfPath&&stricmp(szTemp,hConcatFile->d_szPathList[i]);i++);
   if (i!=hConcatFile->ulNumberOfPath)
   {
    strcpy(szTemp,strrchr(p_szFileName,'\\')+1);
	MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeConcatFile , NULL);
    hConcatFile->d_stConcatFileElement[ulFileNumber].p_szFileName = (char *)TMP_M_p_Malloc((strlen(szTemp)+1)*sizeof(char));
    strcpy(hConcatFile->d_stConcatFileElement[ulFileNumber].p_szFileName,szTemp);
    hConcatFile->d_stConcatFileElement[ulFileNumber].lPathNumber = i;
    bReturn = TRUE;
   }
  }
 
 }
 return(bReturn);
}
/**************************************************************************/
void FIL_fn_vBuildConcatCompleteFileName(char *szCompleteFilename,FIL_tdxHandleToConcatFile hConcatFile,unsigned long ulIndex)
{
 if (hConcatFile->d_stConcatFileElement[ulIndex].lPathNumber==-1)
  strcpy(szCompleteFilename,hConcatFile->d_stConcatFileElement[ulIndex].p_szFileName);
 else
  sprintf(szCompleteFilename,"%s\\%s",hConcatFile->d_szPathList[hConcatFile->d_stConcatFileElement[ulIndex].lPathNumber],hConcatFile->d_stConcatFileElement[ulIndex].p_szFileName);
}
/**************************************************************************/
/**************************************************************************/
 
/* O.C start*/
#define	C_MARK_SIZE				4
#define C_RIFF_MARK				"RIFF"
#define C_AVI_MARK				"AVI "
#define	C_AVI_HEADER_SIZE		sizeof(tdstAviHeader)
#define	C_CHUNK_HEADER_SIZE		sizeof(tdstChunkHeader)
#define C_DEFAULT_CHUNK_NAME	".CNT"
 
typedef struct tdstAviHeader_
{
	unsigned char ucRIFFMark[C_MARK_SIZE];
	long lLength;
	unsigned char ucAVIMark[C_MARK_SIZE];
 
} tdstAviHeader;
 
typedef struct tdstChunkHeader_
{
	unsigned char ucChunkMark[C_MARK_SIZE];
	long lChunkLength;
} tdstChunkHeader;
 
tdstAviHeader stAviHeader;
tdstChunkHeader stChunkHeader;
 
long fn_lCheckForFileinAVI(FILE *p_stFile,char *szFileToFind,char *szChunkToFind)
{
	long lOffset=-1L;
	if (
		  (fseek(p_stFile,0,SEEK_SET)==0)   &&
 		  (fread(&stAviHeader,1,C_AVI_HEADER_SIZE,p_stFile)==C_AVI_HEADER_SIZE) &&
  		  (!strncmp((char*) &(stAviHeader.ucRIFFMark),C_RIFF_MARK,C_MARK_SIZE)) &&
		  (!strncmp((char*) &(stAviHeader.ucAVIMark),C_AVI_MARK,C_MARK_SIZE))
		)
	{
		long lTotalLen=stAviHeader.lLength+C_CHUNK_HEADER_SIZE;
		long lLen;
 
		unsigned char ucSize=0;
		char szBuffer[_MAX_PATH];
 
		while
		(
			  ((lLen=ftell(p_stFile))!=-1L) &&
			  (lLen<lTotalLen) &&
			  (fread(&stChunkHeader,1,C_CHUNK_HEADER_SIZE,p_stFile)==C_CHUNK_HEADER_SIZE)
		)
		{
			  if (
					(!strncmp((char*) &(stChunkHeader.ucChunkMark),szChunkToFind,C_MARK_SIZE)) &&
					(fread(&ucSize,1,1,p_stFile)==1) &&
					(fread(szBuffer,1,ucSize,p_stFile)==(size_t) ucSize) &&
					(
						(strlen(szFileToFind)==0) ||
						(!stricmp(szBuffer,szFileToFind))
					)
				)
			  {
					lOffset=ftell(p_stFile);
					break;
			  }
			  else
			  {
				if (fseek(p_stFile,stChunkHeader.lChunkLength + (stChunkHeader.lChunkLength &1),SEEK_CUR)!=0)
				{
					break;
				}
			  }
			  
		}
	}
    return(lOffset);
}
 
/* To access file in avi FILE.CNT@FILE.AVI*/
/* or first chunk in FILE.AVI*/
FILE *fn_p_stExtendedFopenForCNTinAVI(char *p_szFilename,long *p_lOffset)
{
    FILE *p_stFile=NULL;
	char *szPtr=NULL;
	char szFileToOpen[_MAX_PATH];
	char szFileToFind[_MAX_PATH];
	char szChunkToFind[C_MARK_SIZE+1];
	*p_lOffset=0;
 
	szPtr=strrchr(p_szFilename,'@');
	if (szPtr!=NULL)
	{
		strcpy(szFileToOpen,szPtr+1);
 
		strcpy(szFileToFind,p_szFilename);
		szFileToFind[szPtr-p_szFilename]=0;
 
		szPtr=strrchr(szFileToFind,'.');
		if (szPtr!=NULL)
		{
			memset(szChunkToFind,0,sizeof(szChunkToFind));
			strncpy(szChunkToFind,szPtr,C_MARK_SIZE);
			*szPtr=0;
		}
		else
		{
			strcpy(szChunkToFind,C_DEFAULT_CHUNK_NAME);
		}
	}
	else
	{
		strcpy(szFileToOpen,p_szFilename);
		szFileToFind[0]=0;
		strcpy(szChunkToFind,C_DEFAULT_CHUNK_NAME);
	}
 
	strupr(szFileToFind);
	strupr(szChunkToFind);
	if ((p_stFile=fopen(szFileToOpen,"rb"))!=NULL)
	{
		*p_lOffset=fn_lCheckForFileinAVI(p_stFile,szFileToFind,szChunkToFind);
		if (*p_lOffset==-1L)
		{
			*p_lOffset=0;
			rewind(p_stFile);
		}
	}
	return(p_stFile);
}
/* O.C end*/
 
FIL_tdxHandleToConcatFile FIL_fn_vOpenConcatFile(char *p_szFilename)
{
 FIL_tdxHandleToConcatFile hConcatFile = NULL;
 unsigned long ulNumberOfPath,ulNumberOfFile;
 unsigned long ulInternalLength;
 unsigned long i,j;
 unsigned char ucInternalCheckSum;
 char szTemp[_MAX_PATH];
 FILE *p_stFile;
 
 /* O.C*/
 long lOffsetToAdd=0;
 if ((p_stFile=fn_p_stExtendedFopenForCNTinAVI(p_szFilename,&lOffsetToAdd))!=NULL)
 /*if ((p_stFile=fopen(p_szFilename,"rb"))!=NULL)*/
 {
  /**** Number of paths and files ****/
  fread(&ulNumberOfPath,sizeof(unsigned long),1,p_stFile);
  fread(&ulNumberOfFile,sizeof(unsigned long),1,p_stFile);
  hConcatFile = FIL_fn_hCreateConcatFileHandle(ulNumberOfPath,ulNumberOfFile);
  fread(&hConcatFile->bUseXorCode,sizeof(unsigned char),1,p_stFile);
  fread(&hConcatFile->bUseCheckSum,sizeof(unsigned char),1,p_stFile);
 
  hConcatFile->p_stFile = p_stFile;
  
  /**** Load path table ****/
  fread(&hConcatFile->ucPathXorCode,sizeof(unsigned char),1,p_stFile);
  ucInternalCheckSum = 0;
  for (i=0;i<hConcatFile->ulNumberOfPath;i++)
  {
   fread(&ulInternalLength,sizeof(unsigned long),1,p_stFile);
   fread(szTemp,sizeof(char),ulInternalLength,p_stFile);
   szTemp[ulInternalLength] = 0;
   if (hConcatFile->bUseXorCode||hConcatFile->bUseCheckSum)
   {
    for (j=0;j<ulInternalLength;j++)
    {
     if (hConcatFile->bUseXorCode)
      szTemp[j]^=hConcatFile->ucPathXorCode;
     if (hConcatFile->bUseCheckSum)
      ucInternalCheckSum=(unsigned char)(ucInternalCheckSum+szTemp[j]);
    }
   }
   FIL_fn_bSetConcatPathElement(hConcatFile,i,szTemp);
  }
  fread(&hConcatFile->ucPathCheckSum,sizeof(unsigned char),1,p_stFile);
  if (hConcatFile->ucPathCheckSum!=ucInternalCheckSum)
   M_FILFatalErrorWithMessage(E_uwFILConcatCheckSumOpen,p_szFilename);
 
  /**** Load filenames table ****/
  ucInternalCheckSum = 0;
  for (i=0;i<hConcatFile->ulNumberOfFile;i++)
  {
   fread(&hConcatFile->d_stConcatFileElement[i].lPathNumber,sizeof(long),1,p_stFile);
   fread(&ulInternalLength,sizeof(unsigned long),1,p_stFile);
   fread(szTemp,sizeof(char),ulInternalLength,p_stFile);
   szTemp[ulInternalLength] = 0;
   if (hConcatFile->bUseXorCode)
   {
    for (j=0;j<ulInternalLength;j++)
     szTemp[j]^=hConcatFile->ucPathXorCode;
   }
   FIL_fn_bSetConcatFileElementWithoutPath(hConcatFile,i,szTemp);
   fread(&hConcatFile->d_stConcatFileElement[i].ulXorCode,sizeof(unsigned long),1,p_stFile);
   fread(&hConcatFile->d_stConcatFileElement[i].ulCheckSum,sizeof(unsigned long),1,p_stFile);
   fread(&hConcatFile->d_stConcatFileElement[i].lOffset,sizeof(long),1,p_stFile);
   fread(&hConcatFile->d_stConcatFileElement[i].ulFileLength,sizeof(unsigned long),1,p_stFile);
 
   /* O.C.*/
   hConcatFile->d_stConcatFileElement[i].lOffset+=lOffsetToAdd;
  }
 }
 return(hConcatFile);
}
/**************************************************************************/
void FIL_fn_vCloseConcatFile(FIL_tdxHandleToConcatFile *hConcatFile)
{
 if (*hConcatFile!=NULL)
 {
  fclose((*hConcatFile)->p_stFile);
  fn_vDestroyConcatFileHandle(*hConcatFile);
  *hConcatFile = NULL;
 }
}
/**************************************************************************/
FIL_tdxHandleToFileInConcatFile FIL_fn_hOpenFileInConcatFile(FIL_tdxHandleToConcatFile hConcatFile,char *p_szPath,char *p_szFilename)
{
 FIL_tdxHandleToFileInConcatFile hHandleToFile = NULL;
 unsigned char bFileFound = FALSE;
 char szTemp[_MAX_PATH];
 FILE *p_stFile;
 unsigned long ulInternalLength;
/* unsigned long ulInternalCheckSum;*/
 unsigned long i/*,j*/;
 
 char *p_szPointer;
 
 /**** Convert / by \ in p_szFileName ****/
 while((p_szPointer=strchr(p_szFilename,'/'))!=NULL)
  *p_szPointer = '\\';
 
 if ((p_szPointer=strrchr(p_szFilename,'\\'))==NULL)
  p_szPointer = p_szFilename;
 else
  p_szPointer++;
 
 /**** Search file in concat file ****/
 if (hConcatFile!=NULL)
 {
  for (i=0;i<hConcatFile->ulNumberOfFile&&!bFileFound;i++)
  {
   if (!stricmp(p_szPointer,hConcatFile->d_stConcatFileElement[i].p_szFileName))
   {
    FIL_fn_vBuildConcatCompleteFileName(szTemp,hConcatFile,i);
    if (!stricmp(p_szFilename,szTemp))
    {
     bFileFound = TRUE;
	 MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeConcatFile , NULL);
     hHandleToFile = (FIL_tdxHandleToFileInConcatFile)TMP_M_p_Malloc(sizeof(FIL_tdstFileInConcatFile));
     hHandleToFile->bUseConcatFile = TRUE;
     hHandleToFile->p_stFile = hConcatFile->p_stFile;
     hHandleToFile->ulFileActualSeek = hConcatFile->d_stConcatFileElement[i].lOffset;
     hHandleToFile->ulFileEndSeek = hConcatFile->d_stConcatFileElement[i].lOffset + hConcatFile->d_stConcatFileElement[i].ulFileLength;
     if (!hConcatFile->bUseXorCode&&!hConcatFile->bUseCheckSum)
     {
      hHandleToFile->ulFileXorCode  = 0;
      hHandleToFile->ulFileCheckSum = 0;
     }
     else
     {
      hHandleToFile->ulFileXorCode  = hConcatFile->d_stConcatFileElement[i].ulXorCode;
      hHandleToFile->ulFileCheckSum = hConcatFile->d_stConcatFileElement[i].ulCheckSum;
     }
 
     hHandleToFile->ulCacheCheckSum = 0;
 
     if (hConcatFile->d_stConcatFileElement[i].ulFileLength>FIL_C_MaxConcatCacheSize)
     {
	  MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeConcatFile , NULL);
      hHandleToFile->p_ucCache = (unsigned char *)TMP_M_p_Malloc(FIL_C_MaxConcatCacheSize*sizeof(unsigned char));
      hHandleToFile->ulCacheSize = FIL_C_MaxConcatCacheSize;
     }
     else
     {
	  MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeConcatFile , NULL);
      hHandleToFile->p_ucCache = (unsigned char *)TMP_M_p_Malloc(hConcatFile->d_stConcatFileElement[i].ulFileLength*sizeof(unsigned char));
      hHandleToFile->ulCacheSize = hConcatFile->d_stConcatFileElement[i].ulFileLength;
     }
     hHandleToFile->ulCacheSeek = hHandleToFile->ulCacheSize;
    }
   }
  }
 }
 
 if (!bFileFound)
 {
  sprintf(szTemp,"%s\\%s",p_szPath,p_szFilename);
  ulInternalLength = FIL_fn_ulGetFileSize(szTemp);
  if ((p_stFile = fopen(szTemp,"rb"))!=NULL)
  {
   MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeConcatFile , NULL);
   hHandleToFile = (FIL_tdxHandleToFileInConcatFile)TMP_M_p_Malloc(sizeof(FIL_tdstFileInConcatFile));
   hHandleToFile->bUseConcatFile = FALSE;
   hHandleToFile->p_stFile = p_stFile;
   hHandleToFile->ulFileActualSeek = 0;
   hHandleToFile->ulFileEndSeek = ulInternalLength;
   hHandleToFile->ulFileXorCode  = 0;
   hHandleToFile->ulFileCheckSum = 0;
 
   hHandleToFile->ulCacheCheckSum = 0;
 
   if (ulInternalLength>FIL_C_MaxConcatCacheSize)
   {
	MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeConcatFile , NULL);
    hHandleToFile->p_ucCache = (unsigned char *)TMP_M_p_Malloc(FIL_C_MaxConcatCacheSize*sizeof(unsigned char));
    hHandleToFile->ulCacheSize = FIL_C_MaxConcatCacheSize;
   }
   else
   {
	MMG_fn_vAddMemoryInfo (MMG_C_lTypeFile , MMG_C_lSubTypeConcatFile , NULL);
    hHandleToFile->p_ucCache = (unsigned char *)TMP_M_p_Malloc(ulInternalLength*sizeof(unsigned char));
    hHandleToFile->ulCacheSize = ulInternalLength;
   }
   hHandleToFile->ulCacheSeek = hHandleToFile->ulCacheSize;
  }
 }
 
 return(hHandleToFile);
}
/**************************************************************************/
unsigned long FIL_fn_ulReadFromFileToCacheinConcatFile(FIL_tdxHandleToFileInConcatFile hHandleToFile)
{
 unsigned long ulReadReturn;
 unsigned long i;
 
 fseek(hHandleToFile->p_stFile,hHandleToFile->ulFileActualSeek,SEEK_SET);
 if (hHandleToFile->ulFileActualSeek+hHandleToFile->ulCacheSize>hHandleToFile->ulFileEndSeek)
  ulReadReturn=fread(hHandleToFile->p_ucCache,sizeof(unsigned char),hHandleToFile->ulFileEndSeek-hHandleToFile->ulFileActualSeek,hHandleToFile->p_stFile);
 else
  ulReadReturn=fread(hHandleToFile->p_ucCache,sizeof(unsigned char),hHandleToFile->ulCacheSize,hHandleToFile->p_stFile);
 
 hHandleToFile->ulFileActualSeek += ulReadReturn*sizeof(unsigned char);
 hHandleToFile->ulCacheSeek = 0;
 hHandleToFile->ulCacheSize = ulReadReturn*sizeof(unsigned char);
 
 if (hHandleToFile->ulFileXorCode||hHandleToFile->ulFileCheckSum)
 {
  for (i=0;i<ulReadReturn/4;i++)
  {
   if (hHandleToFile->ulFileXorCode)
    ((unsigned long*)hHandleToFile->p_ucCache)[i]^=hHandleToFile->ulFileXorCode;
   if (hHandleToFile->ulFileCheckSum)
    hHandleToFile->ulCacheCheckSum+=((unsigned long*)hHandleToFile->p_ucCache)[i];
  }
 }
 return(ulReadReturn);
}
/**************************************************************************/
void FIL_fn_vCloseFileInConcatFile(FIL_tdxHandleToFileInConcatFile *hHandleToFile)
{
 if ((*hHandleToFile)->ulFileEndSeek==(*hHandleToFile)->ulFileActualSeek&&(*hHandleToFile)->ulFileCheckSum&&(*hHandleToFile)->ulCacheCheckSum!=(*hHandleToFile)->ulFileCheckSum)
  M_FILFatalError(E_uwFILConcatCheckSumRead);
 
 if (!(*hHandleToFile)->bUseConcatFile)
  fclose((*hHandleToFile)->p_stFile);
 
 if (hHandleToFile!=NULL)
 {
  if ((*hHandleToFile)->p_ucCache!=NULL)
   TMP_M_Free((*hHandleToFile)->p_ucCache);
  TMP_M_Free(*hHandleToFile);
  *hHandleToFile=NULL;
 }
}
/**************************************************************************/
long FIL_fn_lReadFileInConcatFile(void *p_vBuffer,long lSize,long lNumber,FIL_tdxHandleToFileInConcatFile hHandleToFile)
{
 long lInternalLength = 0;
 long lReadLength = 0;
 void *p_vInternalPointer;
 
 if (hHandleToFile!=NULL&&lSize*lNumber>0)
 {
  /**** The asking size is above the file size ****/
  if ((unsigned long)(lSize*lNumber)>(hHandleToFile->ulCacheSize-hHandleToFile->ulCacheSeek)+(hHandleToFile->ulFileEndSeek-hHandleToFile->ulFileActualSeek))
   lInternalLength = (hHandleToFile->ulCacheSize-hHandleToFile->ulCacheSeek)+(hHandleToFile->ulFileEndSeek-hHandleToFile->ulFileActualSeek);
  else
   lInternalLength = lSize*lNumber;
 
  lReadLength = lInternalLength/lSize;
 
 
  for (p_vInternalPointer=p_vBuffer;lInternalLength!=0;)
  {
   if (hHandleToFile->ulCacheSeek+lInternalLength<=hHandleToFile->ulCacheSize)
   {
    memcpy(p_vInternalPointer,hHandleToFile->p_ucCache+hHandleToFile->ulCacheSeek,lInternalLength);
    hHandleToFile->ulCacheSeek+=lInternalLength;
    p_vInternalPointer=(void*)((unsigned long)p_vInternalPointer+lInternalLength);
    lInternalLength = 0;
   }
   else if (hHandleToFile->ulCacheSeek<hHandleToFile->ulCacheSize)
   {
    memcpy(p_vInternalPointer,hHandleToFile->p_ucCache+hHandleToFile->ulCacheSeek,hHandleToFile->ulCacheSize-hHandleToFile->ulCacheSeek);
    lInternalLength -= hHandleToFile->ulCacheSize-hHandleToFile->ulCacheSeek;
    p_vInternalPointer=(void*)((unsigned long)p_vInternalPointer+hHandleToFile->ulCacheSize-hHandleToFile->ulCacheSeek);
    hHandleToFile->ulCacheSeek = hHandleToFile->ulCacheSize;
   }
   else
    FIL_fn_ulReadFromFileToCacheinConcatFile(hHandleToFile);
  }
 }
 return(lReadLength);
}
/**************************************************************************/
/*------------------------------------------------------------------------*/
/**/
/* Author			David Lassonde*/
/* Date				2 Sep 1998*/
/* */
/* Prototype		FIL_fn_vOpenFileInConcatFile*/
/* Parameters		hConcatFile : The concat file*/
/*					p_szPath : */
/*					p_szFilename : */
/*					hHandleToFile : the global variable*/
/* Return Type    int 0  : the handle is OK (the file was found and the global Handle is set)*/
/*                    -1 : the wanted file is not in the big file*/
/* */
/* Description		*/
/**/
/*	same as FIL_fn_hOpenFileInConcatFile, except that it doesn't allocate a new handle for each texture loaded*/
/* */
/*------------------------------------------------------------------------*/
int FIL_fn_iOpenFileInConcatFile(FIL_tdxHandleToConcatFile hConcatFile,char *p_szPath,char *p_szFilename, FIL_tdxHandleToFileInConcatFile hHandleToFile)
{
/* FIL_tdxHandleToFileInConcatFile hHandleToFile = NULL;*/
 unsigned char bFileFound = FALSE;
 char szTemp[_MAX_PATH];
/* unsigned long ulInternalCheckSum;*/
 unsigned long i/*,j*/;
 
 char *p_szPointer;
 
 /**** Convert / by \ in p_szFileName ****/
 while((p_szPointer=strchr(p_szFilename,'/'))!=NULL)
  *p_szPointer = '\\';
 
 if ((p_szPointer=strrchr(p_szFilename,'\\'))==NULL)
  p_szPointer = p_szFilename;
 else
  p_szPointer++;
 
 /**** Search file in concat file ****/
 if (hConcatFile!=NULL)
 {
  for (i=0;i<hConcatFile->ulNumberOfFile&&!bFileFound;i++)
  {
   if (!stricmp(p_szPointer,hConcatFile->d_stConcatFileElement[i].p_szFileName))
   {
    FIL_fn_vBuildConcatCompleteFileName(szTemp,hConcatFile,i);
    if (!stricmp(p_szFilename,szTemp))
    {
     bFileFound = TRUE;
     hHandleToFile->ulFileActualSeek = hConcatFile->d_stConcatFileElement[i].lOffset;
     hHandleToFile->ulFileEndSeek = hConcatFile->d_stConcatFileElement[i].lOffset + hConcatFile->d_stConcatFileElement[i].ulFileLength;
     if (!hConcatFile->bUseXorCode&&!hConcatFile->bUseCheckSum)
     {
      hHandleToFile->ulFileXorCode  = 0;
      hHandleToFile->ulFileCheckSum = 0;
     }
     else
     {
      hHandleToFile->ulFileXorCode  = hConcatFile->d_stConcatFileElement[i].ulXorCode;
      hHandleToFile->ulFileCheckSum = hConcatFile->d_stConcatFileElement[i].ulCheckSum;
     }
    }
   }
  }
 }
 
	if (!bFileFound)
 {
	/* the file is not in the big file... We'll have to use the old function...*/
		return -1;
 }
	return 0;
}
