/*=========================================================================
* Snasyn.c : Save & Read the lips synchro pointers
*
* Version              1.0
* Creation date        03/09/97
* Revision date
*
* (c) Ubi R&D 1997
*=======================================================================*/
#ifdef D_USE_LIPSYNC


#include "ACP_Base.h"
#include "ToolsCPA.h"


#include "GAM\LipsSync.h"
#include "GAM\LoadLSyn.h"
#include "GAM\LSMem.h"


#include "SCR.h"
#include "SNA.h"
#include "SNA\snasyn.h"
#include "acp_opfi.h"
#include "AI\AIBase\StrIntel.h"

FILE *g_xLipsSynchFile;			// LipsSynch pointers file
struct tdstRelocTable_ *g_p_stGPointerRelocTableLS;
FILE *g_p_xLipsSynchroBlocFile;
tdstLipsSynchroBinTable *g_a_p_stLSBinTable;
long g_lNumberOfLSTable;

#ifndef U64
	extern int g_iComplete;
#endif

/*-----------------------------------------------------------------------------
 *  Description : Open LipsSynch pointers  file
 *-----------------------------------------------------------------------------
 *  Input :         Name of the file
 *  Output :        None
 *-----------------------------------------------------------------------------
 *  Creation date : 09/12/97            Author : Michaël
 *-----------------------------------------------------------------------------
 *  Modification date :			        Modification Author :
 *  Modifications :
 *---------------------------------------------------------------------------*/
void SNA_fn_xWriteOpenLipsSynchTableFile(char *szFileName)
{
	SNA_fn_vInitArrays();

	g_xLipsSynchFile=fopen(szFileName,"wb");
}

unsigned long fn_ulGetFileSize(char *szFilename)
{ unsigned long ulFileSize;

	LPWIN32_FIND_DATA lpFFD=(LPWIN32_FIND_DATA)malloc(sizeof(WIN32_FIND_DATA));
	if (FindFirstFile(szFilename,lpFFD) == INVALID_HANDLE_VALUE)
	{
	  free(lpFFD);
	  return 0;
	}
	ulFileSize=lpFFD->nFileSizeHigh * MAXDWORD + lpFFD->nFileSizeLow;
	free(lpFFD);
	return ulFileSize;
}


ACP_tdxBool SNA_fn_xReadOpenLipsSynchTableFile(char *szFileName)
{ 
	unsigned long ulFileSize;
	SNA_fn_vInitArrays();

	if (!g_iComplete)
	{
      ACP_M_OPENLANGFILE(fn_ulGetFileSize,ulFileSize,0,szFileName,(szFileName));
	  if (!ulFileSize)
	    return FALSE;
	}
	else
	{
	  if (!fn_ulGetFileSize(szFileName))
		  return FALSE;
	}

	//g_xLipsSynchFile=fopen(szFileName,"rb"); Multi-install and multi-language
    ACP_M_OPENLANGFILE(fopen,g_xLipsSynchFile,NULL,szFileName,(szFileName,"rb"));
/*
	szFileName[strlen(szFileName)-3]=0;
	strcat(szFileName,"rtl");
	g_p_stGPointerRelocTableLS=SNA_fn_pLoadRelocationTable(szFileName);		// Modifier le filename...
*/
	g_p_stGPointerRelocTableLS=SNA_fn_pLoadRelocationTable();

	return TRUE;
}

/*-----------------------------------------------------------------------------
 *  Description : Close LipsSynch pointers file
 *-----------------------------------------------------------------------------
 *  Input :         Name of the file
 *  Output :        None
 *-----------------------------------------------------------------------------
 *  Creation date : 09/12/97            Author : Michaël
 *-----------------------------------------------------------------------------
 *  Modification date :			        Modification Author :
 *  Modifications :
 *---------------------------------------------------------------------------*/
void SNA_fn_vCloseLipsSynchTableFile()
{
	SNA_fn_pFreeRelocationTable(g_p_stGPointerRelocTableLS);
	fclose(g_xLipsSynchFile);
}

/*-----------------------------------------------------------------------------
 *  Description : Write a LS filename/IA node pointer couple in file
 *-----------------------------------------------------------------------------
 *  Input :         Name of the file
 *  Output :        None
 *-----------------------------------------------------------------------------
 *  Creation date : 09/12/97            Author : Michaël
 *-----------------------------------------------------------------------------
 *  Modification date :			        Modification Author :
 *  Modifications :
 *---------------------------------------------------------------------------*/
void SNA_fn_vWriteLipsSynchEntryInLipsSynchTableFile(char *szLSFilename,unsigned long ulNodeAdr)
{ char szLSFilename255[255];

	strcpy(szLSFilename255,szLSFilename);
	if (SNA_fn_ucGetLoadType()==SNA_SAVE_SNAPSHOT)
	{
		fwrite(szLSFilename255,255,1,g_xLipsSynchFile);
		fwrite(&ulNodeAdr,4,1,g_xLipsSynchFile);
	}
}


// MR0912
void fn_vInitNodeLipSynchroRefWithSNA(tdstNodeInterpret *p_stNode,char *szLipsFileName)
{
	tdstLipsSynchroTable *p_stLSTable;

	p_stLSTable=fn_p_stReturnLipsSynchTable(szLipsFileName);
	M_hLipSynchroHandleIdInterpret(p_stNode) = p_stLSTable;
}

void fn_vUpdateSoundPointersForLipsSynch()
{ ACP_tdxIndex xJ;

	for (xJ=0;xJ<g_lNumberOfLSTable;xJ++)
	{
		g_a_p_stLSBinTable[xJ].p_stLSTable->p_stSndEvent=SND_fn_pGetBinEvent((unsigned long)g_a_p_stLSBinTable[xJ].p_stLSTable->p_stSndEvent);
	}
}

/*-----------------------------------------------------------------------------
 *  Description : Read and update all LipsSynch pointers
 *-----------------------------------------------------------------------------
 *  Input :         Name of the file
 *  Output :        None
 *-----------------------------------------------------------------------------
 *  Creation date : 09/12/97            Author : Michaël
 *-----------------------------------------------------------------------------
 *  Modification date :			        Modification Author :
 *  Modifications :
 *---------------------------------------------------------------------------*/
void SNA_fn_vReadAndUpdateLipsSynchPointers()
{ 
  char szLSFileName[255];
  unsigned long ulOldAdrPointer;
  unsigned long *p_ulLipsSynch;
  unsigned long j;

	while (!feof(g_xLipsSynchFile))
	{	
		if(!fread(szLSFileName,255,1,g_xLipsSynchFile))
		{
			OutputDebugString("\n End of LipsSynchFile !!!");
			break;
		}

		if(!fread(&ulOldAdrPointer,4,1,g_xLipsSynchFile))
		{
			OutputDebugString("\n End of LipsSynchFile !!!");
			break;
		}

		p_ulLipsSynch=(unsigned long *)ulOldAdrPointer;
		
		
		for (j=0;j<g_p_stGPointerRelocTableLS->p_stBloc[0].ulSize;j++)
		{ 
			unsigned char ucModuleNumber,ucBlocNumber;
			
			ucModuleNumber=g_p_stGPointerRelocTableLS->p_stBloc[0].p_stPtr[j].ucModuleNumber;
			ucBlocNumber=g_p_stGPointerRelocTableLS->p_stBloc[0].p_stPtr[j].ucBlocNumber;
			if (((unsigned long)p_ulLipsSynch==g_p_stGPointerRelocTableLS->p_stBloc[0].p_stPtr[j].p_vPtr)&&(g_a_bIsBlocRelocated[ucModuleNumber][ucBlocNumber]))
			{	
				((unsigned long)p_ulLipsSynch)+=g_a_ulOffset[ucModuleNumber][ucBlocNumber];
			}
		}
	
		fn_vInitNodeLipSynchroRefWithSNA((tdstNodeInterpret *)p_ulLipsSynch,szLSFileName);
	
	}


	fclose(g_xLipsSynchFile);
	
	fn_vUpdateSoundPointersForLipsSynch();
}

/**************************************************************************************/
// SNASHOTISATION (MR0912)
/**************************************************************************************/

void fn_vOpenWriteLipsSynchroBloc(char *szFileName)
{
	g_p_xLipsSynchroBlocFile=fopen(szFileName,"wb");
	g_lNumberOfLSTable=0;
}

void fn_vCloseWriteLipsSynchroBloc()
{
	fwrite(&g_lNumberOfLSTable,4,1,g_p_xLipsSynchroBlocFile);
	fclose(g_p_xLipsSynchroBlocFile);
}

void fn_vWriteLipsSynchroBloc(tdstLipsSynchroTable *p_stLSTable, char *szSectionName)
{
	tdstLipsSynchroTable* hLST=p_stLSTable;
	ACP_tdxIndex xI;
	unsigned long BinId;

	g_lNumberOfLSTable++;
	
	// Write section name
	fwrite(szSectionName,1,255,g_p_xLipsSynchroBlocFile);

	fwrite(&hLST->lNumberOfFrames,4,1,g_p_xLipsSynchroBlocFile);
	fwrite(&hLST->lSpeed,4,1,g_p_xLipsSynchroBlocFile);

	BinId=SND_fn_ulGetEventBinIdFromPointer(hLST->p_stSndEvent);
	fwrite(&BinId,4,1,g_p_xLipsSynchroBlocFile);

	for(xI=0;xI<MAX_NUM_CHAN_SYN;++xI)
		fwrite(&(hLST->ucChannelAffected[xI]),1,1,g_p_xLipsSynchroBlocFile);
	fwrite(&hLST->ucNumberOfChannelAffected,1,1,g_p_xLipsSynchroBlocFile);

	fwrite(&hLST->iIndex,4,1,g_p_xLipsSynchroBlocFile);
	fwrite(&hLST->lNumberOfTexts,4,1,g_p_xLipsSynchroBlocFile);
	if(hLST->p_stDialTexts==NULL)
	{	
		BinId=0L;
		fwrite(&BinId,4,1,g_p_xLipsSynchroBlocFile);
	}
	else
	{	
		BinId=1L;
		fwrite(&BinId,4,1,g_p_xLipsSynchroBlocFile);
	}

	fwrite(&hLST->lNumberOfActings,4,1,g_p_xLipsSynchroBlocFile);
	
	if(hLST->p_stActing==NULL)
	{	
		BinId=0L;
		fwrite(&BinId,4,1,g_p_xLipsSynchroBlocFile);
	}
	else
	{	
		BinId=1L;
		fwrite(&BinId,4,1,g_p_xLipsSynchroBlocFile);
	}

	// Now the table of synchro events
	for(xI=0;xI<hLST->lNumberOfFrames;++xI)
	{
		fwrite(&(hLST->p_stTable[xI].ucPhoneme),4,1,g_p_xLipsSynchroBlocFile);
		fwrite(&(hLST->p_stTable[xI].ucIntensity),4,1,g_p_xLipsSynchroBlocFile);
		fwrite(&(hLST->p_stTable[xI].ucExpression),4,1,g_p_xLipsSynchroBlocFile);
	}

	// Then the dial texts
	if(hLST->p_stDialTexts!=NULL)
	{
		for(xI=0;xI<hLST->lNumberOfTexts;++xI)
		{
			fwrite(&(hLST->p_stDialTexts[xI].lFrameNumber),4,1,g_p_xLipsSynchroBlocFile);
			fwrite(&(hLST->p_stDialTexts[xI].xPosX),4,1,g_p_xLipsSynchroBlocFile);
			fwrite(&(hLST->p_stDialTexts[xI].xPosY),4,1,g_p_xLipsSynchroBlocFile);
		}
	}

	// Finally the acting pointer
	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	// !!!!!!!!!!!!!!!    NE MARCHERA PAS   !!!!!!!!!!!!!!!!!!!!
	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	if(hLST->p_stActing!=NULL)
	{
		for(xI=0;xI<hLST->lNumberOfActings;++xI)
		{
			fwrite(&(hLST->p_stActing[xI].lFrameNumber),4,1,g_p_xLipsSynchroBlocFile);
			fwrite(&(hLST->p_stActing[xI].hNewState),4,1,g_p_xLipsSynchroBlocFile);
		}
	}
}

void fn_vReadAllLipsSynchroBlocs(char *szFileName)
{
	tdstLipsSynchroTable* hLST;
	ACP_tdxIndex xI,xJ;
	unsigned long BinId;

	LSY_fn_vFreeLipsSynchroBlock();

	ACP_M_OPENLANGFILE(fopen,g_p_xLipsSynchroBlocFile,NULL,szFileName,(szFileName,"rb"));
	fseek(g_p_xLipsSynchroBlocFile,-4,SEEK_END);
	fread(&g_lNumberOfLSTable,4,1,g_p_xLipsSynchroBlocFile);
	fseek(g_p_xLipsSynchroBlocFile,0,SEEK_SET);
	g_a_p_stLSBinTable=fn_xAllocateLipsSynchroBinTable(g_lNumberOfLSTable);
	
	//while (!feof(g_p_xLipsSynchroBlocFile))
	for (xJ=0;xJ<g_lNumberOfLSTable;xJ++)
	{
		fread(g_a_p_stLSBinTable[xJ].szSectionName,1,255,g_p_xLipsSynchroBlocFile);
		
		hLST=fn_xAllocateLipsSynchroTable();
		g_a_p_stLSBinTable[xJ].p_stLSTable=hLST;
		
		fread(&hLST->lNumberOfFrames,4,1,g_p_xLipsSynchroBlocFile);
		fread(&hLST->lSpeed,4,1,g_p_xLipsSynchroBlocFile);

		// A voir...
		fread(&hLST->p_stSndEvent,4,1,g_p_xLipsSynchroBlocFile);

		for(xI=0;xI<MAX_NUM_CHAN_SYN;++xI)
			fread(&(hLST->ucChannelAffected[xI]),1,1,g_p_xLipsSynchroBlocFile);
		fread(&hLST->ucNumberOfChannelAffected,1,1,g_p_xLipsSynchroBlocFile);

		fread(&hLST->iIndex,4,1,g_p_xLipsSynchroBlocFile);
		fread(&hLST->lNumberOfTexts,4,1,g_p_xLipsSynchroBlocFile);

		fread(&BinId,4,1,g_p_xLipsSynchroBlocFile);
		if (!BinId)
			hLST->p_stDialTexts=NULL;
		else
			hLST->p_stDialTexts=fn_xAllocateDialTexts(hLST->lNumberOfTexts);

		fread(&hLST->lNumberOfActings,4,1,g_p_xLipsSynchroBlocFile);
		
		fread(&BinId,4,1,g_p_xLipsSynchroBlocFile);
		if (!BinId)
			hLST->p_stActing=NULL;
		else
			hLST->p_stActing=fn_xAllocateActing(hLST->lNumberOfActings);

		// Now the table of synchro events
		hLST->p_stTable=fn_xAllocateLipsSynchroEvents(hLST->lNumberOfFrames);
		for(xI=0;xI<hLST->lNumberOfFrames;++xI)
		{
			fread(&(hLST->p_stTable[xI].ucPhoneme),4,1,g_p_xLipsSynchroBlocFile);
			fread(&(hLST->p_stTable[xI].ucIntensity),4,1,g_p_xLipsSynchroBlocFile);
			fread(&(hLST->p_stTable[xI].ucExpression),4,1,g_p_xLipsSynchroBlocFile);
		}

		// Then the dial texts
		if(hLST->p_stDialTexts!=NULL)
		{
			for(xI=0;xI<hLST->lNumberOfTexts;++xI)
			{
				fread(&(hLST->p_stDialTexts[xI].lFrameNumber),4,1,g_p_xLipsSynchroBlocFile);
				fread(&(hLST->p_stDialTexts[xI].xPosX),4,1,g_p_xLipsSynchroBlocFile);
				fread(&(hLST->p_stDialTexts[xI].xPosY),4,1,g_p_xLipsSynchroBlocFile);
			}
		}

		// Finally the acting pointer
		// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		// !!!!!!!!!!!!!!!    NE MARCHERA PAS   !!!!!!!!!!!!!!!!!!!!
		// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		if(hLST->p_stActing!=NULL)
		{
			for(xI=0;xI<hLST->lNumberOfActings;++xI)
			{
				fread(&(hLST->p_stActing[xI].lFrameNumber),4,1,g_p_xLipsSynchroBlocFile);
				fread(&(hLST->p_stActing[xI].hNewState),4,1,g_p_xLipsSynchroBlocFile);
			}
		}
		//xJ++;
	}
	fclose(g_p_xLipsSynchroBlocFile);
}

tdstLipsSynchroTable *fn_p_stReturnLipsSynchTable(char *szSectionName)
{ ACP_tdxIndex xJ;

	for (xJ=0;xJ<g_lNumberOfLSTable;xJ++)
		if (!strcmp(szSectionName,g_a_p_stLSBinTable[xJ].szSectionName))
			return g_a_p_stLSBinTable[xJ].p_stLSTable;
	return NULL;
}

#endif //  D_USE_LIPSYNC
