/*=========================================================================
*
* Main.c	- global functions
*
* Version			1.0
* Revision date
*
*=======================================================================*/
#include <windows.h>
#include <stdio.h>
#include <conio.h>

#define __DeclareGlobalVariableErrMlt_h__
#include "ErrMlt.h"
#undef __DeclareGlobalVariableErrMlt_h__

#define __DeclareGlobalVariableMemMlt_h__
#include "MemMlt.h"
#undef __DeclareGlobalVariableMemMlt_h__


#include "Main.h"

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

#include "Actors.h"
#include "Anims.h"
#include "Banks.h"
#include "Classes.h"
#include "Families.h"
#include "Levels.h"
#include "Textures.h"

#include "ModLib.h"
#include "ModLoad.h"
#include "ObjLoad.h"
#include "LgtLoad.h"
#include "PlgLoad.h"
#include "SctLoad.h"
#include "SpoLoad.h"
#include "VseLoad.h"
#include "ZooLoad.h"

#include "SaveModifLst.h"



//--- Global defines (main.h) --------------------------------------------------------

// current version
char g_fVersion[9] = "7.0.0";
BOOL g_bVersionN64;

// modes
BOOL g_bOneAnimMode,	g_bAnimMode;
BOOL g_bOneBankMode,	g_bBankMode;
BOOL g_bOneClassMode,	g_bClassMode;
BOOL g_bOneLevelMode,	g_bLevelMode;
BOOL g_bOneFamilyMode,	g_bFamilyMode;
BOOL g_bOneTextureMode, g_bTextureMode;

// data
MLT_tdeCategory g_cCategoryType;

xString	g_sAnim[100];
xString	g_sBank[100];
xString	g_sClass[100];
xString	g_sLevel[100];
xString	g_sFamily[100];
xString	g_sTexture[100];

long	g_lAnimNum;
long	g_lBankNum;
long	g_lClassNum;
long	g_lLevelNum;
long	g_lFamilyNum;
long	g_lTextureNum;

// directories
xString g_sInitialDir;
xString g_sRawData;
xString g_sGameData;

xString g_sFileIn, g_sDirectorySave, g_sFileMaterial;


//--- Global defines (system.h) --------------------------------------------------------

// index of chosen directories
int g_iData = 0;
int g_iRaw	= 0;

// paths for directories
xString	g_sGameCommon;
xString	g_sRawCommon;
xString	g_sGameSpecific1;
xString	g_sRawSpecific1;
xString g_sGameSpecific2;
xString	g_sRawSpecific2;

xString		g_sGameTextureDirectory;

//--- Global defines (print.h) --------------------------------------------------------

// main options
BOOL g_bRaymanII		= FALSE;
BOOL g_bModifLst		= FALSE;
BOOL g_bEraseMdf		= TRUE;
// ignore options
BOOL g_bIgnoreZoo		= FALSE;
BOOL g_bIgnoreSct		= TRUE;
BOOL g_bIgnoreSpo		= TRUE;
BOOL g_bIgnoreGmt		= TRUE;
BOOL g_bIgnoreTex		= TRUE;
// conversion options
BOOL g_bCopyAnims		= FALSE;
BOOL g_bCopyTextures	= FALSE;
BOOL g_bGenerateRLI;
BOOL g_bUpdateGameDSC;
// erase options
BOOL g_bEraseDuplicated;
BOOL g_bEraseUnused;
// family options
BOOL g_bCommonFamily	= FALSE;
BOOL g_bSpecificFamily	= FALSE;
BOOL g_bAskFamily		= TRUE;
BOOL g_bApplyAll		= FALSE;
// bank options
BOOL g_bCreateBasicFamily = FALSE;

// existence of files
BOOL g_bCreatedSpo;
BOOL g_bCreatedGmt;
BOOL g_bExistSpo		= TRUE;
BOOL g_bExistMdf		= FALSE;
BOOL g_bExistMdt		= FALSE;
BOOL g_bExistSpoBank;



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

// names
xString gs_szNewName;



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


/****************************************************************************
*		Description:	Main function (DOS)
*
*		Parameters:		
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
#ifndef _WINDOWS
void main (int argc, char **argv)
{
  MLT_fn_vMainConvert( argc, argv );
}
#endif



/****************************************************************************
*		Description:	Main function 
*
*		Parameters:		
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_fn_vMainConvert (int argc, char **argv)
{
  long i;
  
  // save initial directory
  GetCurrentDirectory(256, g_sInitialDir);

  // init system parameters
  MLT_vInitSystem();
  // init main variables
  MLT_vInitVariables();

  // set default directory
  sprintf(g_sRawData, "%s\\RawData", g_sInitialDir);
  sprintf(g_sGameData, "%s\\GameData", g_sInitialDir);
  
  // analyse parameters
  for(i=1; i<argc; i++)
  {
    if( argv[i][0] != '-')
    {
      fprintf(stderr, "\nError : Invalid param : %s\n", argv[i]);
      MLT_vExitSystem();
    }

    switch(toupper(argv[i][1]))
    {
	case 'A' :
	  // one animation mode
      if(g_bOneAnimMode)
        g_bOneAnimMode = (argv[i][2] != '+');
      // animation mode
	  g_bAnimMode = TRUE;
      // add animation to convert
	  sprintf(g_sAnim[g_lAnimNum], "%s", argv[i]+2);
      g_lAnimNum++;
      break;

    case 'B' :
	  // one bank mode
      if(g_bOneBankMode)
        g_bOneBankMode = (argv[i][2] != '+');
      // bank mode
      g_bBankMode = TRUE;
      // add bank to convert
      sprintf(g_sBank[g_lBankNum], "%s", argv[i]+2);
      g_lBankNum++;
      break;

    case 'C' :
	  // one class mode
      if(g_bOneClassMode)
        g_bOneClassMode = (argv[i][2] != '+');
      // class mode
      g_bClassMode = TRUE;
      // add class to convert
      sprintf(g_sClass[g_lClassNum], "%s", argv[i]+2);
      g_lClassNum++;
      break;

    case 'F' :
	  // one family mode
      if(g_bOneFamilyMode)
        g_bOneFamilyMode = (argv[i][2] != '+');
	  // family mode
      g_bFamilyMode = TRUE;
      // add family to convert
      sprintf(g_sFamily[g_lFamilyNum], "%s", argv[i]+2);
      g_lFamilyNum++;
      break;

    case 'L' :
	  // one level mode
      if(g_bOneLevelMode)
        g_bOneLevelMode = (argv[i][2] != '+');
      // level mode
      g_bLevelMode = TRUE;
      // add level to convert
      sprintf(g_sLevel[g_lLevelNum], "%s", argv[i]+2);
      g_lLevelNum++;
      break;

    case 'R' :
      // get RawData directory
	  if(  ((argv[i]+2)[0] == '\\')
        || ((argv[i]+2)[0] == '/')
        || ((argv[i]+2)[1] == ':') )
        sprintf(g_sRawData, "%s", argv[i]+2);
      else
        sprintf(g_sRawData, "%s\\%s", g_sInitialDir, argv[i]+2);
      break;

    case 'G' :
      // get GameData directory
      if(  ((argv[i]+2)[0] == '\\')
        || ((argv[i]+2)[0] == '/')
        || ((argv[i]+2)[1] == ':') )
        sprintf(g_sGameData, "%s", argv[i]+2);
      else
        sprintf(g_sGameData, "%s\\%s", g_sInitialDir, argv[i]+2);
      break;

    case 'S' :
      // texture option
	  if(  (toupper((argv[i]+2)[0]) == 'T')
        && (toupper((argv[i]+2)[1]) == 'G')
        && (toupper((argv[i]+2)[2]) == 'A') )
			g_bCopyTextures=TRUE;
      // super-object option
      if(  (toupper((argv[i]+2)[0]) == 'P')
        && (toupper((argv[i]+2)[1]) == 'O'))
			g_bIgnoreSpo = FALSE;
      // sectors option
      if(  (toupper((argv[i]+2)[0]) == 'C')
        && (toupper((argv[i]+2)[1]) == 'T'))
			g_bIgnoreSct = FALSE;
	  break;

    case 'M' :
      // zones option
	  if(  (toupper((argv[i]+2)[0]) == 'Z')
        && (toupper((argv[i]+2)[1]) == 'O')
        && (toupper((argv[i]+2)[2]) == 'O') )
      g_bIgnoreZoo = TRUE;
      break;    

    case 'V' :
      // N64 option
	  if(  (toupper((argv[i]+2)[0]) == 'N')
        && (toupper((argv[i]+2)[1]) == '6')
        && (toupper((argv[i]+2)[2]) == '4') )
			g_bVersionN64 = TRUE;
      // material option
      if(  (toupper((argv[i]+2)[0]) == 'G')
        && (toupper((argv[i]+2)[1]) == 'M')
        && (toupper((argv[i]+2)[2]) == 'T') )
			g_bIgnoreGmt = FALSE;
      // version option
      if(  (toupper((argv[i]+2)[0]) == 'R')
        && (toupper((argv[i]+2)[1]) == 'I')
        && (toupper((argv[i]+2)[2]) == 'I'))
			g_bRaymanII = TRUE;

      break;    

    case 'H' :
      // help
      printf("Syntax : %s [-Mzoo] [-aAnim] [-lLevel] [-bBank] [-cClasse] [-fFamily] [-rRawData] [-gGameData]\n",argv[0]);
      printf("  -aAnim : Copy to GameData all the files in this anim only or all the anims if +\n");
      printf("  -lLevel : Compute this level only or all if +\n");
      printf("  -bBank : Compute this bank only or all if +\n");
      printf("  -cClasse : Compute this classe only or all if +\n");
      printf("  -fFamily : Compute this family only or all if +\n");
      printf("  -rRawData  : Graphics's directory (default is \"RawData\")\n");
      printf("  -gGameData : 3Dos's directory (default is \"GameData\")\n");
      printf("  -mZoo : Rebuild the .Zoo file for the family\n");
      printf("  -tTexture : Specify the textures directory in Rawdata\n");
      printf("  -vN64 : Exclusif for Nintendo 64\n");
      printf("\n");
      printf("Exemple : Max23Dos -l+ -bNavet\n");
      printf("  This command compute all the levels and the Navet bank\n");
      printf("  from the directory \"RawData\" to the directory \"GameData\"\n");
      MLT_vExitSystem();
      break;    
    }
  }
  printf("\n");

  // verify the GameData
  if( !SetCurrentDirectory(g_sGameData) )
  {
    fprintf(stderr, "\nError : the directory %s does not exist\n", g_sGameData);
    MLT_vExitSystem();
  }

  SetCurrentDirectory(g_sInitialDir);

  // verify the RawData
  if( !SetCurrentDirectory(g_sRawData) )
  {
    fprintf(stderr, "\nError : the directory %s does not exist\n", g_sRawData);
    MLT_vExitSystem();
  }
  MLT_vSetData();

  // compute the anim if there is one
  g_cCategoryType = C_Anim;
  if(g_bAnimMode)
  {
    if(g_bOneAnimMode)
      for(i=0; i<g_lAnimNum; i++)
        MLT_vComputeOneAnim(g_sAnim[i], g_sRawData, g_sGameData);
    else
      MLT_vComputeAllAnims(g_sRawData, g_sGameData);
  printf("\n");
  }

  // compute the bank if there is one
  g_cCategoryType = C_Bank;
  if(g_bBankMode)
  {
    if(g_bOneBankMode)
      for(i=0; i<g_lBankNum; i++)
        MLT_vComputeOneBank(g_sBank[i], g_sRawData, g_sGameData);
    else
      MLT_vComputeAllBanks(g_sRawData, g_sGameData);
  printf("\n");
  }

  // compute the class if there is
  g_cCategoryType = C_Classe;
  if(g_bClassMode)
  {
    if(g_bOneClassMode)
      for(i=0; i<g_lClassNum; i++)
        MLT_vComputeOneClass(MLT_p_cGetFileNameWithoutExt(g_sClass[i]), g_sRawData, g_sGameData);
    else
      MLT_vComputeAllClasses(g_sRawData, g_sGameData);
  printf("\n");
  }
  SetCurrentDirectory(g_sInitialDir);

  // compute the family if there is one
  g_cCategoryType = C_Family;
  if(g_bFamilyMode)
  {
    if(g_bOneFamilyMode)
      for(i=0; i<g_lFamilyNum; i++)
        MLT_vComputeOneFamily(g_sFamily[i], g_sRawData, g_sGameData);
    else
      MLT_vComputeAllFamilies(g_sRawData, g_sGameData);
  printf("\n");
  }

  // compute the level if there is one
  g_cCategoryType = C_Level;
  if(g_bLevelMode)
  {
	MLT_vReadSPOFlagsFile(g_sRawData);
    if(g_bOneLevelMode)
      for(i=0; i<g_lLevelNum; i++)
        MLT_vComputeOneLevel(g_sLevel[i], g_sRawData, g_sGameData);
    else
      MLT_vComputeAllLevels(g_sRawData, g_sGameData);
  printf("\n");
  }

  // desinit system
  MLT_vExitSystem();
}


/****************************************************************************
*		Description:	global initialisations
*
*		Parameters:		
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vInitSystem()
{
  // memory
  Mmg_fn_vFirstInitMmgModule(1);
  // scripts
  SCR_fn_v_RdL0_Init();
  
  // register loading functions
  MLT_vInitMODLoad();
  MLT_vInitPLGLoad();
  MLT_vInitALWLoad();
  MLT_vInitSPOLoad();
  MLT_vInitOBJLoad();
  MLT_vInitSCTLoad();
  MLT_vInitZOOLoad();
  MLT_vInitVSELoad();
  MLT_vInitLVLLoad();

  // init modes
  g_bOneAnimMode = TRUE;
  g_bOneBankMode = TRUE;
  g_bOneClassMode = TRUE;
  g_bOneLevelMode = TRUE;
  g_bOneFamilyMode = TRUE;

  // display version number
  printf("Convertion utility 3DSMAX to 3DOS v%s.\n",g_fVersion);
}


/****************************************************************************
*		Description:	global desinitialisations
*
*		Parameters:		
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vExitSystem()
{
  // scripts
  SCR_fn_v_RdL0_Close();
  
  // erase libraries
  MLT_vEraseLib();
  MLT_vErasePLGLib();
  MLT_vEraseALWLib();
  MLT_vEraseLGTLib();
  // delete hierarchy
  MLT_vDeleteHierarchy(g_hRoot);

  // display end message
  printf("\nPress a key\n");
  while(!getch());
  
  exit(0);
}


/****************************************************************************
*		Description:	create and register all game directories
*
*		Parameters:		
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vSetData ()
{ 
  xString sComment;

  // init ModifLst file
  sprintf(sComment, "%s\\%s", g_sGameData, M_TempSCR_Modif);
  SCR_fn_v_SvL1_SetModificationFileName(sComment);

  // register rawdata directory
  sprintf(g_sRawData, "%s", g_sRawData);
  
  // change directory
  SetCurrentDirectory(g_sGameData);
  
  // create sub directories of GameData
  CreateDirectory("World", NULL);
  CreateDirectory("World\\Graphics", NULL);
  CreateDirectory("World\\Graphics\\Anims", NULL);
  CreateDirectory("World\\Graphics\\Textures", NULL);
  CreateDirectory("World\\Graphics\\Objects", NULL);
  CreateDirectory("World\\Graphics\\Objects\\Classes", NULL);
  CreateDirectory("World\\Graphics\\Objects\\Banks", NULL);
  CreateDirectory("World\\Graphics\\Visuals", NULL);
  CreateDirectory("World\\Libraries", NULL);
  CreateDirectory("World\\Libraries\\Materials", NULL);
  CreateDirectory("World\\Levels", NULL);
  CreateDirectory("World\\Levels\\_Common", NULL);
  CreateDirectory("World\\Levels\\_Common\\Families", NULL);
  
  // set the materials and textures directories
  sprintf(g_sGameTextureDirectory, "%s\\World\\Graphics\\Textures", g_sGameData);

  // register current position in modiflst
  MLT_vSavePosInModifFile();
}


/****************************************************************************
*		Description:	init main variables before conversion
*
*		Parameters:		
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vInitVariables ()
{
  // no action by default
  g_bAnimMode = FALSE;
  g_bBankMode = FALSE;
  g_bClassMode = FALSE;
  g_bLevelMode = FALSE;
  g_bFamilyMode = FALSE;
  g_bVersionN64 = FALSE;
  // no conversion by default
  g_lLevelNum = 0;
  g_lBankNum = 0;
  g_lAnimNum = 0;
  g_lClassNum = 0;
  g_lFamilyNum = 0;
  g_lTextureNum = 0;
}


/****************************************************************************
*		Description:	test the existence of the specified file
*
*		Parameters:		sDir		: directory name
*						sFile		: file name
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
long MLT_bFindFile (char *sDir, char *sFile)
{
  char				*p_cName;
  BOOL				bRet;
  xString			sDirectory, sTemp;
  HANDLE			hHandle;
  WIN32_FIND_DATA	stFindFileData;

  // search file in the given directory
  if (SearchPath(sDir, sFile, NULL, 256, sTemp, &p_cName))
  {
    return TRUE;
  }

  // change directory
  GetCurrentDirectory(256, sDirectory);
  if (SetCurrentDirectory(sDir) == 0)
    return FALSE;

  // search for the subdirectories
  memset(&stFindFileData,0,sizeof(stFindFileData));
  hHandle = FindFirstFile("*.*", &stFindFileData);
  if( hHandle == INVALID_HANDLE_VALUE)
  {
    SetCurrentDirectory(sDirectory);
	MLT_vOutput( C_ComRes_cErrorLine, "\nError : Can't find %s", sDir);
    return FALSE;
  }

  do if(stFindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  {
    if(strlen(stFindFileData.cFileName) == 0) break;
    if(strcmp(stFindFileData.cFileName, ".") == 0) continue;
    if(strcmp(stFindFileData.cFileName, "..") == 0) continue;

    // search in subdirectory
	sprintf(sTemp, "%s\\%s", sDir, stFindFileData.cFileName);
    bRet = MLT_bFindFile(sTemp, sFile);
    SetCurrentDirectory(sDir);

    // if file was found, stop here
	if(bRet)
    {
      SetCurrentDirectory(sDirectory);
      sprintf(sDir, "%s", sTemp);
	  FindClose(hHandle);
      return TRUE;
    }
  }
  while(FindNextFile(hHandle, &stFindFileData));
  FindClose(hHandle);

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


/****************************************************************************
*		Description:	copy file from sSrc to sDst directory
*
*		Parameters:		sFile		: file name
*						sSrc		: source directory
*						sDst		: destination directory
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vCopyFiles (char *sFile, char *sSrc, char *sDst)
{
  xString			sDirectory, sName;
  HANDLE			hHandle;
  WIN32_FIND_DATA	stFindFileData;

  // change directory
  GetCurrentDirectory(256, sDirectory);
  CreateDirectory(sDst, NULL);
  SetCurrentDirectory(sSrc);

  // search for source file
  memset(&stFindFileData,0,sizeof(stFindFileData));
  hHandle = FindFirstFile(sFile, &stFindFileData);
  if( hHandle == INVALID_HANDLE_VALUE)
  {
    SetCurrentDirectory(sDirectory);
	MLT_vOutput( C_ComRes_cErrorLine, "\nError : Can't find %s\\%s", sSrc, sFile);
    return;
  }
  
  do
  {
    xString sFileDst;

    if (strlen(stFindFileData.cFileName) == 0) 
		break;

    // get complete file name for destination
	sprintf(sFileDst, "%s\\%s", sDst, stFindFileData.cFileName);
    // copy file
	SetCurrentDirectory(sSrc);
	CopyFile(stFindFileData.cFileName, sFileDst, FALSE);
	// update ModifLst.txt file
	strcpy(sName, "AAA\\");
	strcat(sName, stFindFileData.cFileName);
    if (!strstr(sFileDst, "Families")) 
	{	
		MLT_vAddEntryToModifFile(sName);
		MLT_vAddEntryToModifFile("\n");
	}
  }
  while(FindNextFile(hHandle, &stFindFileData));
  FindClose(hHandle);

  // restore directory
  SetCurrentDirectory(sDirectory);
}

/****************************************************************************
*		Description:	copy and rename file
*
*		Parameters:		_sFileSrc	: source file
*						_sDirSrc	: source directory
*						_sFileDst	: destination file
*						_sDirDst	: destination directory
*						bErase		: flag : erase or preserve existing file
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vCopyAndRenameFile (char *_sFileSrc, char *_sDirSrc, char *_sFileDst, char *_sDirDst, BOOL bErase)
{
  xString	sDirectory, sFileSrc, sFileDst, sTemp;
  char		*p_cName;

  // save directory
  GetCurrentDirectory(256, sDirectory);
  
  // search destination file
  CreateDirectory(_sDirDst, NULL);
  sprintf(sFileDst, "%s\\%s", _sDirDst, _sFileDst);
  // check that the target file does not exist or must be erased
  if (!bErase && (SearchPath( NULL,sFileDst,NULL,256,sTemp,&p_cName) != 0)) 
	  return; 

  // search source file
  CreateDirectory(_sDirSrc, NULL);
  sprintf(sFileSrc, "%s\\%s", _sDirSrc, _sFileSrc);
  // check that the source file existd 
  if (SearchPath( NULL,sFileSrc,NULL,256,sTemp,&p_cName) == 0) 
	  return; 

  // copy file
  CopyFile(sFileSrc, sFileDst, FALSE);

  // restore directory
  SetCurrentDirectory(sDirectory);
}

/****************************************************************************
*		Description:	copy file and replace source reference with new one
*
*		Parameters:		_sFileSrc	: source file
*						_sDirSrc	: source directory
*						_sFileDst	: destination file
*						_sDirDst	: destination directory
*						_SrcRef		: source reference
*						_DstRef		: destination reference
*						bErase		: flag : erase or preserve existing file
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vCopyAndUpdateFile(char *_sFileSrc, char *_sDirSrc, char *_sFileDst, char *_sDirDst, char *_SrcRef, char *_DstRef, BOOL bErase)
{
  xString	sDirectory, sFileDst, sFileSrc;
  xString	sRead, sWrite, sEnd, sTemp;
  FILE		*fileR, *fileW;
  char		*p_cName, *p_cChar;
  
  // save directory
  GetCurrentDirectory(256, sDirectory);

  // search destination file
  CreateDirectory(_sDirDst, NULL);
  sprintf(sFileDst, "%s\\%s", _sDirDst, _sFileDst);
  // check that the target file does not exist or must be erased
  if (!bErase && (SearchPath( NULL,sFileDst,NULL,256,sTemp,&p_cName) != 0)) 
	  return; 

  // search source file
  CreateDirectory(_sDirSrc, NULL);
  sprintf(sFileSrc, "%s\\%s", _sDirSrc, _sFileSrc);

  // open files
  fileR = fopen(sFileSrc, "rt");
  fileW = fopen(sFileDst, "wt");
  if ((fileR==NULL) || (fileW==NULL))
	  return;

  // copy with updated reference
  while (fgets(sRead, 256, fileR) != NULL)
  {
	  strcpy(sWrite, "");
	  strcpy(sEnd, sRead);
	  // seach for reference
	  while ((p_cChar = strstr(sEnd, _SrcRef)) != NULL)
	  {
		  // replace it with new one
		  strcpy(sTemp, p_cChar + strlen(_SrcRef));
		  p_cChar[0] = '\0';
		  strcat(sWrite, sEnd);
		  strcat(sWrite, _DstRef);
		  strcpy(sEnd, sTemp);
	  }
	  strcat(sWrite, sEnd);
	  fputs(sWrite, fileW);
  }

  // close files
  fclose(fileR);
  fclose(fileW);
}



/****************************************************************************
*		Description:	copy one texture file from source to destination directory
*
*		Parameters:		sTextureName: name of texture file 
*						sRawData	: source directory
*						sGameData	: destination directory
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vCopyOneTexture(char *sTextureName, char *sRawData, char * sGameData)
{
    xString sDirectory, sGameTexturesLevel, sTypeName;

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

	// create destination texture subdirectory
	strcpy(sTypeName, strstr(sRawData, "\\Textures")+9);
	sprintf(sGameTexturesLevel, "%s\\World\\Graphics\\Textures%s", sGameData, sTypeName);
	CreateDirectory(sGameTexturesLevel, NULL);
	// get complete texture name
	strcat(sGameTexturesLevel, "\\");
	strcat(sGameTexturesLevel, sTextureName);
	// copy texture file
	CopyFile(sTextureName, sGameTexturesLevel,  FALSE);

	// restore directory
	SetCurrentDirectory(sDirectory);
}




/****************************************************************************
*		Description:	remove collision flags from the name
*
*		Parameters:		szName		: name to update 
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
char* MLT_vRemoveFromName (char *szName)
{
	char *p_Char;

	// find lowercase flag
	if (strstr(szName, "!nocol"))
		p_Char=strstr(szName, "!nocol");

	// find uppercase flag
	if (strstr(szName, "!NOCOL"))
		p_Char=strstr(szName, "!NOCOL");

	// remove flag
	strcpy(gs_szNewName, szName);
	gs_szNewName[strlen(szName) - strlen(p_Char)]='\0';
	p_Char+=6;
	strcat(gs_szNewName, p_Char);
	
	return gs_szNewName;
}


/****************************************************************************
*		Description:	return the file name whitout extension
*
*		Parameters:		_sFileName	: name to update 
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
char *MLT_p_cGetFileNameWithoutExt(char *_sFileName)
{
  char *p_char;
  static xString sFileName;

  sprintf(sFileName, "%s", _sFileName);
  p_char = sFileName;

  if ((p_char=strstr(sFileName, "."))!=NULL)
	*p_char = 0;

  return sFileName;
}

/****************************************************************************
*		Description:	return the file name whitout path
*
*		Parameters:		sFileName	: name to update 
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
char *MLT_p_cGetFileNameWithoutPath (char *sFileName)
{
  char *p_char;

  if (((p_char = strrchr( sFileName, '/')) != NULL) || ((p_char = strrchr( sFileName, '\\')) != NULL))
	p_char++;
  else
	p_char = sFileName;
	
  return p_char;
}



/****************************************************************************
*		Description:	replace all spaces with '_' character
*
*		Parameters:		sFileName	: name to update 
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
char *MLT_p_cEraseSpace (char *sFileName)
{
  char *p_char;

  p_char = sFileName;

  while ((p_char =strstr(sFileName, " "))!=NULL)
  {
    if (*p_char == ' ') 
		*p_char = '_';
  }

  return sFileName;
}


/****************************************************************************
*		Description:	return section name without the file. (file^section:name)
*
*		Parameters:		sFileName	: name to update 
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
char *MLT_p_cGetSectionName(char *sSection)
{
  return (strchr( sSection, '^') + 1);
}


/****************************************************************************
*		Description:	delete the spo flags from the name
*						(the spo flags are identified by the $ symbol)
*
*		Parameters:		sIdent		: pointer on the name to update 
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vRemoveFlags (char **sIdent )
{
  char *p_Char1, *p_Char2;
  char szName[50];

  if ((p_Char1=strstr(*sIdent, "$"))!=NULL) 
  {	
	p_Char2=p_Char1;
	p_Char1++;
    while( (*p_Char1 != 0) && (*p_Char1 != '|')
		&& (*p_Char1 != '#') && (*p_Char1 != '&')
		&& (*p_Char1 != '=') && (*p_Char1 != '_') )
		 p_Char1++;
	(*sIdent)[strlen(*sIdent)-strlen(p_Char2)]='\0';
	strcpy(szName, *sIdent);
	if (*p_Char1 != 0) 
		strcat(szName, p_Char1);
	strcpy(*sIdent, szName);
  }
}

/****************************************************************************
*		Description:	delete the geometric properties from the name
*						(the geometric properties are identified by the # symbol)
*
*		Parameters:		sIdent		: pointer on the name to update 
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vRemoveGeomProp (char **sIdent )
{
  char *p_Char1, *p_Char2;
  char szName[50];

  if ((p_Char1=strstr(*sIdent, "#"))!=NULL) 
  {	
	p_Char2=p_Char1;
	p_Char1++;
    while( (*p_Char1 != 0)   && (*p_Char1 != '|')
		&& (*p_Char1 != '$') && (*p_Char1 != '&')
		&& (*p_Char1 != '=') && (*p_Char1 != '_') 
		&& (*p_Char1 != '!'))
		 p_Char1++;
	(*sIdent)[strlen(*sIdent)-strlen(p_Char2)]='\0';
	strcpy(szName, *sIdent);
	if (*p_Char1 != 0) 
		strcat(szName, p_Char1);
	strcpy(*sIdent, szName);
  }
}

/****************************************************************************
*		Description:	extract the szExtract part from the name 
*
*		Parameters:		sIdent		: pointer on the name to update 
*						sIdent		: string to return 
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vExtractPropFromName(char **sIdent, char *szExtract )
{
  char *p_Char1, *p_Char2;
  char szName[100];

  if ((p_Char1=strstr(*sIdent, szExtract))!=NULL) 
  {	
	p_Char2=p_Char1+strlen(szExtract);
	(*sIdent)[strlen(*sIdent)-strlen(p_Char1)]='\0';
	strcpy(szName, *sIdent);
	if (*p_Char2 != 0) 
		strcat(szName, p_Char2);
	strcpy(*sIdent, szName);
  }
}

/****************************************************************************
*		Description:	split a module section name into : forme|habillage!NoPhy<NoLod=Name
*
*		Parameters:		_sIdent		: name to split 
*						sForme		: returns the form part
*						sHabillage	: returns the mapping part
*						p_lNoPhy	: returns the physical index
*						p_lNoLod	: returns the level of detail
*						sName		: returns the instance name
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vSplitModuleSectionName (char *_sIdent, char *sForme, char *sHabillage, long *p_lNoPhy, long *p_lNoLod, char *sName)
{
  xString	sIdent;
  char		*p_cForme, *p_cHabillage, *p_cName, *p_char, *p_tmp;
  

  // save complete name
  sprintf(sIdent, "%s", _sIdent);
  // init all parameters
  p_char = sIdent;
  p_cForme = sIdent;
  p_cHabillage = p_cName = NULL;
  *p_lNoPhy = 0;
  *p_lNoLod = 0;
  
  while (*p_char != 0)
  {
    // look for the separator symbols
	while( (*p_char != 0)
        && (*p_char != '|')
        && (*p_char != '!')
        && (*p_char != '=')
        && (*p_char != '<') ) p_char++;

    switch(*p_char)
    {
    case '|' :
      // identify mapping
	  p_cHabillage = p_char+1;
      break;
    case '!' :
      // identify index
      *p_lNoPhy = strtol(p_char+1, &p_tmp, 10);
      break;
    case '<' :
      // identify level of detail
      *p_lNoLod = strtol(p_char+1, &p_tmp, 10);
      break;
    case '=' :
      // identify instance name
      p_cName = p_char+1;
      break;
    }

    if (*p_char == 0) 
		break;
    *p_char = 0;
    
	// next character
	p_char++;
  }

  // update parameters
  sprintf(sForme, "%s", p_cForme);
  if(p_cHabillage != NULL)
    sprintf(sHabillage, "%s", p_cHabillage);
  else
    sprintf(sHabillage, "");
  if(p_cName != NULL)
    sprintf(sName, "%s", p_cName);
  else
    sprintf(sName, "");
}


/****************************************************************************
*		Description:	compute a physical section name into : forme|habillage!NoPhy=Name
*
*		Parameters:		sSection	: name to compute 
*						sForme		: form part
*						sHabillage	: mapping part
*						p_lNoPhy	: physical index
*						sName		: instance name
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vComputePhysicalSectionName (char *sSection, char *sForme, char *sHabillage, long lNoPhy, char *sName)
{
  xString sTmp;

  // init name with form
  sprintf(sSection, "%s", sForme);

  // if necessary, add collide info
  if (!strcmp(sHabillage, M_Collide))
  {
	  strcat(sSection, "!");
  }
  // if necessary, add mapping
  else if(strlen(sHabillage) != 0)
  {
    sprintf(sTmp, "%s|%s", sSection, sHabillage);
    sprintf(sSection, "%s", sTmp);
  }

  // if necessary, add physical index
  if(lNoPhy>1)
  {
    sprintf(sTmp, "%s!%d", sSection, lNoPhy);
    sprintf(sSection, "%s", sTmp);
  }

  // if necessary, add instance name
  if(strlen(sName) != 0)
  {
    sprintf(sTmp, "%s=%s", sSection, sName);
    sprintf(sSection, "%s", sTmp);
  }
}

/****************************************************************************
*		Description:	compute a visualset section name into : forme|habillage=Name
*
*		Parameters:		sSection	: name to compute 
*						sForme		: form part
*						sHabillage	: mapping part
*						sName		: instance name
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vComputeVisualSetSectionName (char *sSection, char *sForme, char *sHabillage, char *sName)
{
  xString sTmp;

  // init name with form
  sprintf(sSection, "%s", sForme);

  // if necessary, add mapping
  if(strlen(sHabillage) != 0)
  {
    sprintf(sTmp, "%s|%s", sSection, sHabillage);
    sprintf(sSection, "%s", sTmp);
  }

  // if necessary, add instance name
  if(strlen(sName) != 0)
  {
    sprintf(sTmp, "%s=%s", sSection, sName);
    sprintf(sSection, "%s", sTmp);
  }
}





/****************************************************************************
*		Description:	display a line in the result window
*
*		Parameters:		cLineType	: type of the line (normal, warning, error) 
*						szFormat	: line to display
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vOutput (char cLineType, char *szFormat, ... )
{
	va_list argptr;
	char szLine[256];

	va_start( argptr, szFormat );
	vsprintf( szLine, szFormat, argptr );
	va_end( argptr );

	#ifndef _WINDOWS
		cLineType = cLineType;	
		fprintf( stderr, szLine );
	#else
		fn_vAfxOutputStringRes( szLine, cLineType);
	#endif
}



