/* ***********************************************************************************/
/* * "a3x_load.c"																	**/
/* * Written by :	Sébastien Rubens												**/
/* * Tabulations :	4 char															**/
/* ***********************************************************************************/
 
 
 
/* ***********************************************************************************/
#define A3X_LOAD_C
 
 
 
/* ***********************************************************************************/
/*																	Included files*/
 
#include <math.h>
#include <stdio.h>
 
#include "PlayAnim/Interpol/specif/a3x_pref.h"
 
/*#define LST2_StaticIsOptimised*/
#include "TOOLSCPA.h"
#include "cpa_std.h"
#include "STRUCTUR/Anim_s.h"
 
#include "PlayAnim/Interpol/a3x_glob.h"
#include "PlayAnim/Interpol/a3x_int.h"
#include "PlayAnim/Interpol/a3x_mem.h"
#include "PlayAnim/Interpol/a3x_load.h"
 
 
 
/* ***********************************************************************************/
/*																	Globals datas*/
 
static	void						*p_vCurrentFile;
 
static	tdstFileA3dAnimationGENERAL	*p_stFileA3dGENERAL;
static	tdxULongVector3				*p_stFileVector3;
static	tdxSShortQuater4			*p_stFileQuater4;
static	tdstFileHierarchy			*p_stFileHierarchy;
static	tdstFileNTTO				*p_stFileNTTO;
static	tdstFileOnlyFrame			*p_stFileOnlyFrame;
static	tdstFileChannel				*p_stFileChannel;
static	tdstFileFrame				*p_stFileFrame;
static	tdstFileKeyFrame			*p_stFileKeyFrame;
static	tdstFileEvent				*p_stFileEvent;
static  tdstFileMorphData           *p_stFileMorphData;
 
static	tdstA3dGENERAL				*p_stCurrentA3dGENERAL;
static	tdxULongVector3				*p_stCurrentVector3;
static	tdxSShortQuater4			*p_stCurrentQuater4;
static	tdstHierarchy				*p_stCurrentHierarchy;
static	tdstNTTO					*p_stCurrentNTTO;
static	tdstOnlyFrame				*p_stCurrentOnlyFrame;
static	tdstChannel					*p_stCurrentChannel, *p_stFirstChannel;
static	tdstFrame					*p_stCurrentFrame;
static	tdstKeyFrame				*p_stCurrentKeyFrame, *p_stOldKeyFrame;
static	tdstEvent					*p_stCurrentEvent;
static  tdstMorphData				*p_stCurrentMorphData;
 
static	tdxMatrix33					a3a3_xMtxOri, a3a3_xMtxSca, a3a3_xScaleMatrix;
static	tdxQuater4					a4_xOldQuatOri, a4_xOldQuatSca;
static	tdxQuater4					a4_xQuatOri, a4_xQuatSca;
static	tdxVector3					a3_xTmpVec;
 
static	unsigned short	uwNumOfFirstVector, uwNumOfFirstQuaternion, uwNumOfFirstHierarchy;
 
#ifdef ANIM_DEBUG
extern char* g_p_cSecurityMalloc; /* for debug -> to be removed !!!*/
#endif /*ANIM_DEBUG*/
 
/* ***********************************************************************************/
#ifdef	A3xDebug
void	fn_v_A3dVerify(	char	*a4_cNeededString,
						char	*p_cString )
{
	if	(	(a4_cNeededString[0] != p_cString[0]) ||
			(a4_cNeededString[1] != p_cString[1]) ||
			(a4_cNeededString[2] != p_cString[2]) ||
			(a4_cNeededString[3] != p_cString[3]) )
	{	printf("Error in %s hunk\n",	a4_cNeededString );
	}
}
 
#define	M_A3xDebug( String, Type, p_xFile )											\
{	fn_v_A3dVerify( String, (char *) (p_xFile) );									\
	p_xFile=	(Type *) ( ((char *) (p_xFile)) + 8 );								\
}
#else
#define	M_A3xDebug( String, Type, p_xFile )
#endif
 
#ifdef U64
/* XB 05/05/99 */
extern void *fast_memcpy(  register void *dest, register void *src, register size_t n);
/* End XB 05/05/99 */
#define memcpy(a,b,c) fast_memcpy(a,b,c)
#endif /*U64*/
 
/* ***********************************************************************************/
void	fn_v_LoadA3dGENERAL( void )
{
	p_stCurrentA3dGENERAL=	&p_stA3dGENERAL[ fn_ul_AllocateOnStack( eStackA3dGENERAL, 1 ) ];
 
	p_stFileA3dGENERAL=	(tdstFileA3dAnimationGENERAL *) p_vCurrentFile;
	M_A3xDebug( "GENE", tdstFileA3dAnimationGENERAL, p_stFileA3dGENERAL );
 
/*	p_stCurrentA3dGENERAL->uwAnimationSpeed=					p_stFileA3dGENERAL->uwAnimationSpeed;
 
	p_stCurrentA3dGENERAL->uwNumberOfVectors=					p_stFileA3dGENERAL->uwNumberOfVectors;
	p_stCurrentA3dGENERAL->uwNumberOfQuaternions=				p_stFileA3dGENERAL->uwNumberOfQuaternions;
	p_stCurrentA3dGENERAL->uwNumberOfHierarchies=				p_stFileA3dGENERAL->uwNumberOfHierarchies;
	p_stCurrentA3dGENERAL->uwNumberOfNTTO=						p_stFileA3dGENERAL->uwNumberOfSavedNTTO;
	p_stCurrentA3dGENERAL->uwNumberOfSavedFrames=				p_stFileA3dGENERAL->uwNumberOfSavedFrames;
 
	p_stCurrentA3dGENERAL->uwNumberOfChannels=					p_stFileA3dGENERAL->uwNumberOfChannels;
	p_stCurrentA3dGENERAL->uwNumberOfFrames=					p_stFileA3dGENERAL->uwNumberOfFrames;
	p_stCurrentA3dGENERAL->uwNumberOfKeyFrames=					p_stFileA3dGENERAL->uwNumberOfKeyFrames;
	p_stCurrentA3dGENERAL->uwNumberOfEvents=					p_stFileA3dGENERAL->uwNumberOfEvents;
	p_stCurrentA3dGENERAL->uwNumberOfMorphData=					p_stFileA3dGENERAL->uwNumberOfMorphData;
 
	p_stCurrentA3dGENERAL->uwNumOfAnimationTranslationOffset=	p_stFileA3dGENERAL->uwNumOfAnimationTranslationOffset;
	p_stCurrentA3dGENERAL->uwNumOfAnimationRotationOffset=		p_stFileA3dGENERAL->uwNumOfAnimationRotationOffset;
	p_stCurrentA3dGENERAL->uwNumOfFirstPosition=				p_stFileA3dGENERAL->uwNumOfFirstPosition;
 
	p_stCurrentA3dGENERAL->uwStartFrame=						p_stFileA3dGENERAL->uwStartFrame;
	p_stCurrentA3dGENERAL->uwEndFrame=							p_stFileA3dGENERAL->uwEndFrame;
	p_stCurrentA3dGENERAL->uwFlags=								p_stFileA3dGENERAL->uwFlags;
	p_stCurrentA3dGENERAL->uwFakeAnimSpeed=						p_stFileA3dGENERAL->uwFakeAnimSpeed; */
/*	p_stCurrentA3dGENERAL->uwAlign=								0;*/
 
	/* optim AR9811*/
	memcpy(p_stCurrentA3dGENERAL,p_stFileA3dGENERAL,sizeof(tdstFileA3dAnimationGENERAL));
 
	p_stFileA3dGENERAL++;
	p_vCurrentFile=	(void *) p_stFileA3dGENERAL;
 
	/*unsigned short	uwNumOfFirstVector;					will be set in fn_v_LoadVectors*/
	/*unsigned short	uwNumOfFirstQuaternion;				will be set in fn_v_LoadQuaternions*/
	/*unsigned short	uwNumOfFirstHierarchy;				will be set in fn_v_LoadHierarchies*/
	/*unsigned short	uwNumOfFirstNTTO;					will be set in fn_v_LoadNTTO*/
	/*unsigned short	uwNumOfFirstOnlyFrame;				will be set in fn_v_LoadOnlyFrames*/
	/*unsigned short	uwNumOfFirstChannel;				will be set in fn_v_LoadChannels*/
	/*unsigned short	uwNumOfFirstEvent;					will be set in fn_v_LoadEvents*/
	/*unsigned short	uwNumOfFirstPosition;				will be add in fn_v_LoadVectors*/
	/*unsigned short	uwNumOfAnimationTranslationOffset;	will be add in fn_v_LoadVectors*/
	/*unsigned short	uwNumOfAnimationRotationOffset;		will be add in fn_v_LoadQuaternions*/
}
 
 
 
/* ***********************************************************************************/
void	fn_v_LoadVectors( void )
{	register unsigned short	uwMax/*, uwCnt1*/;
	register unsigned long  ulInd;
 
	uwMax=	p_stCurrentA3dGENERAL->uwNumberOfVectors;
	ulInd=	fn_ul_AllocateOnStack( eStackVertexes, uwMax );
 
	uwNumOfFirstVector = p_stCurrentA3dGENERAL->uwNumOfFirstVector = (unsigned short)ulInd;
 
	p_stCurrentVector3=	(tdxULongVector3 *) &p_a3_xVectors[ ulInd ];
	p_stFileVector3=	(tdxULongVector3 *) p_vCurrentFile;
	M_A3xDebug( "VERT", tdxULongVector3, p_stFileVector3 );
/*	for	( uwCnt1=0 ; uwCnt1<uwMax ; uwCnt1++ )
	{
		(*p_stCurrentVector3)[0]=	(*p_stFileVector3)[0];
		(*p_stCurrentVector3)[1]=	(*p_stFileVector3)[1];
		(*p_stCurrentVector3)[2]=	(*p_stFileVector3)[2];
		p_stFileVector3++;
		p_stCurrentVector3++;
	}*/
	
	memcpy(p_stCurrentVector3,p_stFileVector3,sizeof(tdxULongVector3)*uwMax); /* optim AR9811*/
 
/*	p_vCurrentFile=	(void *) p_stFileVector3;*/
	p_vCurrentFile=	(void *) (p_stFileVector3+uwMax);
	p_stCurrentVector3 += uwMax;
 
#pragma warning(disable:4244)
	p_stCurrentA3dGENERAL->uwNumOfFirstPosition+=				uwNumOfFirstVector;
	p_stCurrentA3dGENERAL->uwNumOfAnimationTranslationOffset+=	uwNumOfFirstVector;
#pragma warning(default:4244)
}
 
 
 
/* ***********************************************************************************/
void	fn_v_LoadQuaternions( void )
{	register unsigned short	uwMax/*, uwCnt1*/;
	register unsigned long	ulInd; 
	uwMax=	p_stCurrentA3dGENERAL->uwNumberOfQuaternions;
	ulInd=	fn_ul_AllocateOnStack( eStackQuaternions, uwMax );
 
	uwNumOfFirstQuaternion = p_stCurrentA3dGENERAL->uwNumOfFirstQuaternion = (unsigned short)ulInd;
 
	p_stCurrentQuater4=	&p_a4_xQuaternions[ ulInd ];
	p_stFileQuater4=	(tdxSShortQuater4 *) p_vCurrentFile;
	M_A3xDebug( "QUAT", tdxSShortQuater4, p_stFileQuater4 );
/*	for	( uwCnt1=0 ; uwCnt1<uwMax ; uwCnt1++ )
	{
		(*p_stCurrentQuater4)[0]=	(*p_stFileQuater4)[0];
		(*p_stCurrentQuater4)[1]=	(*p_stFileQuater4)[1];
		(*p_stCurrentQuater4)[2]=	(*p_stFileQuater4)[2];
		(*p_stCurrentQuater4)[3]=	(*p_stFileQuater4)[3];
		p_stFileQuater4++;
		p_stCurrentQuater4++;
	} */
 
	memcpy(p_stCurrentQuater4,p_stFileQuater4,sizeof(tdxSShortQuater4)*uwMax); /* optim AR9811*/
 
/*	p_vCurrentFile=	(void *) p_stFileQuater4;*/
	p_vCurrentFile=	(void *) (p_stFileQuater4+uwMax);
	p_stCurrentQuater4 += uwMax;
 
#pragma warning(disable:4244)
	p_stCurrentA3dGENERAL->uwNumOfAnimationRotationOffset+=		uwNumOfFirstQuaternion;
#pragma warning(default:4244)
}
 
 
 
/* ***********************************************************************************/
void	fn_v_LoadHierarchies( void )
{	register unsigned short	uwMax/*, uwCnt1*/;
	register unsigned long ulInd;
 
	uwMax=	p_stCurrentA3dGENERAL->uwNumberOfHierarchies;
	ulInd=	fn_ul_AllocateOnStack( eStackHierarchies, uwMax );
 
	uwNumOfFirstHierarchy = p_stCurrentA3dGENERAL->uwNumOfFirstHierarchy = (unsigned short)ulInd;
 
	p_stCurrentHierarchy=	&p_stHierarchies[ ulInd ];
	p_stFileHierarchy=		(tdstFileHierarchy *) p_vCurrentFile;
	M_A3xDebug( "HIER", tdstFileHierarchy, p_stFileHierarchy );
/*	for	( uwCnt1=0 ; uwCnt1<uwMax ; uwCnt1++ )
	{
		p_stCurrentHierarchy->uwChild=	p_stFileHierarchy->uwChild;
		p_stCurrentHierarchy->uwFather=	p_stFileHierarchy->uwFather;
		p_stFileHierarchy++;
		p_stCurrentHierarchy++;
	} */
 
	memcpy(p_stCurrentHierarchy,p_stFileHierarchy,sizeof(tdstFileHierarchy)*uwMax); /* optim AR9811*/
 
/*	p_vCurrentFile=	(void *) p_stFileHierarchy;*/
	p_vCurrentFile=	(void *) (p_stFileHierarchy+uwMax);
	p_stCurrentHierarchy+=uwMax;
}
 
 
 
/* ***********************************************************************************/
void	fn_v_LoadNTTO( void )
{	register unsigned short	uwMax/*, uwCnt1*/;
	register unsigned long ulInd;
 
	uwMax=	p_stCurrentA3dGENERAL->uwNumberOfNTTO;
	ulInd=	fn_ul_AllocateOnStack( eStackNTTO, uwMax );
 
	p_stCurrentA3dGENERAL->uwNumOfFirstNTTO = (unsigned short)ulInd;
 
	p_stCurrentNTTO=	&p_stNTTO[ ulInd ];
	p_stFileNTTO=		(tdstFileNTTO *) p_vCurrentFile;
	M_A3xDebug( "NTTO", tdstFileNTTO, p_stFileNTTO );
/*	for	( uwCnt1=0 ; uwCnt1<uwMax ; uwCnt1++ )
	{
		p_stCurrentNTTO->ucNumberInTable=	p_stFileNTTO->ucNumberInTable;
		p_stCurrentNTTO->uwTypeOfObject=	p_stFileNTTO->uwTypeOfObject;
		p_stCurrentNTTO->ucTransparency=	p_stFileNTTO->ucTransparency;
		p_stFileNTTO++;
		p_stCurrentNTTO++;
	} */
 
	memcpy(p_stCurrentNTTO,p_stFileNTTO,sizeof(tdstFileNTTO)*uwMax); /* optim AR9811*/
 
/*	p_vCurrentFile=	(void *) p_stFileNTTO;*/
	p_vCurrentFile=	(void *) (p_stFileNTTO+uwMax);
	p_stCurrentNTTO+=uwMax;
}
 
 
 
/* ***********************************************************************************/
void	fn_v_LoadOnlyFrames( void )
{	register unsigned short	uwCnt1, uwMax;
	register unsigned long ulInd;
 
	uwMax=	(unsigned short)(p_stCurrentA3dGENERAL->uwEndFrame - p_stCurrentA3dGENERAL->uwStartFrame);
	ulInd=	fn_ul_AllocateOnStack( eStackOnlyFrames, uwMax );
 
	p_stCurrentA3dGENERAL->uwNumOfFirstOnlyFrame = (unsigned short)ulInd;
 
	p_stCurrentOnlyFrame=	&p_stOnlyFrames[ ulInd ];
	p_stFileOnlyFrame=	(tdstFileOnlyFrame *) p_vCurrentFile;
	M_A3xDebug( "OFRM", tdstFileOnlyFrame, p_stFileOnlyFrame );
	for	( uwCnt1=0 ; uwCnt1<uwMax ; uwCnt1++ )
	{
		if	( p_stFileOnlyFrame->uwNumOfAngularSpeedQuat != SEB_Invalid )
		{	p_stCurrentOnlyFrame->uwNumOfAngularSpeedQuat=	(unsigned short) (uwNumOfFirstQuaternion + p_stFileOnlyFrame->uwNumOfAngularSpeedQuat);
/*			fn_v_ExpandQuat( a4_xQuatOri, p_a4_xQuaternions[ p_stCurrentOnlyFrame->uwNumOfAngularSpeedQuat ] );
			p_stCurrentOnlyFrame->uwAngSpeedQuat=			fn_uw_AngleBetweenQuat(	a4_xQuatOri, a4_xQuater1 ); */
		}
		else
		{	p_stCurrentOnlyFrame->uwNumOfAngularSpeedQuat=	SEB_Invalid;
		}
		if	( p_stFileOnlyFrame->uwNumOfSpeedVector != SEB_Invalid )
				p_stCurrentOnlyFrame->uwNumOfSpeedVector=(unsigned short)(uwNumOfFirstVector + p_stFileOnlyFrame->uwNumOfSpeedVector);
		else	p_stCurrentOnlyFrame->uwNumOfSpeedVector=		SEB_Invalid;
		p_stCurrentOnlyFrame->uwHierarchyNbCouples=			p_stFileOnlyFrame->uwHierarchyNbCouples;
		p_stCurrentOnlyFrame->uwNumOfFirstHierarchyCouple=	(unsigned short)(uwNumOfFirstHierarchy  + p_stFileOnlyFrame->uwNumOfHierarchyCouples);
		p_stCurrentOnlyFrame->uwNumOfSavedFrame=			p_stFileOnlyFrame->uwNumOfSavedFrame;
		p_stFileOnlyFrame++;
		p_stCurrentOnlyFrame++;
	}
	p_vCurrentFile=	(void *) p_stFileOnlyFrame;
}
 
 
 
/* ***********************************************************************************/
void	fn_v_LoadChannels( void )
{	register unsigned short	uwCnt1, uwMax;
	register unsigned long ulInd;
 
	uwMax=	p_stCurrentA3dGENERAL->uwNumberOfChannels;
	ulInd=	fn_ul_AllocateOnStack( eStackChannels, uwMax );
 
	p_stCurrentA3dGENERAL->uwNumOfFirstChannel = (unsigned short)ulInd;
	p_stFirstChannel=	&p_stChannels[ ulInd ];
 
	p_stCurrentChannel=	p_stFirstChannel;
	p_stFileChannel=	(tdstFileChannel *) p_vCurrentFile;
	M_A3xDebug( "CHAN", tdstFileChannel, p_stFileChannel );
	for	( uwCnt1=0 ; uwCnt1<uwMax ; uwCnt1++ )
	{
		p_stCurrentChannel->uwNumberOfKeys=			p_stFileChannel->uwNumberOfKeys;
		p_stCurrentChannel->uwChannelNumber=		p_stFileChannel->uwChannelNumber;
		p_stCurrentChannel->uwNumOfLocalPivotPos=	(unsigned short)(uwNumOfFirstVector + p_stFileChannel->uwNumOfLocalPivotPos);
		p_stFileChannel++;
		p_stCurrentChannel++;
	}
	p_vCurrentFile=	(void *) p_stFileChannel;
 
	/*unsigned short	uwNumOfFirstFrame;			will be set in fn_v_LoadFrames*/
	/*unsigned short	uwNumOfFirstFrameKF;		will be set in fn_v_LoadFrames*/
	/*unsigned short	uwNumOfFirstKeyFrame;		will be set in fn_v_LoadKeyFrames*/
}
 
 
 
/* ***********************************************************************************/
void	fn_v_LoadFrames( void )
{	register unsigned short	uwCnt1, uwCnt2, uwMax;
	register unsigned long ulInd;
 
	p_stCurrentChannel=	p_stFirstChannel;
	p_stFileFrame=		(tdstFileFrame *) p_vCurrentFile;
	M_A3xDebug( "FRMS", tdstFileFrame, p_stFileFrame );
	for	( uwCnt1=0 ; uwCnt1<p_stCurrentA3dGENERAL->uwNumberOfChannels ; uwCnt1++ )
	{
		uwMax=	p_stCurrentA3dGENERAL->uwNumberOfSavedFrames;
		ulInd=	fn_ul_AllocateOnStack( eStackFrames, uwMax );
 
		p_stCurrentChannel->uwNumOfFirstFrame=(unsigned short)ulInd;
		p_stCurrentFrame=	&p_stFrames[ ulInd ];
 
		for	( uwCnt2=0 ; uwCnt2<uwMax ; uwCnt2++ )
		{	
			if(p_stFileFrame->uwNumOfNTTO!=(unsigned short)0xFFFF) /*AR9810 0xFFFF means simple empty object*/
				p_stCurrentFrame->uwNumOfNTTO=	(unsigned short)(p_stCurrentA3dGENERAL->uwNumOfFirstNTTO + p_stFileFrame->uwNumOfNTTO);
			else
				p_stCurrentFrame->uwNumOfNTTO=(unsigned short)0xFFFF;
			p_stFileFrame++;
			p_stCurrentFrame++;
		}
 
		uwMax=	(unsigned short)(p_stCurrentA3dGENERAL->uwEndFrame - p_stCurrentA3dGENERAL->uwStartFrame);
		ulInd=	fn_ul_AllocateOnStack( eStackFramesKF, uwMax );
 
		p_stCurrentChannel->ulNumOfFirstFrameKF = ulInd;
 
		p_stCurrentChannel++;
	}
	p_vCurrentFile=	(void *) p_stFileFrame;
 
	/*unsigned short	uwNumOfKeyFrame;			will be set in fn_v_LoadKeyFrames*/
}
 
 
 
/* ***********************************************************************************/
void	fn_v_LoadKeyFrames( void )
{	register unsigned short	uwCnt1, uwCnt2, uwCnt3, uwMax;
	register unsigned long	ulInd;
	unsigned short			uwNumOfPosition;
	unsigned long			ulNumOfFirstFrameKF;
	unsigned short			uwNumOfOldKeyFrame= 0, uwNumOfCurrentKeyFrame;
	unsigned short			uwNumOfOldFrameNumber= 0, uwNumOfCurrentFrameNumber;
	unsigned short			uwNumOfOldPosition=	0;
 
	p_stCurrentChannel=	p_stFirstChannel;
	p_stFileKeyFrame=	(tdstFileKeyFrame *) p_vCurrentFile;
	M_A3xDebug( "KFRM", tdstFileKeyFrame, p_stFileKeyFrame );
	for	( uwCnt1=0 ; uwCnt1<p_stCurrentA3dGENERAL->uwNumberOfChannels ; uwCnt1++ )
	{
		/* Allocate KeyFrames*/
		uwMax=	p_stCurrentChannel->uwNumberOfKeys;
		ulInd=	fn_ul_AllocateOnStack( eStackKeyFrames, uwMax );
 
		p_stCurrentChannel->uwNumOfFirstKeyFrame = (unsigned short)ulInd;
		p_stCurrentKeyFrame=	&p_stKeyFrames[ ulInd ];
/* Warning : don't change uwInd value (it will use at the end of this routine to get first keyframe)*/
 
		ulNumOfFirstFrameKF=		p_stCurrentChannel->ulNumOfFirstFrameKF;
		uwNumOfCurrentKeyFrame=		(unsigned short)ulInd;
		uwNumOfCurrentFrameNumber=	0;
 
		ulInd=	0;
		uwCnt3=	p_stCurrentChannel->uwNumOfLocalPivotPos;
		if	(	(p_a3_xVectors[uwCnt3][0] != xZero) ||
				(p_a3_xVectors[uwCnt3][1] != xZero) ||
				(p_a3_xVectors[uwCnt3][2] != xZero) )
		{	ulInd=	1;
		}
 
		for	( uwCnt2=0 ; uwCnt2<uwMax ; uwCnt2++ )
		{
			/* Copy Key Frame information*/
			p_stCurrentKeyFrame->uwFrameNumber=			p_stFileKeyFrame->uwFrameNumber;
			p_stCurrentKeyFrame->uwMask=				p_stFileKeyFrame->uwMask;
 
			p_stCurrentKeyFrame->uwNumOfQuatOri=		(unsigned short)(uwNumOfFirstQuaternion + p_stFileKeyFrame->uwNumOfQuatOri);
			p_stCurrentKeyFrame->uwNumOfQuatSca=		(unsigned short)(uwNumOfFirstQuaternion + p_stFileKeyFrame->uwNumOfQuatSca);
			p_stCurrentKeyFrame->uwNumOfScaleValues=	(unsigned short)(uwNumOfFirstVector	   + p_stFileKeyFrame->uwNumOfScaleValues);
			p_stCurrentKeyFrame->uwNumOfPosition=		(unsigned short)(uwNumOfFirstVector     + p_stFileKeyFrame->uwNumOfPosition);
			p_stCurrentKeyFrame->swInterpolationParameter=	p_stFileKeyFrame->swInterpolationParameter;
 
			/* World Pivot position*/
			fn_v_ExpandQuat  ( a4_xQuatOri,  p_a4_xQuaternions[ p_stCurrentKeyFrame->uwNumOfQuatOri ] );
			fn_v_ExpandQuat( a4_xQuatSca,  p_a4_xQuaternions[ p_stCurrentKeyFrame->uwNumOfQuatSca ] );
			if	(ulInd == 0)
			{	register	SEB_xReal	xTmp;
 
				xTmp=	0.0f;
				p_stCurrentKeyFrame->a3_xWorldPivotPosition[0]=	xTmp;
				p_stCurrentKeyFrame->a3_xWorldPivotPosition[1]=	xTmp;
				p_stCurrentKeyFrame->a3_xWorldPivotPosition[2]=	xTmp;
			}
			else
			{
				fn_v_QuatToMatrix( a3a3_xMtxOri, a4_xQuatOri );
 
				/* optim AR9811*/
				if((a4_xQuatSca[0]!=0.0f)||(a4_xQuatSca[1]!=0.0f)||(a4_xQuatSca[2]!=0.0f)||(a4_xQuatSca[3]!=1.0f))
				{
				fn_v_QuatToMatrix( a3a3_xMtxSca, a4_xQuatSca );
				fn_v_InvRotDiaRot( a3a3_xScaleMatrix, a3a3_xMtxSca, p_a3_xVectors[ p_stCurrentKeyFrame->uwNumOfScaleValues ] );
				fn_v_MatrixByVector( a3_xTmpVec, a3a3_xScaleMatrix, p_a3_xVectors[ p_stCurrentChannel->uwNumOfLocalPivotPos ] );
				}
				else
				{
					a3_xTmpVec[0]=p_a3_xVectors[ p_stCurrentKeyFrame->uwNumOfScaleValues ][0]*p_a3_xVectors[ p_stCurrentChannel->uwNumOfLocalPivotPos ][0];
					a3_xTmpVec[1]=p_a3_xVectors[ p_stCurrentKeyFrame->uwNumOfScaleValues ][1]*p_a3_xVectors[ p_stCurrentChannel->uwNumOfLocalPivotPos ][1];
					a3_xTmpVec[2]=p_a3_xVectors[ p_stCurrentKeyFrame->uwNumOfScaleValues ][2]*p_a3_xVectors[ p_stCurrentChannel->uwNumOfLocalPivotPos ][2];
				}
 
				fn_v_MatrixByVector( p_stCurrentKeyFrame->a3_xWorldPivotPosition, a3a3_xMtxOri, a3_xTmpVec  );
			}
			uwNumOfPosition=	p_stCurrentKeyFrame->uwNumOfPosition;
			p_stCurrentKeyFrame->a3_xWorldPivotPosition[0]+=	p_a3_xVectors[ uwNumOfPosition ][0];
			p_stCurrentKeyFrame->a3_xWorldPivotPosition[1]+=	p_a3_xVectors[ uwNumOfPosition ][1];
			p_stCurrentKeyFrame->a3_xWorldPivotPosition[2]+=	p_a3_xVectors[ uwNumOfPosition ][2];
 
			/* DistMaster*/
			p_stCurrentKeyFrame->xDistMaster=	fn_x_VectorLength( p_a3_xVectors[ uwNumOfPosition ] );
 
			/* If we are not on the first keyframe*/
			if	( uwCnt2 > 0 )
			{
				p_stOldKeyFrame->uwAngQuatOri=	0x0000;
				if	((p_stOldKeyFrame->uwMask & SEB_xMaskQuatOri) == 0x0000)
					p_stOldKeyFrame->uwAngQuatOri=	fn_uw_AngleBetweenQuat(	a4_xOldQuatOri, a4_xQuatOri );
 
				p_stOldKeyFrame->uwAngQuatSca=	0x0000;
				if	((p_stOldKeyFrame->uwMask & SEB_xMaskQuatSca) == 0x0000)
					p_stOldKeyFrame->uwAngQuatSca=	fn_uw_AngleBetweenQuat(	a4_xOldQuatSca, a4_xQuatSca );
 
				/* Copy KeyFrames references*/
				uwNumOfCurrentFrameNumber=	p_stFileKeyFrame->uwFrameNumber;
				if	( uwNumOfCurrentFrameNumber > p_stCurrentA3dGENERAL->uwEndFrame )
					uwNumOfCurrentFrameNumber=	p_stCurrentA3dGENERAL->uwEndFrame;
#pragma warning(disable:4244)
				uwNumOfCurrentFrameNumber-=	p_stCurrentA3dGENERAL->uwStartFrame;
#pragma warning(default:4244)
 
				for	( uwCnt3=uwNumOfOldFrameNumber ; uwCnt3<uwNumOfCurrentFrameNumber ; uwCnt3++ )
					p_stFramesKF[ulNumOfFirstFrameKF + uwCnt3].uwNumOfKeyFrame=	uwNumOfOldKeyFrame;
			}
 
			/* Copy old informations*/
			p_stOldKeyFrame=	p_stCurrentKeyFrame;
			fn_v_CopyQuat( a4_xOldQuatOri, a4_xQuatOri );
			fn_v_CopyQuat( a4_xOldQuatSca, a4_xQuatSca );
			uwNumOfOldPosition=		uwNumOfPosition;
			uwNumOfOldFrameNumber=	uwNumOfCurrentFrameNumber;
			uwNumOfOldKeyFrame=		uwNumOfCurrentKeyFrame;
 
			uwNumOfCurrentKeyFrame++;
 
			p_stFileKeyFrame++;
			p_stCurrentKeyFrame++;
		}
 
		/* For last keyframe*/
		p_stCurrentKeyFrame=	&p_stKeyFrames[ p_stCurrentChannel->uwNumOfFirstKeyFrame ];
		fn_v_ExpandQuat  ( a4_xQuatOri,  p_a4_xQuaternions[ p_stCurrentKeyFrame->uwNumOfQuatOri ] );
		fn_v_ExpandQuat  ( a4_xQuatSca,  p_a4_xQuaternions[ p_stCurrentKeyFrame->uwNumOfQuatSca ] );
 
		p_stOldKeyFrame->uwAngQuatOri=	0x0000;
		if	((p_stOldKeyFrame->uwMask & SEB_xMaskQuatOri) == 0x0000)
			p_stOldKeyFrame->uwAngQuatOri=		fn_uw_AngleBetweenQuat(	a4_xOldQuatOri, a4_xQuatOri );
 
		p_stOldKeyFrame->uwAngQuatSca=	0x0000;
		if	((p_stOldKeyFrame->uwMask & SEB_xMaskQuatSca) == 0x0000)
			p_stOldKeyFrame->uwAngQuatSca=		fn_uw_AngleBetweenQuat(	a4_xOldQuatSca, a4_xQuatSca );
 
 
		for	( uwCnt3=uwNumOfOldFrameNumber ; uwCnt3<(p_stCurrentA3dGENERAL->uwEndFrame - p_stCurrentA3dGENERAL->uwStartFrame) ; uwCnt3++ )
			p_stFramesKF[ulNumOfFirstFrameKF + uwCnt3].uwNumOfKeyFrame=	uwNumOfOldKeyFrame;
 
		p_stCurrentChannel++;
	}
 
	/* Normalization of positions*/
	for	( uwCnt1=p_stCurrentA3dGENERAL->uwNumOfFirstPosition ; uwCnt1<uwNumOfFirstVector+p_stCurrentA3dGENERAL->uwNumberOfVectors ; uwCnt1++ )
		fn_v_NormalizeVector( p_a3_xVectors[ uwCnt1 ] );
 
 
	/* Calculate (uwAngObjCentre) and (WorldPivotPosition with hierarchy)*/
	p_stCurrentChannel=	p_stFirstChannel;
	for	( uwCnt1=0 ; uwCnt1<p_stCurrentA3dGENERAL->uwNumberOfChannels ; uwCnt1++ )
	{
		p_stOldKeyFrame=		&p_stKeyFrames[ p_stCurrentChannel->uwNumOfFirstKeyFrame ];
		p_stCurrentKeyFrame=	&p_stOldKeyFrame[1];
		uwMax=	p_stCurrentChannel->uwNumberOfKeys;
		for	( uwCnt2=1 ; uwCnt2<uwMax ; uwCnt2++ )
		{	/* uwAngObjCentre*/
			p_stOldKeyFrame->uwAngObjCentre=
				fn_uw_AngleBetweenVect(	p_a3_xVectors[ p_stOldKeyFrame->uwNumOfPosition ],
										p_a3_xVectors[ p_stCurrentKeyFrame->uwNumOfPosition ] );
 
			p_stOldKeyFrame++;
			p_stCurrentKeyFrame++;
		}
		/* For last keyframe*/
		p_stOldKeyFrame->uwAngObjCentre=
			fn_uw_AngleBetweenVect(	p_a3_xVectors[ p_stOldKeyFrame->uwNumOfPosition ], p_a3_xVectors[ p_stKeyFrames[p_stCurrentChannel->uwNumOfFirstKeyFrame].uwNumOfPosition ] );
 
		p_stCurrentChannel++;
	}
 
	p_vCurrentFile=	(void *) p_stFileKeyFrame;
}
 
/*----------------------------------------------------------------------------
//  Description : fn_v_LoadMorphingData
//  Load morphing data from the rom
----------------------------------------------------------------------------//
//  Methods : None
----------------------------------------------------------------------------//
//  Input :	
//  Output :  
----------------------------------------------------------------------------//
//  Creation date : Mar 98			  		  Author: Alain Robin
----------------------------------------------------------------------------//
//  Modifications :	
//  Modification date :				          Modification author : 
----------------------------------------------------------------------------*/
void	fn_v_LoadMorphingData	( void )
{	
	register unsigned short	uwMax/*, uwCnt1*/;
	register unsigned long ulInd;
 
	/* Alignment*/
	while	( (((unsigned long) p_vCurrentFile) % 4) != 0 )
		p_vCurrentFile=	(void *) (((unsigned char *) p_vCurrentFile) + 1);
 
	uwMax=	p_stCurrentA3dGENERAL->uwNumberOfMorphData;
	ulInd=	fn_ul_AllocateOnStack( eStackMorphData, p_stCurrentA3dGENERAL->uwNumberOfMorphData);
 
	p_stCurrentA3dGENERAL->uwNumOfFirstMorphData = (unsigned short)ulInd;
	p_stCurrentMorphData=	&p_stMorphData[ulInd];
 
	p_stFileMorphData=		(tdstFileMorphData *) p_vCurrentFile;
/*	for	( uwCnt1=0 ; uwCnt1<uwMax ; uwCnt1++ )
	{
		p_stCurrentMorphData->ucTarget=p_stFileMorphData->ucTarget; 
		p_stCurrentMorphData->ucMorphingAmount=p_stFileMorphData->ucMorphingAmount;
		p_stCurrentMorphData->uwChannelNumber=p_stFileMorphData->uwChannelNumber;
		p_stCurrentMorphData->uwFrameNumber=p_stFileMorphData->uwFrameNumber;
 
		p_stFileMorphData++;
		p_stCurrentMorphData++;
	} */
 
	memcpy(p_stCurrentMorphData,p_stFileMorphData,sizeof(tdstFileMorphData)*uwMax); /* optim AR9811*/
 
/*	p_vCurrentFile=	(void *) p_stFileMorphData;*/
	p_vCurrentFile=	(void *) (p_stFileMorphData+uwMax);
	p_stCurrentMorphData+=uwMax;
}
 
/*AR9809 Now, this function can be in the common part (same structure used)*/
void	fn_v_LoadEvents()
{	register unsigned short	uwCnt1, uwMax;
	register unsigned long ulInd;
 
	/* Alignment*/
	while	( (((unsigned long) p_vCurrentFile) % 4) != 0 )
		p_vCurrentFile=	(void *) (((unsigned char *) p_vCurrentFile) + 1);
 
	uwMax=	p_stCurrentA3dGENERAL->uwNumberOfEvents;
	ulInd=	fn_ul_AllocateOnStack( eStackEvents, uwMax );
 
	p_stCurrentA3dGENERAL->uwNumOfFirstEvent = (unsigned short)ulInd;
	p_stCurrentEvent=	&p_stEvents[ulInd];
 
	p_stFileEvent=		(tdstFileEvent *) p_vCurrentFile;
	M_A3xDebug( "EVNT", tdstFileEvent, p_stFileEvent );
	for	( uwCnt1=0 ; uwCnt1<uwMax ; uwCnt1++ )
	{
		p_stCurrentEvent->uwFrameNumber=		p_stFileEvent->uwFrameNumber;
		p_stCurrentEvent->usEventNumberInTBL=	p_stFileEvent->usEventNumberInTBL;
		p_stCurrentEvent->p_stfEventInTBL=      NULL;
		p_stCurrentEvent->uwChannelNumber=		p_stFileEvent->uwChannelNumber;
 
		p_stFileEvent++;
		p_stCurrentEvent++;
	}
 
	p_vCurrentFile=	(void *) p_stFileEvent;
}
 
/* ***********************************************************************************/
 
 

#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC 04/06/99 */
unsigned short	fn_uw_LoadAnimV6	( void	*_p_vStartFile )
{
 
	p_vCurrentFile=	_p_vStartFile;
	fn_v_LoadA3dGENERAL	();
	fn_v_LoadVectors	();
	fn_v_LoadQuaternions();
	fn_v_LoadHierarchies();
	fn_v_LoadNTTO		();
	fn_v_LoadOnlyFrames	();
	fn_v_LoadChannels	();
	fn_v_LoadFrames		();
	fn_v_LoadKeyFrames	();
	fn_v_LoadEvents		();
/*	fn_v_LoadLights		();*/
	fn_v_LoadMorphingData(); /*AR980306*/
	return	(unsigned short)(fn_ul_GetStackAlloc(eStackA3dGENERAL));
 
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC 04/06/99 */

 
 
 
 
 
/* ***********************************************************************************/
void	fn_v_LoadCachedAnimV6	(	char	*_p_cDestMem,
									void	*_p_vStartFile,
									unsigned long _ulMaxlength )
{
#ifdef ANIM_PROFILE
	u64 ulBefore,ulAfter;
 
	if(_ulMaxlength==10240)
		ulBefore=osGetTime();
#endif
#ifdef	A3X_CacheIsUsed
	/* Reset Stacks*/
	M_v_ResetOneStack( eStackA3dGENERAL );
	M_v_ResetOneStack( eStackVertexes );
	M_v_ResetOneStack( eStackQuaternions );
	M_v_ResetOneStack( eStackHierarchies );
	M_v_ResetOneStack( eStackNTTO );
	M_v_ResetOneStack( eStackOnlyFrames );
	M_v_ResetOneStack( eStackChannels );
	M_v_ResetOneStack( eStackFrames );
	M_v_ResetOneStack( eStackFramesKF );
	M_v_ResetOneStack( eStackKeyFrames );
	M_v_ResetOneStack( eStackEvents );
	M_v_ResetOneStack( eStackMorphData );
 
	p_vCurrentFile=	_p_vStartFile;
 
	p_stA3dGENERAL=			(tdstA3dGENERAL *) _p_cDestMem;
	fn_v_LoadA3dGENERAL	();
 
	p_a3_xVectors=			(tdxVector3 *) &p_stA3dGENERAL[1];
	fn_v_LoadVectors	();
 
	p_a4_xQuaternions=		(tdxSShortQuater4 *) p_stCurrentVector3;
	fn_v_LoadQuaternions();
 
	p_stHierarchies=		(tdstHierarchy *) p_stCurrentQuater4;
	fn_v_LoadHierarchies();
 
	p_stNTTO=				(tdstNTTO *) p_stCurrentHierarchy;
	fn_v_LoadNTTO		();
 
	p_stOnlyFrames=			(tdstOnlyFrame *) p_stCurrentNTTO;
	fn_v_LoadOnlyFrames	();
 
	p_stChannels=			(tdstChannel *) p_stCurrentOnlyFrame;
	while	( (((unsigned long) p_stChannels) %4) != 0 )
		p_stChannels=	(tdstChannel *) (((char *) p_stChannels) + 1);
	fn_v_LoadChannels	();
 
	p_stFrames=				(tdstFrame *) p_stCurrentChannel;
	fn_v_LoadFrames		();
 
	p_stFramesKF=			(tdstFrameKF *) p_stCurrentFrame;
	/*p_stKeyFrames=			(tdstKeyFrame *) &p_stFramesKF[ p_stCurrentA3dGENERAL->uwNumberOfChannels * p_stCurrentA3dGENERAL->uwNumberOfFrames ];*/
	p_stKeyFrames=			(tdstKeyFrame *) &p_stFramesKF[	p_stCurrentA3dGENERAL->uwNumberOfChannels *
															(p_stCurrentA3dGENERAL->uwEndFrame - p_stCurrentA3dGENERAL->uwStartFrame) ];
	/* Alignment*/
	if	( (((unsigned long) p_stKeyFrames) & 0x0002) != 0x0000 )
		p_stKeyFrames=	(tdstKeyFrame *) (((char *) p_stKeyFrames) + 2);
	fn_v_LoadKeyFrames	();
 
	p_stEvents=				(tdstEvent *) p_stCurrentKeyFrame;
	fn_v_LoadEvents		();
 
/*	fn_v_LoadLights		();*/
 
	/* due to alignment*/
	while	( (((unsigned long) p_stCurrentEvent) %4) != 0 )
		p_stCurrentEvent=	(tdstEvent *) (((char *) p_stCurrentEvent) + 1);
	
	p_stMorphData=			(tdstMorphData *) p_stCurrentEvent; /*AR9803*/
	fn_v_LoadMorphingData(); /*AR9803*/
 
#ifdef ANIM_PROFILE
	if(_ulMaxlength==10240)
	{
		ulAfter=osGetTime();
		osSyncPrintf("%llu\n",ulAfter-ulBefore);
	}
#endif
 
	/*AR9901 For debug only -> to be removed !!!*/
#ifdef ANIM_DEBUG
	if(*((unsigned char*)(g_p_cSecurityMalloc))!=0xA1)
	{
		ASM_BREAK;
	}
#endif /*#ifdef ANIM_DEBUG*/
 
#ifdef ANIM_DEBUG
	/* due to alignment*/
	while	( (((unsigned long) p_stCurrentMorphData) %4) != 0 )
		p_stCurrentMorphData=	(tdstMorphData *) (((char *) p_stCurrentMorphData) + 1);
 
	if	( abs((unsigned long)p_stCurrentMorphData - (unsigned long)p_stCurrentA3dGENERAL) > _ulMaxlength )
	{
		osSyncPrintf("fn_v_LoadCachedAnimV6 (%d > %d)\n", ((unsigned long)p_stCurrentMorphData - (unsigned long)p_stCurrentA3dGENERAL),_ulMaxlength);
		osSyncPrintf("   uwNumberOfFrames     = %4d\n", p_stCurrentA3dGENERAL->uwNumberOfFrames);
		osSyncPrintf("   uwNumberOfVectors    = %4d\n", p_stCurrentA3dGENERAL->uwNumberOfVectors);
		osSyncPrintf("   uwNumberOfQuaternions= %4d\n", p_stCurrentA3dGENERAL->uwNumberOfQuaternions);
		osSyncPrintf("   uwNumberOfHierarchies= %4d\n", p_stCurrentA3dGENERAL->uwNumberOfHierarchies);
		osSyncPrintf("   uwNumberOfNTTO       = %4d\n", p_stCurrentA3dGENERAL->uwNumberOfNTTO);
		osSyncPrintf("   uwNumberOfOnlyFrames = %4d\n", (p_stCurrentA3dGENERAL->uwEndFrame - p_stCurrentA3dGENERAL->uwStartFrame));
		osSyncPrintf("   uwNumberOfChannels   = %4d\n", p_stCurrentA3dGENERAL->uwNumberOfChannels);
		osSyncPrintf("   uwNumberOfSavedFrames= %4d\n", p_stCurrentA3dGENERAL->uwNumberOfSavedFrames);
		osSyncPrintf("   uwNumberOfKeyFrames  = %4d\n", p_stCurrentA3dGENERAL->uwNumberOfKeyFrames);
		osSyncPrintf("   uwNumberOfEvents     = %4d\n", p_stCurrentA3dGENERAL->uwNumberOfEvents);
		osSyncPrintf("   uwNumberOfMorphData  = %4d\n", p_stCurrentA3dGENERAL->uwNumberOfMorphData);
		osSyncPrintf("   uwStartFrame         = %4d\n", p_stCurrentA3dGENERAL->uwStartFrame);
		osSyncPrintf("   uwEndFrame           = %4d\n", p_stCurrentA3dGENERAL->uwEndFrame);
 
		osSyncPrintf("   p_stA3dGENERAL       = %d\n", 0);
		osSyncPrintf("   p_a3_xVectors        = %d\n", (unsigned long)p_a3_xVectors - (unsigned long)p_stA3dGENERAL);
		osSyncPrintf("   p_a4_xQuaternions    = %d\n", (unsigned long)p_a4_xQuaternions - (unsigned long)p_stA3dGENERAL);
		osSyncPrintf("   p_stHierarchies      = %d\n", (unsigned long)p_stHierarchies - (unsigned long)p_stA3dGENERAL);
		osSyncPrintf("   p_stNTTO             = %d\n", (unsigned long)p_stNTTO - (unsigned long)p_stA3dGENERAL);
		osSyncPrintf("   p_stOnlyFrames       = %d\n", (unsigned long)p_stOnlyFrames - (unsigned long)p_stA3dGENERAL);
		osSyncPrintf("   p_stChannels         = %d\n", (unsigned long)p_stChannels - (unsigned long)p_stA3dGENERAL);
		osSyncPrintf("   p_stFrames           = %d\n", (unsigned long)p_stFrames - (unsigned long)p_stA3dGENERAL);
		osSyncPrintf("   p_stFramesKF         = %d\n", (unsigned long)p_stFramesKF - (unsigned long)p_stA3dGENERAL);
		osSyncPrintf("   p_stKeyFrames        = %d\n", (unsigned long)p_stKeyFrames - (unsigned long)p_stA3dGENERAL);
		osSyncPrintf("   p_stEvents           = %d\n", (unsigned long)p_stEvents - (unsigned long)p_stA3dGENERAL);
		osSyncPrintf("   p_stMorphData        = %d\n", (unsigned long)p_stMorphData - (unsigned long)p_stA3dGENERAL);
 
		ASM_BREAK;
	}
#endif /* ANIM_DEBUG */
#endif
}
 
 
 
/* ***********************************************************************************/
#undef	A3X_LOAD_C
