/*=========================================================================
*
* Banks.c	- Bank conversion
*
* Version			1.0
* Revision date
*
*=======================================================================*/
#include <Windows.h>
#include <stdio.h>

#include "Banks.h"

#include "SCR.h"

#include "conventi.h"
#include "main.h"
#include "print.h"
#include "system.h"

#include "sprobj.h"

#include "ModLib.h"
#include "PlgLoad.h"
#include "A3dSave.h"
#include "ChlSave.h"
#include "ModSave.h"
#include "ObjSave.h"
#include "RliSave.h"
#include "VseSave.h"

#include "Anims.h"
#include "Levels.h"
#include "Families.h"

#include "SaveModifLst.h"



//--- Global externs --------------------------------------------------------

MLT_tdxHandleToSuperObject	g_hBankRoot;

//--- Global statics --------------------------------------------------------

char	gs_szFilesCommon[10][5];

//--------------------------------------------------------------------


/****************************************************************************
*		Description:	compute all the banks found in the source directory
*
*		Parameters:		sRawData	: source directory
*						sGameData	: destination directory
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vComputeAllBanks(char *sRawData, char *sGameData)
{
  xString			sDirectory;
  HANDLE			hHandle;
  WIN32_FIND_DATA	stFindFileData;

  // change directory
  GetCurrentDirectory(256, sDirectory);
  SetCurrentDirectory(sRawData);

  // search all the banks files
  memset(&stFindFileData,0,sizeof(stFindFileData));
  hHandle = FindFirstFile("World\\Graphics\\Objects\\Banks\\*.mod", &stFindFileData);
  if( hHandle == INVALID_HANDLE_VALUE)
  {
    SetCurrentDirectory(sDirectory);
    fprintf(stderr, "\nError : Can't find the Banks directory\n");
    return;
  }
  
  do
  {
    if(strlen(stFindFileData.cFileName) == 0) break;

    // compute the bank
	MLT_vComputeOneMod(MLT_p_cGetFileNameWithoutExt(stFindFileData.cFileName), MLT_p_cGetFileNameWithoutExt(stFindFileData.cFileName), sRawData, sGameData);
  }
  while(FindNextFile(hHandle, &stFindFileData));
  FindClose(hHandle);

  // restore directory
  SetCurrentDirectory(sDirectory);
}

/****************************************************************************
*		Description:	compute the specified bank
*
*		Parameters:		sBankName	: bank to convert
*						sRawData	: source directory
*						sGameData	: destination directory
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vComputeOneBank (char *sBankName, char *sRawData, char *sGameData)
{
// WIN version
#ifndef _WINDOWS

  xString			sDirectory, sFileSearch;
  HANDLE			hHandle;
  WIN32_FIND_DATA	stFindFileData;

  // change directory
  GetCurrentDirectory(256, sDirectory);

  // search for the bank file
  if (g_bStandardConfig)
  {	  
	  SetCurrentDirectory(sRawData);
	  sprintf(sFileSearch, "World\\Graphics\\Objects\\Banks\\%s.mod", sBankName);
  }
  else
	  sprintf(sFileSearch, "%s\\%s.mod", g_szBanks, sBankName);

  memset(&stFindFileData,0,sizeof(stFindFileData));
  hHandle = FindFirstFile(sFileSearch, &stFindFileData);
  if( hHandle == INVALID_HANDLE_VALUE)
  {
    SetCurrentDirectory(sDirectory);
    fprintf(stderr, "\nError : Can't find %s bank\n", sBankName);
    return;
  }
  do
  {
    if(strlen(stFindFileData.cFileName) == 0) break;

    // compute the MOD file
	MLT_vComputeOneMod(MLT_p_cGetFileNameWithoutExt(stFindFileData.cFileName), MLT_p_cGetFileNameWithoutExt(stFindFileData.cFileName), sRawData, sGameData);
  }
  while(FindNextFile(hHandle, &stFindFileData));
  FindClose(hHandle);

  // restore directory
  SetCurrentDirectory(sDirectory);

// DOS version
#else
  MLT_vComputeOneMod (sBankName, sBankName, sRawData, sGameData);  
#endif
}


/****************************************************************************
*		Description:	compute the MOD file in the specified bank
*
*		Parameters:		sBankName	: bank to convert
*						sModName	: file to convert
*						sRawData	: source directory
*						sGameData	: destination directory
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vComputeOneMod (char *sBankName, char *sModName, char *sRawData, char *sGameData)
{
  SCR_tdst_Cxt_Values			*p_stVal;
  xString						sRawBank, sGameBank, sRawFamily, sRawAnims, sRead;
  xString						sFile, sFileM, sFile1, sFileNew;
  xString						sRoot, sFileSpo, sDir;
  FILE							*file, *fileR, *fileF;
  int							f, i, ii, p, jj, j = 0, k = 0, k1 = 0, l = 0;

  // register globals
  sprintf(g_sFileIn, "%s", sModName);
  sprintf(g_sFileMaterial, "%s", sBankName);
  sprintf(g_sDirectorySave, "%s\\", sBankName);

  // init paths
  if (g_bStandardConfig)
  {
	sprintf(sRawBank, "%s\\World\\Graphics\\Objects\\Banks", sRawData);
	sprintf(sRawAnims, "%s\\World\\Graphics\\Anims", sRawData);
	sprintf(sRawFamily, "%s\\World\\Families", sRawData);
  }
  else
  {
	sprintf(sRawBank, g_szBanks);
	sprintf(sRawAnims, g_szAnims);
	sprintf(sRawFamily, g_szFamilies);
  }

  sprintf(sGameBank, "%s\\World\\Graphics\\Objects\\Banks\\%s\\", sGameData, sBankName);

  // DISPLAY
  MLT_vOutput( C_ComRes_cTitleLine, "\nBank %s\\%s.mod",sBankName, sModName);

  // change directory
  CreateDirectory(sGameBank, NULL);
  SetCurrentDirectory(sGameBank);

  // notify OBJ file, CHL file and A3d file
  sprintf(sFile, "%s\\%s.spo", sRawBank, sBankName);
  fileF = fopen (sFile, "r");

  //create the basic family if the .spo file exists
  if (g_bCreateBasicFamily && fileF)
  {
	if (g_bStandardConfig)
	{	
		MLT_vExistFile (sBankName, sRawData, "\\world\\families\\", "obj", &j);
		MLT_vExistFile (sBankName, sRawData, "\\world\\families\\", "chl", &j);
	}
	else
	{
		MLT_vExistFileInBank (sBankName, g_szFamilies, "obj", &j);
		MLT_vExistFileInBank (sBankName, g_szFamilies, "chl", &j);
	}
	//the source files for a family exist in RawData directory, so convert them
	if (j == 2)
		MLT_vOutput( C_ComRes_cNormalLine, "\nA source family already exists for this bank : the Converting Tool will convert this existing family instead of creating a new one.");
	
	// find the common extensions for the family
	MLT_vGetCommonExt(&jj);
	// test if at least one common file for a family exist in the GameData directory
	MLT_vExistFile (sBankName, g_sGameCommon, "\\world\\levels\\_common\\families\\", gs_szFilesCommon[0], &k);
	if (k) 
	{	
		// check if all te common files exist for the family
		for (p=1; p<jj; p++)
			MLT_vExistFile (sBankName, g_sGameCommon, "\\world\\levels\\_common\\families\\", gs_szFilesCommon[p], &k);

		// check if one of the specific file exist in the common directory
		MLT_vExistFile (sBankName, g_sGameCommon, "\\world\\levels\\_common\\families\\", g_szFiles[0], &k);
		//the family is a common one
		if (k==4)
		{	
			// check if all specific files exist in the common directory
			for (ii = 1 ; ii < g_iNbFiles; ii++)
				MLT_vExistFile (sBankName, g_sGameCommon, "\\world\\levels\\_common\\families\\", g_szFiles[ii], &k);
		}
		else
		{	
			//search for the files in the GameSpecific1 or GameSpecific2 directories
			MLT_vExistFile (sBankName, g_sGameSpecific1, "\\world\\levels\\_common\\families\\", g_szFiles[0], &k1);
			//the family is a specific one, with the specific files in GameSpecific2
			if (!k1) 
			{	
				for (ii = 0 ; ii < g_iNbFiles; ii++)
					MLT_vExistFile (sBankName, g_sGameSpecific2, "\\world\\levels\\_common\\families\\", g_szFiles[ii], &k);				
			}
			//the family is a specific one, with the specific files in GameSpecific1
			else 
			{	
				for (ii = 1 ; ii < g_iNbFiles; ii++)
					MLT_vExistFile (sBankName, g_sGameSpecific1, "\\world\\levels\\_common\\families\\", g_szFiles[ii], &k);
			}
		}
	}
	//the files already exist, so don't create them
	if (k == 7) 
		MLT_vOutput( C_ComRes_cNormalLine, "\nA Family already exists for this bank : the Converting Tool will keep it instead of creating a new one.");
	//the family don't exist
	else
	{	
		xString sDirFamily;

		sprintf(sDirFamily, "%s\\%s", sRawFamily, sBankName);
		CreateDirectory(sDirFamily, NULL);
		// notify files
		sprintf(sFile, "%s\\%s.obj", sDirFamily, sBankName);
		SCR_fn_v_SvL1_RegisterNotify(sFile, MLT_vSaveObjHeader, (void *)0x1, SCR_EA_Ntfy_AddOrModifySection);
		sprintf(sFile, "%s\\%s.chl", sDirFamily, sBankName);
		SCR_fn_v_SvL1_RegisterNotify(sFile, MLT_vSaveChlHeader, NULL, SCR_EA_Ntfy_AddOrModifySection);
	}

	//If an animation already exists (and the family does not exist)
	if ((k!=7) && (j!=2))  
	{	
		//search if the animation exists
		if (g_bStandardConfig)
			MLT_vExistFile (sBankName, sRawData, "\\world\\graphics\\anims\\", "a3d", &l);
		else
			MLT_vExistFileInBank (sBankName, g_szAnims, "a3d", &l);
		
		//the .a3d file doesn't exist in RawData directory
		if (!l) 
		{	
			MLT_vExistFile (sBankName, sGameData, "\\world\\graphics\\anims\\", "a3d", &l);
			//if is not in chosen directory
			if (!l) 
			{	
				//the animation is in GameCommon?
				MLT_vExistFile (sBankName, g_sGameCommon, "\\world\\graphics\\anims\\", "a3d", &l);
				//if is not in gamedata
				if (!l) 
				{	
					MLT_vExistFile (sBankName, g_sGameSpecific1, "\\world\\graphics\\anims\\", "a3d", &l);
					if (!l)
					{	
						MLT_vExistFile (sBankName, g_sGameSpecific2, "\\world\\graphics\\anims\\", "a3d", &l);
						if (l)
						{	
							//copy the animation in the other specific directory
							if (strcmp(sGameData, g_sGameCommon)) 
							{	
								sprintf(sFile, "%s\\world\\graphics\\anims\\%s\\%s.a3d", g_sGameSpecific2, sBankName, sBankName);
								sprintf(sFileNew, "%s\\world\\graphics\\anims\\%s\\", sGameData, sBankName);
								CreateDirectory(sFileNew, NULL);
								strcat(sFileNew, sBankName);
								strcat(sFileNew, ".a3d");
								CopyFile(sFile, sFileNew, FALSE);
							}
						}
					}
					else
					{	
						//copy the animation in the other specific directory (not the gamedat)
						if (strcmp(sGameData, g_sGameCommon)) 
						{	
							sprintf(sFile, "%s\\world\\graphics\\anims\\%s\\%s.a3d", g_sGameSpecific1, sBankName, sBankName);
							sprintf(sFileNew, "%s\\world\\graphics\\anims\\%s\\", sGameData, sBankName);
							CreateDirectory(sFileNew, NULL);
							strcat(sFileNew, sBankName);
							strcat(sFileNew, ".a3d");
							CopyFile(sFile, sFileNew, FALSE);
						}
					}
				}
			}
		}
		else
		{	
			//convert the animation existing in RawData directory
			sprintf(sFile, "%s\\%s", sRawAnims, sBankName);
			GetCurrentDirectory(256, sDir);
			SetCurrentDirectory(sFile);
			MLT_vComputeOneAnim(sBankName, sRawData, sGameData);
			SetCurrentDirectory(sDir);
		}

		//if the file doesn't exist
		if (!l) 
		{	
			sprintf(sFile, "%s\\%s", sRawAnims, sBankName);
			CreateDirectory( sFile, NULL );
			strcat(sFile, "\\");
			strcat(sFile, sBankName);
			strcat(sFile, ".a3d");
			SCR_fn_v_SvL1_RegisterNotify(sFile, MLT_vSaveA3dHeader, NULL, SCR_EA_Ntfy_AddOrModifySection);
		}
	}
  }

  // notify MOD file
  sprintf(sFile, "%s.mod", g_sFileIn);
  SCR_fn_v_SvL1_RegisterNotify(sFile, MLT_vSaveEmptyModHeader, NULL, SCR_EA_Ntfy_AddOrModifySection);

// multitextures
  // notify TEX file
  sprintf(sFile, "%s.tex", g_sFileIn);
  if (!(file = fopen(sFile, "r")))
  {
	g_bExistTex = FALSE;
    SCR_fn_v_SvL1_RegisterNotify(sFile, MLT_vSaveTexFile, NULL, SCR_EA_Ntfy_AddOrModifySection);
  }
  else
  {
    g_bExistTex = TRUE;
	fclose(file);
  }

  // notify VMT file
  sprintf(sFile, "%s.vmt", g_sFileIn);
  if(! SCR_fn_c_RdL0_IsSectionExists(sFile))
    SCR_fn_v_SvL1_RegisterNotify(sFile, MLT_vSaveVmtFile, NULL, SCR_EA_Ntfy_AddOrModifySection);

  // notify VSE file
  sprintf(sFile, "%s.vse", g_sFileIn);
  if(! SCR_fn_c_RdL0_IsSectionExists(sFile))
    SCR_fn_v_SvL1_RegisterNotify(sFile, MLT_vSaveVseFile, NULL, SCR_EA_Ntfy_AddSection);
  else
  {	
	CopyFile(sFile, "temp.vse", FALSE);
	remove(sFile);
	SCR_fn_v_SvL1_RegisterNotify(sFile, MLT_vSaveVseFile, NULL, SCR_EA_Ntfy_AddSection);
  }

  // notify GMT file
  sprintf(sFile, "%s.gmt", g_sFileIn);
  if(! SCR_fn_c_RdL0_IsSectionExists(sFile))
  {  
	 SCR_fn_v_SvL1_RegisterNotify(sFile, MLT_vSaveGmtFile, NULL, SCR_EA_Ntfy_AddOrModifySection);
	 g_bCreatedGmt = FALSE;	
  }
  else
	g_bCreatedGmt=TRUE;	

  // if GMT file exist, check if must be rebuilt
  if (g_bCreatedGmt)
  { 
    if (g_bIgnoreGmt)	
	{   
		remove(sFile);
	    SCR_fn_v_SvL1_RegisterNotify(sFile, MLT_vSaveGmtFile, NULL, SCR_EA_Ntfy_AddOrModifySection);
	}
	else
	{	
		CopyFile(sFile, "temp.gmt", FALSE);
		remove(sFile);
		SCR_fn_v_SvL1_RegisterNotify(sFile, MLT_vSaveGmtFile, NULL, SCR_EA_Ntfy_AddOrModifySection);
	}
  }

  // save all notified sections
  SCR_fn_v_SvL1_UpdateAllNotify();

  
  // register path for load
  SCR_fn_v_RdL0_RegisterPath(sGameBank);

  // change directory
  SetCurrentDirectory(sRawBank);

  // DISPLAY
  MLT_vOutput( C_ComRes_cNormalLine, "\n\tLoad...");

  // find SPO file
  GetCurrentDirectory(256, sDir);
  SetCurrentDirectory(sRawBank);
  sprintf(sFileSpo, "%s.spo", g_sFileIn);
  if(! SCR_fn_c_RdL0_IsSectionExists(sFileSpo))
	g_bExistSpo = FALSE;
  else
	g_bExistSpo = TRUE;
  SetCurrentDirectory(sDir);


  // load MOD file
  MLT_vLoadModFileInLib();

  // load PLG file
  MLT_vLoadPLGFileInLib();

  // find Root section
  GetCurrentDirectory(256, sDir);
  SetCurrentDirectory(sRawBank);
  SCR_fn_v_RdL0_ComputeSectionName(sRoot, sFileSpo, M_SuperObject, M_Root);
  // load module hierarchy
  if(SCR_fn_c_RdL0_IsSectionExists(sRoot))
  {
	p_stVal = SCR_fnp_st_RdL0_AnalyseSection(sRoot, SCR_CDF_uw_Anl_Normal);
	g_hBankRoot = (MLT_tdxHandleToSuperObject)SCR_M_ul_RdL0_ExtractLongValue(p_stVal,0);
	g_bExistSpoBank=TRUE;
  }
  else
	g_bExistSpoBank=FALSE;

  // if necessary, load RLI
  if(g_bGenerateRLI) 
	  MLT_vLoadLG2();

  // restore directory
  SetCurrentDirectory(sDir);

  // DISPLAY
  MLT_vOutput( C_ComRes_cNormalLine, "\n\tCreate Physical...");

  // build physical sections
  MLT_vMakePhysicalInLib();

  // change directory
  SetCurrentDirectory(sGameBank); 

  // DISPLAY
  MLT_vOutput( C_ComRes_cNormalLine, "\n\tSave...");

  // save MOD file
  MLT_vSaveLibInModFile(FALSE, FALSE, FALSE, TRUE);
  // save PLG file
  MLT_vSaveLibInPLGFile();

  // if necessary, remove old files
  g_bExistMdf = FALSE;
  g_bExistMdt = FALSE;
  if (g_bEraseMdf)	
  {	
	  strcpy (sFile, sGameBank);
	  sprintf(sFileM, "%s.mdf", sModName);
	  strcat(sFile, sFileM);
      _chmod(sFile, _S_IREAD | _S_IWRITE );
	  f = remove(sFile);		//remove the old gmt file
	  if (f != -1) 
	    g_bExistMdf = TRUE;

	  strcpy (sFile, sGameBank);
	  sprintf(sFileM, "%s.mdt", sModName);
	  strcat(sFile, sFileM);
      _chmod(sFile, _S_IREAD | _S_IWRITE );
	  f = remove(sFile);		//remove the old gmt file
	  if (f != -1) 
	    g_bExistMdt = TRUE;
  }

  // save all notified sections
  SCR_fn_v_SvL1_UpdateAllNotify();


  // create basic family
  if (g_bCreateBasicFamily && fileF)
  { 
	if (!l && (j!=2))
	{	
		sprintf(sFile, "%s\\%s\\%s.a3d", sRawAnims, sBankName, sBankName);
		SCR_fn_v_SvL1_RegisterNotify(sFile, MLT_vSaveA3dFile, NULL, SCR_EA_Ntfy_AddOrModifySection);
		// save all notified sections
		SCR_fn_v_SvL1_UpdateAllNotify();
	}

	// the family is already converted in the destination directory, keep it
	if (k != 7) 
	{	
		if (j != 2)
		{	
			sprintf(sFile, "%s\\%s\\%s.obj", sRawFamily, sBankName, sBankName);
			SCR_fn_v_SvL1_RegisterNotify(sFile, MLT_vSaveObjFile, NULL, SCR_EA_Ntfy_AddOrModifySection);
			sprintf(sFile, "%s\\%s\\%s.chl", sRawFamily, sBankName, sBankName);

			SCR_fn_v_SvL1_RegisterNotify(sFile, MLT_vSaveChlFile, NULL, SCR_EA_Ntfy_AddOrModifySection);
			// save all notified sections
			SCR_fn_v_SvL1_UpdateAllNotify();
		}
	    if (!l && (j!=2))
		{	
			//convert the animation 
			sprintf(sFile, "%s\\%s", sRawAnims, sBankName);

			GetCurrentDirectory(256, sDir);
			SetCurrentDirectory(sFile);
			MLT_vComputeOneAnim(sBankName, sRawData, sGameData);
			SetCurrentDirectory(sDir);
		}
		//convert the family 
		sprintf(sFile, "%s\\%s\\", sRawFamily, sBankName);
		GetCurrentDirectory(256, sDir);
		SetCurrentDirectory(sFile);
		g_cCategoryType = C_Family;
		MLT_vComputeOneFamily(sBankName, sRawData, sGameData);
		SetCurrentDirectory(sDir);
	}
  }

  if (fileF)
	  fclose(fileF);

  g_cCategoryType = C_Bank;

  // if necessary, create
  if (g_bGenerateRLI) 
	  MLT_vCreateRLI();

  // erase the libs
  MLT_vEraseLib();
  MLT_vErasePLGLib();

  // update ModifLst file
  MLT_vUpdatePathInModifFile(sGameBank);


  // close all opened files for VSE
  SCR_fn_v_RdL0_Close();
  strcpy(sFile, sGameBank);
  strcat(sFile, "temp.vse");
  remove(sFile);
  MLT_vInitSystem();

  // close all opened files for GMT
  if (g_bCreatedGmt && !g_bIgnoreGmt)	
  {	
	  SCR_fn_v_RdL0_Close();
	  strcpy (sFile, sGameBank);
	  strcat(sFile, "temp.gmt");
      _chmod(sFile, _S_IREAD | _S_IWRITE );
	  remove(sFile);		//remove the old gmt file
	  MLT_vInitSystem();
  }

  // DISPLAY
  MLT_vOutput( C_ComRes_cResultLine, "\nBank %s converted\n",sModName);

  // clean all opened structures
  for (i=3; i<256; i++)
	_close((int)i);
  MLT_vInitSystem();


// multitextures
  if (g_bIgnoreTex && g_bExistTex)
  {
	  strcpy (sFile, sGameBank);
	  sprintf(sFileM, "%s.tex", sBankName);
	  strcat(sFile, sFileM);

	  strcpy (sFile1, sGameBank);
	  strcat(sFile1, "temp.tex");

	  fileR=fopen(sFile1, "rt");
	  file =fopen(sFile, "r+");
	  if (!fileR) return;
	  if (!file) return;

	  while (!feof(fileR))
	  {
		fgets(sRead, 256, fileR);
		if (strstr(sRead, "Texture"))
		{	//a new section begins
			MLT_vSearch(sRead, file);
			fputs(sRead, file);
			fgets(sRead, 256, fileR);
			while (!strstr(sRead, "}"))
			{	fputs(sRead, file);
				fgets(sRead, 256, fileR);
			}
		}
	  }
	  fclose(file);
	  fclose(fileR);
	  remove(sFile1);
  }
}


/****************************************************************************
*		Description:	search the specified section in the raw bank
*
*		Parameters:		sFile	: initial file to search in
*						sIdent	: name of the geometric object to search
*						sFamily : return the family
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
BOOL MLT_bFindFileInBank (char *sFile, char *sIdent, char *sFamily)
{
  xString			sDirectory, sSection, sDirs, sDir1;
  HANDLE			hHandle;
  WIN32_FIND_DATA	stFindFileData;

  // change directory
  GetCurrentDirectory(256, sDirectory);
  SetCurrentDirectory(g_sRawData);

  // first: search in the specified bank
  if (g_bStandardConfig)
  {	
	SetCurrentDirectory(g_sRawData);
	// first: search in the specified bank
	sprintf(sDirs, "World\\Graphics\\Objects\\Banks\\%s", sFile);
  }
  else
  { //SetCurrentDirectory(g_szBanks);
	sprintf(sDirs, "%s\\%s", g_szBanks, sFile);
  }

  SCR_fn_v_RdL0_ComputeSectionName(sSection, sDirs, M_Geometric, sIdent);
  if(SCR_fn_c_RdL0_IsSectionExists(sSection))
  {
    // the first is the best
    sprintf(sFamily, "%s", sFile);
	// restore directory
	SetCurrentDirectory(sDirectory);
	// file was found
    return TRUE;
  }

  // if not : search in all the banks
  memset(&stFindFileData,0,sizeof(stFindFileData));
  if (g_bStandardConfig)
	hHandle = FindFirstFile("World\\Graphics\\Objects\\Banks\\*.mod", &stFindFileData);
  else
  {	
    sprintf(sDir1, "%s\\*.mod", g_szBanks);
	hHandle = FindFirstFile(sDir1, &stFindFileData);
  }
  
  // no bank in Raw directory ?
  if( hHandle == INVALID_HANDLE_VALUE)
  {
	// DISPLAY
	if (g_bStandardConfig)
		MLT_vOutput( C_ComRes_cErrorLine, "\nError : No banks in %s", g_sRawData);
	else
		MLT_vOutput( C_ComRes_cErrorLine, "\nError : No banks in %s", g_szBanks);

	// erase name
    sprintf(sFamily, "%s", sFile);
     // restore directory
	SetCurrentDirectory(sDirectory);
	// file was not found
	return FALSE;
  }
  
  // search all banks
  do if(stFindFileData.dwFileAttributes)
  {
    if(strlen(stFindFileData.cFileName) == 0) break;
    
    // search in current bank
	if (g_bStandardConfig)
		sprintf(sDirs, "World\\Graphics\\Objects\\Banks\\%s", stFindFileData.cFileName);
	else
		sprintf(sDirs, "\\%s", stFindFileData.cFileName);

    SCR_fn_v_RdL0_ComputeSectionName(sSection, sDirs, M_Geometric, sIdent);
    if(SCR_fn_c_RdL0_IsSectionExists(sSection))
    {
      // the first is the best
	  sprintf(sFamily, "%s", stFindFileData.cFileName);
	  // restore directory
	  SetCurrentDirectory(sDirectory);
	  // file was found
      return TRUE;
    }
  }
  while(FindNextFile(hHandle, &stFindFileData));
  FindClose(hHandle);

  // restore directory
  SetCurrentDirectory(sDirectory);
  // file was not found
  return FALSE;
}


/****************************************************************************
*		Description:	search the specified section in the game bank
*
*		Parameters:		sFile	: initial file to search in
*						sIdent	: name of the geometric object to search
*						sFamily : return the family
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
BOOL MLT_bFindFileInBankInGameData (char *sFile, char *sIdent, char *sFamily)
{
  BOOL		bResult;
  xString	sDirectory; 

  // save current directory
  GetCurrentDirectory(256, sDirectory);

  // search in the appropriate directories
  switch(g_iData) 
  {	
    case 0:
			// GameData
			MLT_vFindInDir(sDirectory, g_sGameCommon, sFile, sIdent, sFamily, &bResult);
			if (bResult) 
				return TRUE;
			// GameSpecific1
			MLT_vFindInDir(sDirectory, g_sGameSpecific1, sFile, sIdent, sFamily, &bResult);
			if (bResult) 
				return TRUE;
			// GameSpecific2
			MLT_vFindInDir(sDirectory, g_sGameSpecific2, sFile, sIdent, sFamily, &bResult);
			if (bResult) 
				return TRUE;
			break;
	case 1:
			// GameSpecific1
			MLT_vFindInDir(sDirectory, g_sGameSpecific1, sFile, sIdent, sFamily, &bResult);
			if (bResult) 
				return TRUE;
			// GameData
			MLT_vFindInDir(sDirectory, g_sGameCommon, sFile, sIdent, sFamily, &bResult);
			if (bResult) 
				return TRUE;
			// GameSpecific2
			MLT_vFindInDir(sDirectory, g_sGameSpecific2, sFile, sIdent, sFamily, &bResult);
			if (bResult) 
				return TRUE;
			break;
	case 2:
			// GameSpecific2
			MLT_vFindInDir(sDirectory, g_sGameSpecific2, sFile, sIdent, sFamily, &bResult);
			if (bResult) 
				return TRUE;
			// GameData
			MLT_vFindInDir(sDirectory, g_sGameCommon, sFile, sIdent, sFamily, &bResult);
			if (bResult) 
				return TRUE;
			// GameSpecific1
			MLT_vFindInDir(sDirectory, g_sGameSpecific1, sFile, sIdent, sFamily, &bResult);
			if (bResult) 
				return TRUE;
			break;
  }

  // restore directory
  SetCurrentDirectory(sDirectory);

  // file was not found
  return FALSE;
}


/****************************************************************************
*		Description:	search the specified section in the given directory
*
*		Parameters:		sDirectory	: current directory
*						sGame		: name of directory to search in
*						sFile		: initial file to search in
*						sIdent		: name of the geometric object to search
*						sFamily		: return the family
*						bRes		: return the result
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vFindInDir (xString sDirectory, xString sGame, char* sFile, char *sIdent, char *sFamily, BOOL *bRes)
{
  xString			sSection, sDirs, sFileExe;
  HANDLE			hHandle;
  WIN32_FIND_DATA	stFindFileData;

  // init result
  *bRes = FALSE;
  
  if (strcmp(sGame, ""))
  {
	// change directory
	SetCurrentDirectory(sGame);
	
	// init serach data
	strcpy(sFileExe, MLT_p_cGetFileNameWithoutExt(sFile));

	// first: search in the specified bank
	sprintf(sDirs, "World\\Graphics\\Objects\\Banks\\%s\\%s", sFileExe, sFile);
	SCR_fn_v_RdL0_ComputeSectionName(sSection, sDirs, M_Geometric, sIdent);
	if(SCR_fn_c_RdL0_IsSectionExists(sSection))
	{
		// the first is the best
		sprintf(sFamily, "%s", sFile);
		SetCurrentDirectory(sDirectory);
		*bRes = TRUE;
		return;
	}

	// if not : search in all the bank's
	memset(&stFindFileData,0,sizeof(stFindFileData));
	sprintf(sDirs, "World\\Graphics\\Objects\\Banks\\*");
	hHandle = FindFirstFile(sDirs, &stFindFileData);
	if( hHandle == INVALID_HANDLE_VALUE)
	{
		SetCurrentDirectory(sDirectory);
		sprintf(sFamily, "%s", sFile);
	}
	else {
		do if(stFindFileData.dwFileAttributes)
		{
			if(strlen(stFindFileData.cFileName) == 0) break;
		    if(strcmp(stFindFileData.cFileName, ".") == 0) continue;
			if(strcmp(stFindFileData.cFileName, "..") == 0) continue;
			// search in current bank
			sprintf(sDirs, "World\\Graphics\\Objects\\Banks\\%s\\%s.mod", stFindFileData.cFileName, sFileExe);
			SCR_fn_v_RdL0_ComputeSectionName(sSection, sDirs, M_Geometric, sIdent);
			if(SCR_fn_c_RdL0_IsSectionExists(sSection))
			{
				sprintf(sFamily, "%s", stFindFileData.cFileName);
				SetCurrentDirectory(sDirectory);
				*bRes = TRUE;
				return;
			}
		} while(FindNextFile(hHandle, &stFindFileData));
		FindClose(hHandle);
	}
  }
}




/****************************************************************************
*		Description:	find if the file exist in a directory
*
*		Parameters:		sBankName	: bank to convert
*						sRawData	: source directory
*						sDir		: source sub-directory
*						sExt		: the extension of the file
*						j			: 1 if the file exists
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vExistFile (char *sBankName, char *sRawData, char *sDir, char *sExt, int *j)
{
  xString	sFile;
  FILE		*file;

  sprintf(sFile, "%s%s%s\\%s.%s", sRawData, sDir, sBankName, sBankName, sExt);
  if (file = fopen(sFile, "r"))
  {	
	(*j)++; 
    fclose(file);
  }
}


/****************************************************************************
*		Description:	find if the file exist in a bank directory
*
*		Parameters:		sBankName	: bank to convert
*						sRawData	: source directory
*						sExt		: the extension of the file
*						j			: 1 if the file exists
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vExistFileInBank (char *sBankName, char * sDir, char *sExt, int *j)
{
  xString	sFile;
  FILE		*file;

  sprintf(sFile, "%s\\%s\\%s.%s", sDir, sBankName, sBankName, sExt);
  if (file = fopen(sFile, "r"))
  {	
	(*j)++; 
    fclose(file);
  }
}


/****************************************************************************
*		Description:	compute the MOD file in the specified bank
*
*		Parameters:		jj	: number of common files found
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vGetCommonExt (int *jj)
{	
	*jj=0;

	// for each family extension, test if it is a specific one
	if (!MLT_bSearchExt ("ace")) 
	{	
		strcpy(gs_szFilesCommon[*jj], "ace");
		(*jj)++;
	}
	if (!MLT_bSearchExt ("acz")) 
	{	
		strcpy(gs_szFilesCommon[*jj], "acz");
		(*jj)++;
	}
	if (!MLT_bSearchExt ("sta")) 
	{	
		strcpy(gs_szFilesCommon[*jj], "sta");
		(*jj)++;
	}
	if (!MLT_bSearchExt ("phy")) 
	{	
		strcpy(gs_szFilesCommon[*jj], "phy");
		(*jj)++;
	}
	if (!MLT_bSearchExt ("tbl")) 
	{	
		strcpy(gs_szFilesCommon[*jj], "tbl");
		(*jj)++;
	}
	if (!MLT_bSearchExt ("zoo")) 
	{	
		strcpy(gs_szFilesCommon[*jj], "zoo");
		(*jj)++;
	}
	if (!MLT_bSearchExt ("chl")) 
	{	
		strcpy(gs_szFilesCommon[*jj], "chl");
		(*jj)++;
	}
}
