/* ***********************************************************************************/
/* * "a3x_cach.c"																	**/
/* * Written by :	Sébastien Rubens												**/
/* * Tabulations :	4 char															**/
/* ***********************************************************************************/
#define	A3X_CACH_C
 
 
 
/* ***********************************************************************************/
/*																	Included files*/
 
#include "PlayAnim/Interpol/specif/a3x_pref.h"
 
/*#define LST2_StaticIsOptimised*/
 
#include "TOOLSCPA.h"
#include "cpa_std.h"
#include "STRUCTUR/Anim_s.h"
#include "STRUCTUR/Engmode.h"
 
#ifdef	A3X_N64
#include "u_dma.h"
#include "memload.h"
#include "ZeMem.h"
#endif
 
#include "PlayAnim/Interpol/a3x_glob.h"
#include "PlayAnim/Interpol/a3x_load.h"
#include "PlayAnim/Interpol/a3x_mem.h"
#include "PlayAnim/Interpol/a3x_cach.h"
 
#define	UseCompressedAnimations
 
#ifdef U64
#include "RastMem.h"
#endif /* U64 */
 
 
/* ***************************************************************************************************/
#ifdef	UseCompressedAnimations
extern	void	slidstart( unsigned char *, unsigned char * );
#endif
 
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
unsigned short	uwMaxInStackFrame3d= 0, uwMaxInStackElement3d= 0;
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
char			*p_cLoadAnimBuf;
char			*p_cCompressedAnimBuf;
 
/*AR9901 For debug -> to be removed !*/
#ifdef ANIM_DEBUG
char* g_p_cSecurityMalloc;
#endif /*ANIM_DEBUG*/
 
/* ***************************************************************************************************/
unsigned short	uwMaxNumberOfAnims=	2000;
 
/* Input cache*/
#ifdef	A3X_CacheIsUsed
#define	NbCacheLists	5
#endif
 
/* Output cache*/
#define	uwMaxInTabFrame3d			100
#define uwMaxInTabElement3d			1000
 
#ifdef	A3X_N64
extern char	_animsSegmentRomStart[];
extern char	_animsSegmentRomEnd[];
#ifndef FORCE_REAL_TIME_LOAD
extern char	_anims_rawSegmentRomStart[];
extern char	_anims_rawSegmentRomEnd[];
#endif
extern char	_shortAnimsSegmentRomStart[];
extern char	_shortAnimsSegmentRomEnd[];
extern char	_a3dheaderSegmentRomStart[];
extern char	_a3dheaderSegmentRomEnd[];
#ifdef	A3X_CUT
extern char	_cuttableSegmentRomStart[];
extern char	_cuttableSegmentRomEnd[];
#endif
#endif
 
/* Max size of cutted animation*/
#define	MaxSizeOfList		(MaxRAMSizeOfAnim/1024)
 
 
 
/* ***************************************************************************************************/
/* Input cache*/
 
 
#ifdef A3X_N64
unsigned long	ulNbIntAnims;
 
unsigned long	*p_ulAnimOffsets;
#endif
#ifdef	A3X_CacheIsUsed
unsigned long	ulMaxRamSizeOfAnim, ulMaxRomSizeOfAnim;
 
char			*p_cBigMalloc;
tdstCacheLine	*p_stCacheLine;
tdstA3dHeader	*p_stA3dHeaders;
char			*p_cMemBlocs;
 
unsigned short	ax_uwCacheList[NbCacheLists];		/* Tete de liste*/
unsigned short	ax_uwCacheListNbElt[]=				/* Nombre de cases par zone*/
{	
	25,												/* Zone 1*/
	8,
	7,
 
	7,
	10
};
unsigned short	ax_uwCacheListSize[]=
{	
	1,
	3,
	5,
	7,
	10,
	(MaxSizeOfList+1)
};
unsigned short	ax_uwSizeToList[MaxSizeOfList];
 
unsigned long	ulNumberOfCacheLines;
#endif
 
 
/* ***************************************************************************************************/
 
unsigned short	*p_uwLastA3dGENERAL;
 
 
 
 
/* ***************************************************************************************************/
/* Output cache*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
unsigned long		ulLastEngineFrame=	0xFFFFFFFF;
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
/*tdstOutputCacheLine	ax_stOutputCacheLine[uwMaxInTabFrame3d]; // Useless now... AR9808*/
 
#ifdef	A3X_N64
 
/* Global variables used by loading functions*/
char* g_p_cROMAnimBlocStart=_animsSegmentRomStart;

#ifdef ANIM_DEBUG
char* g_p_cROMAnimBlocStop=_animsSegmentRomEnd;
#endif 

#endif
 
#ifndef FORCE_REAL_TIME_LOAD
int g_bRealTimeAnimationLoad = FALSE;
#endif
 
#ifdef	A3X_N64
/*-----------------------------------------------------------------------------
 *  Name : fn_vInitROMLoad
 *-----------------------------------------------------------------------------
 *  Description :   Initialise the ROM loading system for the animation
 *					(Real time load or use memory extension)
 *-----------------------------------------------------------------------------
 *  Input :         
 *  Output :        
 *-----------------------------------------------------------------------------
 *  Creation date : Oct 98            Author : Al1
 *-----------------------------------------------------------------------------*/
#ifndef FORCE_REAL_TIME_LOAD
void fn_vInitROMLoad(void)
{
#ifdef A3X_REAL_TIME_LOAD
	g_p_cROMAnimBlocStart=_animsSegmentRomStart;
	g_p_cROMAnimBlocStop=_animsSegmentRomEnd;
	g_bRealTimeAnimationLoad=TRUE;
	return;
#endif /*A3X_REAL_TIME_LOAD*/
	if(osMemSize>4194304) /* memory available > 4M*/
	{
		/* Here we can load all the animation in RAM*/
		g_p_cROMAnimBlocStart=_anims_rawSegmentRomStart;
		g_p_cROMAnimBlocStop=_anims_rawSegmentRomEnd;
		g_bRealTimeAnimationLoad=FALSE;
	}
	else
	{
		/* Here we must use real time load system*/
		g_p_cROMAnimBlocStart=_animsSegmentRomStart;
		g_p_cROMAnimBlocStop=_animsSegmentRomEnd;
		g_bRealTimeAnimationLoad=TRUE;
	}
}
#endif
#endif /*A3X_N64*/
 
/* ***************************************************************************************************/
#ifdef	A3X_N64
void	*fn_p_ReadAnimFromROM(	unsigned short	_uwNumOfIntAnim )
{
#ifdef	A3X_N64
#ifdef ANIM_DEBUG
	if	( _uwNumOfIntAnim >= ulNbIntAnims )
	{
		osSyncPrintf("fn_p_ReadAnimFromROM1 : numéro d'animation trop grand\n");
		osSyncPrintf("fn_p_ReadAnimFromROM1 : _uwNumOfIntAnim = %d\n", _uwNumOfIntAnim );
		ASM_BREAK;
	}
	if	( g_p_cROMAnimBlocStart + (0x7FFFFFFF & p_ulAnimOffsets[_uwNumOfIntAnim + 1]) > g_p_cROMAnimBlocStop )
	{
		osSyncPrintf("fn_p_ReadAnimFromROM2 : chargement d'anims trop grand\n");
		osSyncPrintf("fn_p_ReadAnimFromROM2 : _uwNumOfIntAnim = %d\n", _uwNumOfIntAnim );
		ASM_BREAK;
	}
#endif /*ANIM_DEBUG*/
#endif
 
#ifdef	UseCompressedAnimations
	if	(p_ulAnimOffsets[_uwNumOfIntAnim] & 0x80000000)
	{
		LDR_fn_vLoadFromROM(	( g_p_cROMAnimBlocStart + (0x7FFFFFFF & p_ulAnimOffsets[_uwNumOfIntAnim] )),
								( g_p_cROMAnimBlocStart + (0x7FFFFFFF & p_ulAnimOffsets[_uwNumOfIntAnim + 1]) ),
								p_cCompressedAnimBuf,
								MSG_BLOCK	);
		slidstart(p_cCompressedAnimBuf, p_cLoadAnimBuf);
	}
	else
#endif
		LDR_fn_vLoadFromROM(	( g_p_cROMAnimBlocStart + p_ulAnimOffsets[_uwNumOfIntAnim] ),
								( g_p_cROMAnimBlocStart + (0x7FFFFFFF & p_ulAnimOffsets[_uwNumOfIntAnim + 1]) ),
								p_cLoadAnimBuf,
								MSG_BLOCK	);
	return	((void *) p_cLoadAnimBuf);
}
#endif
 
/* ***************************************************************************************************/
#ifdef	A3X_CUT
tdstShortA3dGENERAL	*fn_p_ReadShortAnimFromROM(	unsigned short	_uwNumOfIntAnim )
{
	LDR_fn_vLoadFromROM(	( _shortAnimsSegmentRomStart + _uwNumOfIntAnim * sizeof(tdstShortA3dGENERAL) ),
							( _shortAnimsSegmentRomStart + (_uwNumOfIntAnim + 1) * sizeof(tdstShortA3dGENERAL) ),
							p_cLoadAnimBuf,
							MSG_BLOCK	);
 
	return	((tdstShortA3dGENERAL *) p_cLoadAnimBuf);
}
 
/* ***************************************************************************************************/
#endif
#ifdef	A3X_CacheIsUsed
void	*fn_p_Align16(	void	*p_vPointer	)
{
	if	( (((unsigned long) p_vPointer) & 0x0000000F) != 0x00000000 )
			return	( (void *) ((((unsigned long) p_vPointer) & 0xFFFFFFF0) + 0x00000010) );
	else	return	p_vPointer;
	
}
#endif
 
 
 
/* ***************************************************************************************************/
#ifdef	A3X_CacheIsUsed
void	fn_v_CacheAllocation( void )
{
/*	p_stOutputCacheLine=	(tdstOutputCacheLine *)			fn_p_Align16( p_cBigMalloc );*/
	p_stCacheLine=			(tdstCacheLine *)				fn_p_Align16( p_cBigMalloc );
	p_ulAnimOffsets=		(unsigned long *)				fn_p_Align16( &p_stCacheLine[ulNumberOfCacheLines] );
/*HP980806*/
/*	p_stFrame3d=			(tdstFrame3d *)					fn_p_Align16( &p_ulAnimOffsets[1 + ulNbIntAnims] );*/
/*	p_p_stElement3d=		(tdstElement3d* *)				fn_p_Align16( &p_stFrame3d[uwMaxInTabFrame3d] );*/
/*	p_stAngularSpeedMatrix=	(MTH3D_tdstMatrix *)			fn_p_Align16( &p_p_stElement3d[uwMaxInTabElement3d] );*/
/*	p_stHierarchy=			(tdstPLA_Hierarchy *)			fn_p_Align16( &p_stAngularSpeedMatrix[uwMaxInTabFrame3d] );*/
/*	p_stElement3d=			(tdstElement3d *)				fn_p_Align16( &p_stHierarchy[uwMaxInTabFrame3d] );*/
/*	p_stPosMatrix=			(POS_tdstCompletePosition *)	fn_p_Align16( &p_stElement3d[uwMaxInTabElement3d] ); */
/*	p_cLoadAnimBuf=			(char *)						fn_p_Align16( &p_stPosMatrix[uwMaxInTabElement3d] );*/
	p_cLoadAnimBuf=			(char *)						fn_p_Align16( &p_ulAnimOffsets[1 + ulNbIntAnims] );
	/*	p_cCompressedAnimBuf=	(char *)						fn_p_Align16( &p_cLoadAnimBuf[ulMaxRamSizeOfAnim] );*/
	p_stA3dHeaders=			(tdstA3dHeader *)				fn_p_Align16( &p_cLoadAnimBuf[ulMaxRamSizeOfAnim] );
#ifdef	A3X_CUT
	p_uwLastA3dGENERAL=		(unsigned short *)				fn_p_Align16( &p_stA3dHeaders[ulNbIntAnims] );
	p_stCuttedAnim=			(tdstCuttedAnim *)				fn_p_Align16( &p_uwLastA3dGENERAL[ulNbIntAnims] );
	p_cMemBlocs=			(char *)						fn_p_Align16( &p_stCuttedAnim[ulNbIntAnims] );
#else
	p_cMemBlocs=			(char *)						fn_p_Align16( &p_stA3dHeaders[ulNbIntAnims] );
#endif
}
#endif
 
 
#ifdef	A3X_CacheIsUsed
 
/* ***************************************************************************************************/
void	fn_v_InitCache( void )
{
	
	unsigned long	ulNumOfAnim;
	unsigned long	ulStart, ulNumInSizeToList, ulOld, ulCnt2;
	unsigned long	ulNbElem, ulNumOfBloc;
	unsigned long	ulCnt1;
	
#ifndef FORCE_REAL_TIME_LOAD
	if(g_bRealTimeAnimationLoad)
	{
#endif

#if defined(FINAL_VERSION) && !defined(FINAL_VERSION_FOR_TESTERS)
	/* When we are in final version mode, we can increase the anim cache */
	if(osMemSize>C_4Megs) /* RAM xtension detected */
	{
		ax_uwCacheListNbElt[0]+=250;
		ax_uwCacheListNbElt[1]+=80;
		ax_uwCacheListNbElt[2]+=100;
		ax_uwCacheListNbElt[3]+=140;
		ax_uwCacheListNbElt[4]+=180;
	}
#endif /* defined(FINAL_VERSION) && !defined(FINAL_VERSION_FOR_TESTERS) */
	/* ----------------------------------------------------------------------------------------------*/
	/* Init ax_uwSizeToList table*/
	ulNumInSizeToList=	0;
	ulOld=				0;
	for	( ulCnt1=0 ; ulCnt1<NbCacheLists ; ulCnt1++ )
		{	
			for	( ulCnt2=ulOld ; ulCnt2<ax_uwCacheListSize[ulCnt1] ; ulCnt2++ )
			ax_uwSizeToList[ulNumInSizeToList++]=	(unsigned short) ulCnt1;
		ulOld=	ax_uwCacheListSize[ulCnt1];
	}
 
 
	/* ----------------------------------------------------------------------------------------------*/
	/* Init p_stCacheLine table*/
	ulNumberOfCacheLines=	0;
	for	( ulCnt1=0 ; ulCnt1<NbCacheLists ; ulCnt1++ )
		ulNumberOfCacheLines+=	ax_uwCacheListNbElt[ulCnt1];
 
 
	/* ----------------------------------------------------------------------------------------------*/
/*	p_cBigMalloc=		(char *) M_p_GameMallocInHLM( (uwMaxNumberOfAnims+1L)*sizeof(unsigned long) );	// WithoutFree !!!*/
	p_cBigMalloc=		(char *) fn_pvAllocTmp( (uwMaxNumberOfAnims+1L)*sizeof(unsigned long), 16 );	/* WithFree*/
 
	/* Read number of animations*/
	p_ulAnimOffsets=	(unsigned long *)	fn_p_Align16( p_cBigMalloc );
		LDR_fn_vLoadFromROM(	( g_p_cROMAnimBlocStart ),
							( g_p_cROMAnimBlocStart + 3*sizeof(unsigned long) ),
							(char *) p_ulAnimOffsets,
							MSG_BLOCK	);
	ulNbIntAnims=		*((unsigned long *) &p_ulAnimOffsets[0]);
	ulMaxRamSizeOfAnim=	*((unsigned long *) &p_ulAnimOffsets[1]);
	ulMaxRomSizeOfAnim=	*((unsigned long *) &p_ulAnimOffsets[2]);
 
		
	fn_vFreeRomTmp( (void *)p_cBigMalloc );	/* Oliv'*/
 
#ifdef UseCompressedAnimations
		GEO_M_CPAMalloc(p_cCompressedAnimBuf,char *,ulMaxRomSizeOfAnim+16,E_uwGEONotEnoughtMemory);
		p_cCompressedAnimBuf=(char*)fn_p_Align16(p_cCompressedAnimBuf); /* 16 bytes aligned for DMA transferts*/
#endif /*UseCompressedAnimations*/
 
	/* ----------------------------------------------------------------------------------------------*/
	/* Set relatives pointers*/
	p_cBigMalloc=			NULL;
	fn_v_CacheAllocation();
 
	/* Calculate memory size to allocate*/
	ulNumOfAnim=			((unsigned long) p_cMemBlocs) - ((unsigned long) p_cBigMalloc);
	for	(  ulCnt1=0 ; ulCnt1<NbCacheLists ; ulCnt1++ )
		ulNumOfAnim+=	ax_uwCacheListSize[ulCnt1] * 1024L * ax_uwCacheListNbElt[ulCnt1];
 
	/* Allocate memory*/
#ifdef U64
	RM_fn_vInitAddInfo();
#endif /* U64 */
	GEO_M_CPAMalloc(p_cBigMalloc,char *,ulNumOfAnim+16,E_uwGEONotEnoughtMemory); /* +16 because the address allocated can be not aligned to 16 chars !*/
#ifdef U64
	RM_fn_vAddInfo(eAnimPlayerCach,eSubAnimPlayerCach,eGeo);
#endif /* U64 */
	fn_v_CacheAllocation();
		
	M_PrintfN64(("   Malloc animations = %d octets\n", ulNumOfAnim));
		
#ifdef ANIM_DEBUG
	/* 1Ko added For security ! AR9901*/
	GEO_M_CPAMalloc(g_p_cSecurityMalloc,char *,1024,E_uwGEONotEnoughtMemory);
	memset(g_p_cSecurityMalloc,0xA1,1024);
#endif /*ANIM_DEBUG*/
 
	/* ----------------------------------------------------------------------------------------------*/
	/* Used in fn_p_GetEventsAddress to get last cutted animation A3dGENERAL (avoid first cutted animation loading)*/
	for	( ulCnt1=0 ; ulCnt1<ulNbIntAnims ; ulCnt1++ )
		p_uwLastA3dGENERAL[ulCnt1]=	(unsigned short) ulCnt1;
 
 
	/* ----------------------------------------------------------------------------------------------*/
	/* Init p_stCacheLine table*/
	ulNumOfBloc=			0;
	ulStart=				0;
	for	( ulCnt1=0 ; ulCnt1<NbCacheLists ; ulCnt1++ )
	{	ax_uwCacheList[ulCnt1]=	(unsigned short) ulStart;						/* Beginning of list*/
		ulNbElem=				ax_uwCacheListNbElt[ulCnt1];
		for	( ulCnt2=0 ; ulCnt2<ulNbElem ; ulCnt2++ )
		{
			p_stCacheLine[ulStart + ulCnt2].slCacheValue=		-4096;
			p_stCacheLine[ulStart + ulCnt2].uwNumOfA3dHeader=	SEB_Invalid;
			p_stCacheLine[ulStart + ulCnt2].uwNumOfMemBloc=		(unsigned short) ulNumOfBloc;
			p_stCacheLine[ulStart + ulCnt2].uwNext=				(unsigned short) (ulStart + ulCnt2 + 1);
			p_stCacheLine[ulStart + ulCnt2].uwPrev=				(unsigned short) (ulStart + ulCnt2 - 1);
			ulNumOfBloc+=										ax_uwCacheListSize[ulCnt1];
		}
		p_stCacheLine[ulStart].uwPrev=							(unsigned short) (ulStart + ulNbElem - 1);
		p_stCacheLine[ulStart + ulNbElem - 1].uwNext=			(unsigned short) ulStart;
		ulStart+=												ulNbElem;
	}
 
 
 
	/* ----------------------------------------------------------------------------------------------*/
	/* Read all animations offsets (p_ulAnimOffsets table)*/
		LDR_fn_vLoadFromROM(	( g_p_cROMAnimBlocStart + 4*sizeof(unsigned long) ),
								( g_p_cROMAnimBlocStart + ((5 + ulNbIntAnims) * sizeof(unsigned long)) ),
							(char *) p_ulAnimOffsets,
							MSG_BLOCK	);
 
	/* Init p_stA3dHeaders table*/
/*	for	( ulCnt1=0 ; ulCnt1<ulNbIntAnims ; ulCnt1++ )
	{	tdstFileA3dAnimationGENERAL	*p_stFileA3dAnimationGENERAL;
		unsigned long				ulSizeOfAnim;
 
		fn_p_ReadAnimFromROM(ulCnt1);
 
		p_stFileA3dAnimationGENERAL=	(tdstFileA3dAnimationGENERAL *) p_cLoadAnimBuf;
		ulSizeOfAnim=		sizeof(tdstA3dGENERAL) +
							sizeof(tdxVector3)		* (unsigned long) p_stFileA3dAnimationGENERAL->uwNumberOfVectors +
							sizeof(tdxSShortQuater4)* (unsigned long) p_stFileA3dAnimationGENERAL->uwNumberOfQuaternions +
							sizeof(tdstHierarchy)	* (unsigned long) p_stFileA3dAnimationGENERAL->uwNumberOfHierarchies +
							sizeof(tdstNTTO)		* (unsigned long) p_stFileA3dAnimationGENERAL->uwNumberOfSavedNTTO +
							sizeof(tdstOnlyFrame)	* (unsigned long) (p_stFileA3dAnimationGENERAL->uwEndFrame - p_stFileA3dAnimationGENERAL->uwStartFrame) +
							sizeof(tdstChannel)		* (unsigned long) p_stFileA3dAnimationGENERAL->uwNumberOfChannels +
							sizeof(tdstFrame)		* (unsigned long) p_stFileA3dAnimationGENERAL->uwNumberOfSavedFrames *
													  (unsigned long) p_stFileA3dAnimationGENERAL->uwNumberOfChannels +
							sizeof(tdstFrameKF)		* (unsigned long) (p_stFileA3dAnimationGENERAL->uwEndFrame - p_stFileA3dAnimationGENERAL->uwStartFrame) *
													  (unsigned long) p_stFileA3dAnimationGENERAL->uwNumberOfChannels;
		if	( ((ulSizeOfAnim) & 0x0002) != 0x0000 )
			ulSizeOfAnim+=	2;
		ulSizeOfAnim+=		sizeof(tdstKeyFrame)	* (unsigned long) p_stFileA3dAnimationGENERAL->uwNumberOfKeyFrames +
							sizeof(tdstEvent)		* (unsigned long) p_stFileA3dAnimationGENERAL->uwNumberOfEvents;
 
		/* alignment*/
/*		while	( ((ulSizeOfAnim) % 4) != 0 )
			ulSizeOfAnim++;
		ulSizeOfAnim+=		sizeof(tdstMorphData)	* (unsigned long) p_stFileA3dAnimationGENERAL->uwNumberOfMorphData; /*AR9804*/
 
/*#ifdef ANIM_DEBUG
/*		if	(ulSizeOfAnim > MaxRAMSizeOfAnim)
		{
			osSyncPrintf("fn_v_InitCache (ulCnt1= %d) : ulSizeOfAnim (%d) > %d\n", ulCnt1, ulSizeOfAnim, MaxRAMSizeOfAnim);
			osSyncPrintf("   uwNumberOfVectors    = %4d\n", p_stFileA3dAnimationGENERAL->uwNumberOfVectors);
			osSyncPrintf("   uwNumberOfQuaternions= %4d\n", p_stFileA3dAnimationGENERAL->uwNumberOfQuaternions);
			osSyncPrintf("   uwNumberOfHierarchies= %4d\n", p_stFileA3dAnimationGENERAL->uwNumberOfHierarchies);
			osSyncPrintf("   uwNumberOfNTTO       = %4d\n", p_stFileA3dAnimationGENERAL->uwNumberOfSavedNTTO);
			osSyncPrintf("   uwNumberOfOnlyFrames = %4d\n", (p_stFileA3dAnimationGENERAL->uwEndFrame - p_stFileA3dAnimationGENERAL->uwStartFrame));
			osSyncPrintf("   uwNumberOfChannels   = %4d\n", p_stFileA3dAnimationGENERAL->uwNumberOfChannels);
			osSyncPrintf("   uwNumberOfSavedFrames= %4d\n", p_stFileA3dAnimationGENERAL->uwNumberOfSavedFrames);
			osSyncPrintf("   uwNumberOfKeyFrames  = %4d\n", p_stFileA3dAnimationGENERAL->uwNumberOfKeyFrames);
			osSyncPrintf("   uwNumberOfEvents     = %4d\n", p_stFileA3dAnimationGENERAL->uwNumberOfEvents);
			osSyncPrintf("   uwNumberOfMorphData  = %4d\n", p_stFileA3dAnimationGENERAL->uwNumberOfMorphData);
			osSyncPrintf("   uwStartFrame         = %4d\n", p_stFileA3dAnimationGENERAL->uwStartFrame);
			osSyncPrintf("   uwEndFrame           = %4d\n", p_stFileA3dAnimationGENERAL->uwEndFrame);
			
			ASM_BREAK;
		}
#endif /*ANIM_DEBUG*/
 
	/* ANTIBUG -------------------------------------------------*/

		// AR9904 : Optimisation. Read the a3dheader from the rom
		LDR_fn_vLoadFromROM(_a3dheaderSegmentRomStart,_a3dheaderSegmentRomStart+ulNbIntAnims*sizeof(tdstA3dHeader),(char *)p_stA3dHeaders,MSG_BLOCK);
		for	( ulCnt1=0 ; ulCnt1<ulNbIntAnims ; ulCnt1++ )
		{
			unsigned long ulSizeOfAnim;
 
			ulSizeOfAnim=(unsigned long)p_stA3dHeaders[ulCnt1].uwCacheList;
#ifdef ANIM_DEBUG
			if	(ulSizeOfAnim > MaxRAMSizeOfAnim)
			{
				osSyncPrintf("Size for %d =%d\n",ulCnt1,ulSizeOfAnim);
				ASM_BREAK;
			}
#endif /*ANIM_DEBUG*/
		
		if	( (ulSizeOfAnim & 0x03FF) == 0 )				/* mod 1024*/
				ulSizeOfAnim=	(ulSizeOfAnim >> 10) - 1;	/* div 1024 - 1*/
			else
				ulSizeOfAnim=	(ulSizeOfAnim >> 10);		/* div 1024*/
 
		p_stA3dHeaders[ulCnt1].uwCacheList=			ax_uwSizeToList[ulSizeOfAnim];
	}
//	}
 
#ifdef	A3X_CUT
	LDR_fn_vLoadFromROM(	_cuttableSegmentRomStart,
							_cuttableSegmentRomEnd,
							(char *) p_stCuttedAnim,
							MSG_BLOCK	);
#endif
#ifndef FORCE_REAL_TIME_LOAD
	}
#endif
}
 
#endif
 
/* ***************************************************************************************************/
void	fn_v_UpdateCache(	unsigned short	_uwNumOfA3dGENERAL,
							unsigned long	_ulFrameNumber )
{
#ifdef	A3X_CacheIsUsed
	register unsigned short	uwOffset, uwNumOfCacheList, uwFirstOfCacheList;
 
#ifdef	A3X_N64
#ifdef ANIM_DEBUG
	if	( _uwNumOfA3dGENERAL >= ulNbIntAnims )
	{
		osSyncPrintf("fn_v_UpdateCache : _uwNumOfA3dGENERAL trop grand\n");
		osSyncPrintf("_uwNumOfA3dGENERAL = %d\n",_uwNumOfA3dGENERAL);
		ASM_BREAK;
	}
#endif /*ANIM_DEBUG*/
#endif
 
	uwNumOfCacheList=	p_stA3dHeaders[ _uwNumOfA3dGENERAL ].uwCacheList;		/* Number of Cache list (static value !)*/
	uwOffset=			p_stA3dHeaders[ _uwNumOfA3dGENERAL ].uwNumOfCacheEntry;	/* NumOfCacheEntry*/
	uwFirstOfCacheList=	ax_uwCacheList[ uwNumOfCacheList ];						/* First element of the cache list*/
 
	p_stCacheLine[ uwOffset ].slCacheValue=	_ulFrameNumber;						/* ulFrameNumber*/
 
	if	( uwOffset != uwFirstOfCacheList )
	{
		while	( ((signed long) _ulFrameNumber > p_stCacheLine[ p_stCacheLine[uwOffset].uwPrev ].slCacheValue) &&
				  (p_stCacheLine[uwOffset].uwNext != uwFirstOfCacheList) )
		{	register unsigned short	uwFirst, uwSecond, uwQuat;					/* And uwOffset (as third)*/
 
			uwSecond=	p_stCacheLine[uwOffset].uwPrev;
			uwFirst=	p_stCacheLine[uwSecond].uwPrev;
			uwQuat=		p_stCacheLine[uwOffset].uwNext;
			/* And now, we have uwFirst, uwOffset (as second) and uwSecond (as third)*/
			p_stCacheLine[uwFirst].uwNext=	uwOffset;
			p_stCacheLine[uwSecond].uwPrev=	uwOffset;
			p_stCacheLine[uwSecond].uwNext=	uwQuat;
			p_stCacheLine[uwOffset].uwPrev=	uwFirst;
			p_stCacheLine[uwOffset].uwNext=	uwSecond;
			p_stCacheLine[uwQuat].uwPrev=	uwSecond;
		}
 
		/* Change first element of CacheList*/
		if	(p_stCacheLine[uwOffset].uwNext == uwFirstOfCacheList)		/* If next element is the old first element*/
			ax_uwCacheList[ uwNumOfCacheList ]=	uwOffset;
	}
#endif
}
 
 
 
/* ***************************************************************************************************/
tdstA3dGENERAL	*fn_p_GetA3dGENERAL(	unsigned short	_uwNumOfA3dGENERAL,
										unsigned long	_ulFrameNumber )
{
#ifdef	A3X_N64
#ifndef FORCE_REAL_TIME_LOAD
	if(g_bRealTimeAnimationLoad)
	{
#endif
#ifdef ANIM_DEBUG
		if	( _uwNumOfA3dGENERAL >= ulNbIntAnims )
		{
			osSyncPrintf("fn_p_GetA3dGENERAL : _uwNumOfA3dGENERAL trop grand\n");
			osSyncPrintf("_uwNumOfA3dGENERAL = %d\n",_uwNumOfA3dGENERAL);
			ASM_BREAK;
		}
#endif /*ANIM_DEBUG*/
	
		_ulFrameNumber=g_stEngineStructure.stEngineTimer.ulTrameNumber; /*because frame number should be called trame number !*/
 
		if	( p_stA3dHeaders[_uwNumOfA3dGENERAL].uwNumOfCacheEntry == SEB_Invalid )
		{	/* Animation is non loaded*/
			register unsigned short	uwOffset, uwOldestA3dHeader, uwNumOfCacheList;
			
			/* Invalidate oldest cached A3dHeader*/
			uwNumOfCacheList=	p_stA3dHeaders[ _uwNumOfA3dGENERAL ].uwCacheList;		/* Number of Cache list (static value !)*/
			uwOffset=			ax_uwCacheList[ uwNumOfCacheList ];						/* First element of the cache list*/
			uwOffset=			p_stCacheLine[ uwOffset ].uwPrev;						/* Last element of the cache list*/
			uwOldestA3dHeader=	p_stCacheLine[ uwOffset ].uwNumOfA3dHeader;
			if	( uwOldestA3dHeader != SEB_Invalid )									/* Animation is loaded ???*/
			{
				p_stA3dHeaders[uwOldestA3dHeader].uwNumOfCacheEntry=	SEB_Invalid;	/* Yes -> unload animation*/
#ifdef ANIM_DEBUG
				if(p_stCacheLine[uwOffset].slCacheValue==_ulFrameNumber)
					osSyncPrintf("Saturation cache %d\n",uwNumOfCacheList);
#endif /*ANIM_DEBUG*/
			}
			
			/* Update cache values*/
			p_stA3dHeaders[_uwNumOfA3dGENERAL].uwNumOfCacheEntry=	uwOffset;			/* New Element*/
			p_stCacheLine[uwOffset].uwNumOfA3dHeader=				_uwNumOfA3dGENERAL;	/* Change uwNumOfA3dHeader*/
			p_stCacheLine[uwOffset].slCacheValue=					(signed long) _ulFrameNumber;	/* Update slCacheValue*/
			/*p_stCacheLine[uwOffset].uwNumOfMemBloc				(static value !)*/
			/*p_stCacheLine[uwOffset].uwNext						(is not changed)*/
			/*p_stCacheLine[uwOffset].uwPrev						(is not changed)*/
			ax_uwCacheList[uwNumOfCacheList]=						uwOffset;			/* Update first position of the cache list*/
			
			/* Load animation in p_cMemBlocs*/
/*			osSyncPrintf("fn_p_GetA3dGENERAL : chargement animation #%d -> cache %d\n", _uwNumOfA3dGENERAL,p_stA3dHeaders[_uwNumOfA3dGENERAL].uwNumOfCacheEntry);*/
			fn_v_LoadCachedAnimV6(	&p_cMemBlocs[ ((unsigned long) p_stCacheLine[uwOffset].uwNumOfMemBloc) << 10 ],
				fn_p_ReadAnimFromROM(_uwNumOfA3dGENERAL),ax_uwCacheListSize[p_stA3dHeaders[_uwNumOfA3dGENERAL].uwCacheList]*1024);
 
#ifdef ANIM_DEBUG
			if	( ((unsigned long)&p_stMorphData[p_stA3dGENERAL->uwNumberOfMorphData] - (unsigned long)p_stA3dGENERAL) > MaxRAMSizeOfAnim )
			{
				/* ANTIBUG -------------------------------------------------*/
				osSyncPrintf("Anim %d too big !!!\n",_uwNumOfA3dGENERAL);
				osSyncPrintf("fn_v_LoadCachedAnimV6 (%d > %d)\n", ((unsigned long)&p_stEvents[p_stA3dGENERAL->uwNumberOfEvents] - (unsigned long)p_stA3dGENERAL), MaxRAMSizeOfAnim);
				osSyncPrintf("   uwNumberOfFrames     = %4d\n", p_stA3dGENERAL->uwNumberOfFrames);
				osSyncPrintf("   uwNumberOfVectors    = %4d\n", p_stA3dGENERAL->uwNumberOfVectors);
				osSyncPrintf("   uwNumberOfQuaternions= %4d\n", p_stA3dGENERAL->uwNumberOfQuaternions);
				osSyncPrintf("   uwNumberOfHierarchies= %4d\n", p_stA3dGENERAL->uwNumberOfHierarchies);
				osSyncPrintf("   uwNumberOfNTTO       = %4d\n", p_stA3dGENERAL->uwNumberOfNTTO);
				osSyncPrintf("   uwNumberOfOnlyFrames = %4d\n", (p_stA3dGENERAL->uwEndFrame - p_stA3dGENERAL->uwStartFrame));
				osSyncPrintf("   uwNumberOfChannels   = %4d\n", p_stA3dGENERAL->uwNumberOfChannels);
				osSyncPrintf("   uwNumberOfSavedFrames= %4d\n", p_stA3dGENERAL->uwNumberOfSavedFrames);
				osSyncPrintf("   uwNumberOfKeyFrames  = %4d\n", p_stA3dGENERAL->uwNumberOfKeyFrames);
				osSyncPrintf("   uwNumberOfEvents     = %4d\n", p_stA3dGENERAL->uwNumberOfEvents);
				osSyncPrintf("   uwNumberOfMorphData  = %4d\n", p_stA3dGENERAL->uwNumberOfMorphData);
				osSyncPrintf("   uwStartFrame         = %4d\n", p_stA3dGENERAL->uwStartFrame);
				osSyncPrintf("   uwEndFrame           = %4d\n", p_stA3dGENERAL->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*/
 
		}
		else
		{
			/* Anim is already loaded. We must update the global pointers.*/
			fn_v_UpdateCache( _uwNumOfA3dGENERAL, _ulFrameNumber );
			p_stA3dGENERAL=			(tdstA3dGENERAL *)		&p_cMemBlocs[ ((unsigned long) p_stCacheLine[ p_stA3dHeaders[_uwNumOfA3dGENERAL].uwNumOfCacheEntry ].uwNumOfMemBloc) << 10 ];
			p_a3_xVectors=			(tdxVector3 *)			&p_stA3dGENERAL[ 1 ];
			p_a4_xQuaternions=		(tdxSShortQuater4 *)	&p_a3_xVectors[ p_stA3dGENERAL->uwNumberOfVectors ];
			p_stHierarchies=		(tdstHierarchy *)		&p_a4_xQuaternions[ p_stA3dGENERAL->uwNumberOfQuaternions ];
			p_stNTTO=				(tdstNTTO *)			&p_stHierarchies[ p_stA3dGENERAL->uwNumberOfHierarchies ];
			p_stOnlyFrames=			(tdstOnlyFrame *)		&p_stNTTO[ p_stA3dGENERAL->uwNumberOfNTTO ];
			
			p_stChannels=			(tdstChannel *)			&p_stOnlyFrames[ (p_stA3dGENERAL->uwEndFrame - p_stA3dGENERAL->uwStartFrame) ];
			while	( (((unsigned long) p_stChannels) %4) != 0 )
				p_stChannels=	(tdstChannel *) (((char *) p_stChannels) + 1);
 
			p_stFrames=				(tdstFrame *)			&p_stChannels[ p_stA3dGENERAL->uwNumberOfChannels ];
			p_stFramesKF=			(tdstFrameKF *)			&p_stFrames[ p_stA3dGENERAL->uwNumberOfSavedFrames * p_stA3dGENERAL->uwNumberOfChannels ];
			/*	p_stKeyFrames=			(tdstKeyFrame *)		&p_stFramesKF[ p_stA3dGENERAL->uwNumberOfFrames * p_stA3dGENERAL->uwNumberOfChannels ];*/
			p_stKeyFrames=			(tdstKeyFrame *)		&p_stFramesKF[ (p_stA3dGENERAL->uwEndFrame - p_stA3dGENERAL->uwStartFrame) * p_stA3dGENERAL->uwNumberOfChannels ];
			/* Alignment*/
			if	( (((unsigned long) p_stKeyFrames) & 0x0002) != 0x0000 )
				p_stKeyFrames=	(tdstKeyFrame *) (((char *) p_stKeyFrames) + 2);
			
			p_stEvents=				(tdstEvent *)			&p_stKeyFrames[ p_stA3dGENERAL->uwNumberOfKeyFrames ];
			/* due to alignment*/
			while	( (((unsigned long) p_stEvents) %4) != 0 )
				p_stEvents=	(tdstEvent *) (((char *) p_stEvents) + 1);
 
			p_stMorphData=			(tdstMorphData *)		&p_stEvents[ p_stA3dGENERAL->uwNumberOfEvents ];
			
#ifdef ANIM_DEBUG
			/* ANTIBUG -------------------------------------------------*/
			if	( ((unsigned long)&p_stMorphData[p_stA3dGENERAL->uwNumberOfMorphData] - (unsigned long)p_stA3dGENERAL) > MaxRAMSizeOfAnim )
			{
				osSyncPrintf("Anim %d too big !!!\n",_uwNumOfA3dGENERAL);				
				osSyncPrintf("fn_v_LoadCachedAnimV6 (%d > %d)\n", ((unsigned long)&p_stEvents[p_stA3dGENERAL->uwNumberOfEvents] - (unsigned long)p_stA3dGENERAL), MaxRAMSizeOfAnim);
				osSyncPrintf("   uwNumberOfFrames     = %4d\n", p_stA3dGENERAL->uwNumberOfFrames);
				osSyncPrintf("   uwNumberOfVectors    = %4d\n", p_stA3dGENERAL->uwNumberOfVectors);
				osSyncPrintf("   uwNumberOfQuaternions= %4d\n", p_stA3dGENERAL->uwNumberOfQuaternions);
				osSyncPrintf("   uwNumberOfHierarchies= %4d\n", p_stA3dGENERAL->uwNumberOfHierarchies);
				osSyncPrintf("   uwNumberOfNTTO       = %4d\n", p_stA3dGENERAL->uwNumberOfNTTO);
				osSyncPrintf("   uwNumberOfOnlyFrames = %4d\n", (p_stA3dGENERAL->uwEndFrame - p_stA3dGENERAL->uwStartFrame));
				osSyncPrintf("   uwNumberOfChannels   = %4d\n", p_stA3dGENERAL->uwNumberOfChannels);
				osSyncPrintf("   uwNumberOfSavedFrames= %4d\n", p_stA3dGENERAL->uwNumberOfSavedFrames);
				osSyncPrintf("   uwNumberOfKeyFrames  = %4d\n", p_stA3dGENERAL->uwNumberOfKeyFrames);
				osSyncPrintf("   uwNumberOfEvents     = %4d\n", p_stA3dGENERAL->uwNumberOfEvents);
				osSyncPrintf("   uwNumberOfMorphData  = %4d\n", p_stA3dGENERAL->uwNumberOfMorphData);
				osSyncPrintf("   uwStartFrame         = %4d\n", p_stA3dGENERAL->uwStartFrame);
				osSyncPrintf("   uwEndFrame           = %4d\n", p_stA3dGENERAL->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;;
			}
			/* ANTIBUG -------------------------------------------------*/
#endif /*ANIM_DEBUG*/
		}
		return	p_stA3dGENERAL;
#ifndef FORCE_REAL_TIME_LOAD
	}
	else
#endif
#endif /*A3X_N64*/
#ifndef FORCE_REAL_TIME_LOAD
		return	&p_stA3dGENERAL[ _uwNumOfA3dGENERAL ];
#endif	
}
 
 
#ifdef U64
void fn_vInvalidateAnimCache(void)
{
	unsigned long i,ulNbIntAnims;
	char* p_cBigMalloc;
	
	/* Read number of animations*/
	p_cBigMalloc=(char *) fn_pvAllocTmp( 4 , 16 );
	LDR_fn_vLoadFromROM(	( g_p_cROMAnimBlocStart ),
							( g_p_cROMAnimBlocStart + 1*sizeof(unsigned long) ),
							(char *) p_cBigMalloc,
							MSG_BLOCK	);
	ulNbIntAnims=		*((unsigned long *) &p_cBigMalloc[0]);	
	fn_vFreeRomTmp( (void *)p_cBigMalloc );	
 
	/* Mark all cache entry invalid*/
	for(i=0;i<ulNbIntAnims;++i)
		p_stA3dHeaders[i].uwNumOfCacheEntry=SEB_Invalid;
}
#endif
 
/* ***************************************************************************************************/
/*tdstOutputCacheLine	*fn_p_GetOutputCacheEntry(	unsigned short	_uwNumOfA3dGENERAL,
												unsigned long	_ulFrame,
												void			*_p_vSuperObject )
{	unsigned short	uwCnt;
	unsigned long	ulMax;
 
	if	(ulLastEngineFrame != _ulFrame)
	{
#ifndef MESSAGES_OFF
//		M_PrintfN64_((ON"Changement frame moteur (%d)\n", _ulFrame ));
#endif	// MESSAGES_OFF
 
		M_v_ResetOneStack( eStackFrame3d );
		M_v_ResetOneStack( eStackElement3d );
		ulLastEngineFrame=	_ulFrame;
	}
 
	ulMax = fn_ul_GetStackPos(eStackFrame3d);
	for	( uwCnt=0 ; uwCnt<ulMax ; uwCnt++ )
		if	( _p_vSuperObject == ax_stOutputCacheLine[uwCnt].p_vSuperObject )
			return	&ax_stOutputCacheLine[uwCnt];
 
	ax_stOutputCacheLine[ulMax].p_vSuperObject=		_p_vSuperObject;
	ax_stOutputCacheLine[ulMax].p_stAnim3d=			(void *) 0xFFFFFFFF;
	ax_stOutputCacheLine[ulMax].lNumOfLastFrame=		-1;
#ifdef	A3X_CUT
	ax_stOutputCacheLine[ulMax].p_stFrame3d=			&p_stFrame3d[ fn_ul_AllocateOnStack( eStackFrame3d, 1 ) ];
	ax_stOutputCacheLine[ulMax].p_stElement3d=
		&p_stElement3d[ fn_ul_AllocateOnStack( eStackElement3d, p_stCuttedAnim[_uwNumOfA3dGENERAL].uwMaxNumberOfElements ) ];
#else
	ax_stOutputCacheLine[ulMax].p_stFrame3d=			&p_stFrame3d[ fn_ul_AllocateOnStack( eStackFrame3d, 1 ) ];
	ax_stOutputCacheLine[ulMax].p_stElement3d=		&p_stElement3d[ fn_ul_AllocateOnStack(eStackElement3d,fn_p_GetA3dGENERAL(_uwNumOfA3dGENERAL,_ulFrame)->uwNumberOfChannels) ];
#endif
	ax_stOutputCacheLine[ulMax].p_stFrame3d->p_stArrayOfElts3d = ax_stOutputCacheLine[ulMax].p_stElement3d;
 
 
	// ANTIBUG -------------------------------------------------
	if	( (fn_ul_GetStackPos(eStackFrame3d) > uwMaxInTabFrame3d) || (fn_ul_GetStackPos(eStackElement3d) > uwMaxInTabElement3d) )
	{
		M_v_ResetOneStack( eStackFrame3d );
		M_v_ResetOneStack( eStackElement3d );
#ifdef	A3X_CUT
		ax_stOutputCacheLine[ulMax].p_stFrame3d=&p_stFrame3d[ fn_ul_AllocateOnStack( eStackFrame3d, 1 ) ];
		ax_stOutputCacheLine[ulMax].p_stElement3d=
			&p_stElement3d[ fn_ul_AllocateOnStack( eStackElement3d, p_stCuttedAnim[_uwNumOfA3dGENERAL].uwMaxNumberOfElements ) ];
#else
		ax_stOutputCacheLine[ulMax].p_stFrame3d=&p_stFrame3d[ fn_ul_AllocateOnStack( eStackFrame3d, 1 ) ];
		ax_stOutputCacheLine[ulMax].p_stElement3d=&p_stElement3d[ fn_ul_AllocateOnStack( eStackElement3d,fn_p_GetA3dGENERAL(_uwNumOfA3dGENERAL,_ulFrame)->uwNumberOfChannels) ];
#endif
#ifdef	A3X_N64
#ifndef MESSAGES_OFF
		M_PrintfN64(("fn_uw_GetOutputCacheEntry : saturation cache sortie\n"));
	//	asm("break 0xFF");
#endif	// MESSAGES_OFF
#endif
		return	&ax_stOutputCacheLine[0];
	}
 
	if	( (fn_ul_GetStackPos(eStackFrame3d) > uwMaxInStackFrame3d) || (fn_ul_GetStackPos(eStackElement3d) > uwMaxInStackElement3d) )
	{	if	(fn_ul_GetStackPos(eStackFrame3d) > uwMaxInStackFrame3d)
			uwMaxInStackFrame3d = (unsigned short)fn_ul_GetStackPos(eStackFrame3d);
		
		if	(fn_ul_GetStackPos(eStackElement3d) > uwMaxInStackElement3d)
			uwMaxInStackElement3d = (unsigned short)fn_ul_GetStackPos(eStackElement3d);
#ifdef	A3X_N64
#ifndef MESSAGES_OFF
//		M_PrintfN64((	"uwMaxInStackFrame3d= %d, uwMaxInStackElement3d= %d\n",
//							uwMaxInStackFrame3d, uwMaxInStackElement3d ));
#endif	// MESSAGES_OFF
#endif
	}
	// ANTIBUG -------------------------------------------------
 
	return	&ax_stOutputCacheLine[ulMax];
}*/
 
 
/* ***************************************************************************************************/
#undef	A3X_CACH_C
