////////////////////////////////////////////////////////////////////////////
//
//  Crytek Engine Source File.
//  Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
//  File name:   crtdebug.cpp
//  Version:     v1.00
//  Created:     16/1/2003 by Timur.
//  Compilers:   Visual Studio.NET
//  Description: 
// -------------------------------------------------------------------------
//  History:
//
////////////////////////////////////////////////////////////////////////////

#include "StdAfx.h"

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

//#ifdef _CRTDBG_MAP_ALLOC
#ifdef CRTDBG_MAP_ALLOC
#pragma pack (push,1)
#define nNoMansLandSize 4
typedef struct MyCrtMemBlockHeader
{
	struct MyCrtMemBlockHeader * pBlockHeaderNext;
	struct MyCrtMemBlockHeader * pBlockHeaderPrev;
	char *                      szFileName;
	int                         nLine;
	size_t                      nDataSize;
	int                         nBlockUse;
	long                        lRequest;
	unsigned char               gap[nNoMansLandSize];
	/* followed by:
	*  unsigned char           data[nDataSize];
	*  unsigned char           anotherGap[nNoMansLandSize];
	*/
} MyCrtMemBlockHeader;
#pragma pack (pop)

#define pbData(pblock) ((unsigned char *)((MyCrtMemBlockHeader *)pblock + 1))
#define pHdr(pbData) (((MyCrtMemBlockHeader *)pbData)-1)


void crtdebug( const char *s,... )
{
	char str[32768];
	va_list arg_ptr;
	va_start( arg_ptr,s );
	vsprintf( str,s,arg_ptr );
	va_end( arg_ptr );
	
	FILE *l = fopen( "crtdump.txt","a+t" );
	if (l) {
		fprintf( l,"%s",str );
		fclose( l );
	}
}

int crtAllocHook(int nAllocType, void *pvData, 
      size_t nSize, int nBlockUse, long lRequest, 
      const unsigned char * szFileName, int nLine )
{
	if (nBlockUse == _CRT_BLOCK)
		return( TRUE );
	
	static int total_cnt = 0;
	static int total_mem = 0;
	if (nAllocType == _HOOK_ALLOC)
	{
		//total_mem += nSize;
		//total_cnt++;
		//_CrtMemState mem_state;
		//_CrtMemCheckpoint( &mem_state );
		//total_cnt = mem_state.lCounts[_NORMAL_BLOCK];
		//total_mem = mem_state.lTotalCount;
		if ((total_cnt&0xF) == 0) 
		{
			//_CrtCheckMemory();
		}

		total_cnt++;
		total_mem += nSize;

		//crtdebug( "<CRT> Alloc %d,size=%d,in: %s %d (total size=%d,num=%d)\n",lRequest,nSize,szFileName,nLine,total_mem,total_cnt );
		crtdebug( "Size=%d,	[Total=%d,N=%d]	[%s:%d]\n",nSize,total_mem,total_cnt,szFileName,nLine );
	} else if (nAllocType == _HOOK_FREE) {
		MyCrtMemBlockHeader *pHead;
		pHead = pHdr(pvData);
		
		total_cnt--;
		total_mem -= pHead->nDataSize;

		crtdebug( "Size=%d,	[Total=%d,N=%d]	[%s:%d]\n",pHead->nDataSize,total_mem,total_cnt,pHead->szFileName,pHead->nLine );
		//crtdebug( "<CRT> Free size=%d,in: %s %d (total size=%d,num=%d)\n",pHead->nDataSize,pHead->szFileName,pHead->nLine,total_mem,total_cnt );
		//total_mem -= nSize;
		//total_cnt--;
	}
	return TRUE;
}

int crtReportHook(int nRptType, char *szMsg, int *retVal)
{
	static int gl_num_asserts = 0;
	if (gl_num_asserts != 0) return TRUE;
	gl_num_asserts++;
	switch (nRptType) {
		case _CRT_WARN:
			crtdebug( "<CRT WARNING> %s\n",szMsg );
			break;
		case _CRT_ERROR:
			crtdebug( "<CRT ERROR> %s\n",szMsg );
			break;
		case _CRT_ASSERT:
			crtdebug( "<CRT ASSERT> %s\n",szMsg );
			break;
	}
	gl_num_asserts--;
	return TRUE;
}

void InitCrt() {
	FILE *l = fopen( "crtdump.txt","w" );
	if (l) fclose(l);
	
   //_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_DEBUG );
   //_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );
   //_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_DEBUG );

	_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_WNDW );
	_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_WNDW );
	_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_WNDW );

	//_CrtSetDbgFlag( _CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_CHECK_CRT_DF|_CRTDBG_LEAK_CHECK_DF|_CRTDBG_DELAY_FREE_MEM_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) );
	//_CrtSetDbgFlag( _CRTDBG_CHECK_CRT_DF|_CRTDBG_LEAK_CHECK_DF/*|_CRTDBG_DELAY_FREE_MEM_DF*/ | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) );
	int flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
	flags &= ~_CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_CRT_DF;

	_CrtSetDbgFlag( flags );

	_CrtSetAllocHook ( crtAllocHook );
	_CrtSetReportHook( crtReportHook );

}

void DoneCrt() {
	//_CrtCheckMemory();
	//_CrtDumpMemoryLeaks();
}

// Autoinit CRT.
//struct __autoinit_crt { __autoinit_crt() { InitCrt(); }; ~__autoinit_crt() { DoneCrt(); } } __autoinit_crt_var;
#endif


//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////