#include "stypes.h"
#include "..\game\items.h"
#include "..\game\room.h"
#include "..\game\title.h"
#include "include.h"

/*** defines ***/
//#define LOG

/*** globals ***/
defglobal char malloc_buffer[MALLOC_SIZE];		// the main malloc area (big)
defglobal char* malloc_ptr;
defglobal int malloc_free;
defglobal int malloc_used;
defglobal int script_malloc_size;

#ifdef GAMEDEBUG
char* game_malloc_strings[]=
{
	"Temp Alloc",
	"Txtr Pages",
	"Mesh Ptrs",
	"Meshes",
	"Anims",
	"Change",
	"Ranges",
	"Commands",
	"Bones",
	"Frames",
	"Room Txtrs",
	"Room Infos",
	"Room Mesh",
	"Room Door",
	"Room Floor",
	"Room Lites",
	"SttMshInfs",
	"Floor Data",
	"ITEMS!!",
	"Cameras",
	"Sound FX",
	"Boxes",
	"Overlaps",
	"GroundZone",
	"FlyZone",
	"AniTxt Rngs",
	"Cine Frms",
	"LdDem Buf",
	"SvDem Buf",
	"Cine FX",
	"Mummy HdTn",
	"Xtra DR Stf",
	"FX_Array",
	"Creat.Data",
	"Creat.LOT",
	"Samp Infos",
	"Samples",
	"Samp Offs",
	"Rlg Ball Stf",
	"Skidoo Stuff",
	"LdPic Buf",
	"FMV Buf",
	"Poly Bufs",
	"O-Tables",
	"CLUTs",
	"Text Infos",
	"Spr Infos",
	"Script Dat",
	"NULL"
	};
int game_malloc_totals[256];
#endif

/*** macros ***/
#ifdef LOG
#define Log_(format,args...) DebugOut(format "\n" , ## args)
#else
#define Log_(args...)
#endif

/******************************************************************************
 *			Initialise Game Malloc stuff
 *****************************************************************************/
void	init_game_malloc( void )
{

#ifdef GAMEDEBUG
	int		i;

	for ( i=0;i<256;i++ )
		game_malloc_totals[i] = 0;
	game_malloc_totals[SCRIPT_DATA] = script_malloc_size;
#endif

	malloc_free = MALLOC_SIZE - script_malloc_size;
	malloc_used = script_malloc_size;
	malloc_ptr = malloc_buffer + script_malloc_size;

#ifdef GAMEDEBUG
	//S_MemSet(malloc_buffer,0x55,MALLOC_SIZE);
	jprintf("Game_Malloc Initialised -->%dK - %d bytes for script\n",MALLOC_SIZE/1024,script_malloc_size );
#endif
}

/*****************************************************************************
 *			Do Linear Incremental Buffer Memory Allocation
 ****************************************************************************/
char	*game_malloc( int size, int type )
{
	char	*ptr;

	size = (size+3) & 0xfffffffc;		// LongWord Align....
	if ( size<=malloc_free )
	{
#ifdef GAMEDEBUG
		game_malloc_totals[type] += size;
#endif
		ptr = malloc_ptr;
		malloc_free -= size;
		malloc_used += size;
		malloc_ptr += size;
//		printf("game_malloc(%d,%s) Free=%d\n", size, game_malloc_strings[type], malloc_free);
		return( ptr );
	}
#if defined(GAMEDEBUG) || defined(EZORAY)
//	printf("game_malloc(%d,%s) Free=%d\n", size, game_malloc_strings[type], malloc_free);
	printf("game_malloc() out of space!!\n");
#endif
	exit(0);
	return(NULL);
}

/***************************************************************************
 *			Free Space on Linear Incremental Buffer
 *				Use this With Extreme Care
 **************************************************************************/
void	game_free( int size, int type )
{
#ifdef GAMEDEBUG
	game_malloc_totals[type] -= size;
#endif

	malloc_ptr -= size;
	malloc_free += size;
	malloc_used -= size;

//	printf("game_free(%d,%s) Free=%d\n", size, game_malloc_strings[type], malloc_free);
}

/**************************************************************************
 *			Show Memory Totals for each type
 *************************************************************************/

void	show_game_malloc_totals( void )
{
#if defined(GAMEDEBUG) || defined (EZORAY)
	printf( "\n\n---->Total Memory Used %dK of %dK<----\n\n",(malloc_used+1023)/1024,(malloc_used+malloc_free)/1024);
#endif
}

#ifdef GAMEDEBUG
void	save_game_malloc_totals( char *fname )
{
	int		file;
	int		i;
	char	*ptr,*ptr2,*ptr3;
	char	buf[256];

#ifndef CD_LOAD

#ifdef EZORAY
	file = PCcreat0(fname,0);
	PCclose0(file);
	file = PCopen0(fname,1,0);
#else
	file = PCcreat(fname,0);
	PCclose(file);
	file = PCopen(fname,1,0);
#endif
	printf("FILE: %s FD:%d\n\r",fname,file);
	if (file<=0) return;
	printf("Writing...\n");
	sprintf(buf,"Level: '%s' '%s'\n\r",GF_Level_Names[CurrentLevel],GF_levelfilenames[CurrentLevel]);
	for ( i=0; i<256; i+=3 )
	{
		ptr = game_malloc_strings[i];
		if ( *ptr=='N' && *(ptr+1)=='U' &&
		     *(ptr+2)=='L' && *(ptr+3)=='L' )
				break;

		ptr2 = game_malloc_strings[i+1];
		if ( *ptr2=='N' && *(ptr2+1)=='U' &&
		     *(ptr2+2)=='L' && *(ptr2+3)=='L' )
				break;

		ptr3 = game_malloc_strings[i+2];
		if ( *ptr3=='N' && *(ptr3+1)=='U' &&
		     *(ptr3+2)=='L' && *(ptr3+3)=='L' )
				break;


		sprintf(buf, "%8d %-10s  %8d %-10s %8d %-10s\n\r",game_malloc_totals[i],ptr, game_malloc_totals[i+1],ptr2, game_malloc_totals[i+2],ptr3 );
#ifdef EZORAY
		PCwrite0(file,buf,strlen(buf));
#else
		PCwrite(file,buf,strlen(buf));
#endif
	}

	sprintf(buf, "---->Total Memory Used %dK of %dK<----\n\r",malloc_used/1024,(malloc_used+malloc_free)/1024);
#ifdef EZORAY
	PCwrite0(file,buf,strlen(buf));
	PCclose0(file);
#else
	PCwrite(file,buf,strlen(buf));
	PCclose(file);
#endif
	printf("Closed\n\n");
#endif

}
#endif



/******************************************************************************
 *			Machine specific MemCopy routine
 *****************************************************************************/
#ifndef USE_ASM
void	S_MemCpy( void *dest, void *src, int length )
{
	char	*csrc,*cdest;

	csrc = (char *)src;
	cdest = (char *)dest;
	for ( ;length>0;length-- )
		*(cdest++) = *(csrc++);
}

/******************************************************************************
 *			Machine specific MemCopy routine copies LONGS
 *****************************************************************************/
void	S_LongMemCpy( void *dest, void *src, int length )
{
	int		*csrc,*cdest;

	csrc = (int *)src;
	cdest = (int *)dest;
	for ( ;length>0;length-- )
		*(cdest++) = *(csrc++);
}

/******************************************************************************
 *			Machine Specific MemSet routine
 *****************************************************************************/
void	S_MemSet( void *dest, unsigned char value, int length )
{
	unsigned char *ptr;

	ptr = (unsigned char *)dest;
	for ( ;length>0;length-- )
		*(ptr++) = value;
}
#endif
