#include "pch.hpp"
//===========================================================================//
// File:	 Analyze.cpp													 //
// Project:  GameOS					                                         //
// Contents: Lab Rat type analyzer											 //
//---------------------------------------------------------------------------//
// Date      Who    Modification                                             //
// 11/02/99  AG		Created													 //
//---------------------------------------------------------------------------//
// Copyright (C) 1999 Microsoft Corp.						                 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//
#include "MemoryManager.hpp"
#include "Profiler.hpp"
#include "Debugger.hpp"



bool			gAnalyzeEnable=0;
HGOSHEAP		AnalyzeHeap;
AnalyzeStat*	pAnalyze;
AnalyzeData*	pAnalyzeDataStart;
AnalyzeData*	pAnalyzeData;
AnalyzeData*	pAnalyzeDataEnd;



//
// Internal analyze variables
//
DWORD AnalyzeAllRenderers;
DWORD AnalyzeGameRenderers;
DWORD AnalyzeGameLogic;
DWORD AnalyzeControls;
DWORD AnalyzeWindowsMessages;
DWORD AnalyzeScriptExecution;
DWORD AnalyzeScriptRenderers;
DWORD AnalyzeBltFlip;
DWORD AnalyzeDebugger;
DWORD AnalyzeEndScene;
DWORD AnalyzeFrameNumber;

//
// Startup analyze session
//
void InitAnalyze()
{
	pAnalyze=0;
	pAnalyzeData=0;
	AnalyzeHeap=gos_CreateMemoryHeap( "Analyze", 0, ParentGameOSHeap );
	pAnalyzeDataStart=0;
//
// Setup GameOS default analyze traces
//
	AnalyzeFrameNumber=gosAddAnalyzeStatistic( "Frame Number", gos_TypeDWORD );
	AnalyzeAllRenderers=gosAddAnalyzeStatistic( "All Renderers", gos_TypeRoutine );
	AnalyzeGameRenderers=gosAddAnalyzeStatistic( "Game Renderers", gos_TypeRoutine );
	AnalyzeGameLogic=gosAddAnalyzeStatistic( "Game Logic", gos_TypeRoutine );
	AnalyzeControls=gosAddAnalyzeStatistic( "Reading Controls", gos_TypeRoutine );
	AnalyzeWindowsMessages=gosAddAnalyzeStatistic( "Windows Messages", gos_TypeRoutine );
	AnalyzeScriptExecution=gosAddAnalyzeStatistic( "Script Execution", gos_TypeRoutine );
	AnalyzeScriptRenderers=gosAddAnalyzeStatistic( "Script Renderers", gos_TypeRoutine );
	AnalyzeBltFlip=gosAddAnalyzeStatistic( "Blt/Flip time", gos_TypeRoutine );
	AnalyzeDebugger=gosAddAnalyzeStatistic( "Debugger", gos_TypeRoutine );
	AnalyzeEndScene=gosAddAnalyzeStatistic( "End Scene", gos_TypeRoutine );

// On by default.
//	FlipAnalyze=1;

}

//
// Close down analyze session
//
void DestroyAnalyze()
{
	while( pAnalyze )
	{
		AnalyzeStat* pTemp=pAnalyze->pNext;
		gos_Free( pAnalyze );
		pAnalyze=pTemp;
	}
	while( pAnalyzeDataStart )
	{
		AnalyzeData* pThis=(AnalyzeData*)pAnalyzeDataStart[8191].Value;
		gos_Free( pAnalyzeDataStart );
		pAnalyzeDataStart=pThis;
	}
	if( TraceBuffer )
	{
		gos_Free( TraceBuffer );
		TraceBuffer=0;
	}
	if( LineBuffer )
	{
		gos_Free( LineBuffer );
		LineBuffer=0;
	}
	if( AnalyzeHeap )
	{
		gos_DestroyMemoryHeap( AnalyzeHeap, true );
		AnalyzeHeap = 0;
	}
}


//
// Called when analyze is started or stopped
//
void RestartAnalyze()
{
	if( gAnalyzeEnable )
	{
		pAnalyzeDataStart=pAnalyzeData=(AnalyzeData*)gos_Malloc( 8192*sizeof(AnalyzeData), AnalyzeHeap );
		pAnalyzeDataEnd=pAnalyzeData+8191;
		pAnalyzeData[8191].Stat=(AnalyzeStat*)TypeEndOfBlock;
		pAnalyzeData[8191].Value=0;
	}
	else
	{
		while( pAnalyzeDataStart )
		{
			AnalyzeData* pThis=(AnalyzeData*)pAnalyzeDataStart[8191].Value;
			gos_Free( pAnalyzeDataStart );
			pAnalyzeDataStart=pThis;
		}
		pAnalyzeData=0;
	}
}




//
// Add a new statistic to analyze
//
DWORD __stdcall gosAddAnalyzeStatistic( char* Name, gosAnalyzeType Type )
{
//
//
//
	AnalyzeStat* pTemp=(AnalyzeStat*)gos_Malloc( sizeof(AnalyzeStat)+strlen(Name), AnalyzeHeap );
	memcpy( pTemp->Name, Name, strlen(Name)+1 );
	pTemp->pNext=0;
	pTemp->Type=Type;
	pTemp->Magic=0xF22E44BA;
//
// Find last entry
//
	AnalyzeStat* pThis=pAnalyze;

	if( pThis )
	{
		while( pThis->pNext )
		{
			if( 0==stricmp( Name, pThis->Name ) )
			{
				STOP(( "Duplicated statistic '%s'",Name ));
			}
			pThis=pThis->pNext;
		}
		pThis->pNext=pTemp;
	}
	else
	{
		pAnalyze=pTemp;
	}

	return (DWORD)pTemp;
}








void __stdcall gosLabRatStart( DWORD Handle )
{
	if( !gAnalyzeEnable )
		return;
	pAnalyzeData->Stat=(AnalyzeStat*)Handle;
	pAnalyzeData->TimeStamp=GetCycles();
	pAnalyzeData->Value=TypeEnter;
	pAnalyzeData++;
	if( pAnalyzeData==pAnalyzeDataEnd )
	{
		pAnalyzeData->Value=(DWORD)gos_Malloc( 8192*sizeof(AnalyzeData), AnalyzeHeap );
		pAnalyzeData=(AnalyzeData*)pAnalyzeData->Value;
		pAnalyzeDataEnd=pAnalyzeData+8191;
		pAnalyzeDataEnd->Stat=(AnalyzeStat*)TypeEndOfBlock;
		pAnalyzeDataEnd->Value=0;
	}
}


void __stdcall gosLabRatEnd( DWORD Handle )
{
	if( !gAnalyzeEnable )
		return;
	pAnalyzeData->Stat=(AnalyzeStat*)Handle;
	pAnalyzeData->TimeStamp=GetCycles();
	pAnalyzeData->Value=TypeExit;
	pAnalyzeData++;
	if( pAnalyzeData==pAnalyzeDataEnd )
	{
		pAnalyzeData->Value=(DWORD)gos_Malloc( 8192*sizeof(AnalyzeData), AnalyzeHeap );
		pAnalyzeData=(AnalyzeData*)pAnalyzeData->Value;
		pAnalyzeDataEnd=pAnalyzeData+8191;
		pAnalyzeDataEnd->Stat=(AnalyzeStat*)TypeEndOfBlock;
		pAnalyzeDataEnd->Value=0;
	}
}


void __stdcall gosLabRatSet( DWORD Handle, DWORD Value )
{
	if( !gAnalyzeEnable )
		return;
	pAnalyzeData->Stat=(AnalyzeStat*)Handle;
	pAnalyzeData->TimeStamp=GetCycles();
	pAnalyzeData->Value=Value;
	pAnalyzeData++;
	if( pAnalyzeData==pAnalyzeDataEnd )
	{
		pAnalyzeData->Value=(DWORD)gos_Malloc( 8192*sizeof(AnalyzeData), AnalyzeHeap );
		pAnalyzeData=(AnalyzeData*)pAnalyzeData->Value;
		pAnalyzeDataEnd=pAnalyzeData+8191;
		pAnalyzeDataEnd->Stat=(AnalyzeStat*)TypeEndOfBlock;
		pAnalyzeDataEnd->Value=0;
	}
}


void __stdcall gosLabRatSet( DWORD Handle, float Value )
{
	if( !gAnalyzeEnable )
		return;
	pAnalyzeData->Stat=(AnalyzeStat*)Handle;
	pAnalyzeData->TimeStamp=GetCycles();
	pAnalyzeData->Value=*(DWORD*)&Value;
	pAnalyzeData++;
	if( pAnalyzeData==pAnalyzeDataEnd )
	{
		pAnalyzeData->Value=(DWORD)gos_Malloc( 8192*sizeof(AnalyzeData), AnalyzeHeap );
		pAnalyzeData=(AnalyzeData*)pAnalyzeData->Value;
		pAnalyzeDataEnd=pAnalyzeData+8191;
		pAnalyzeDataEnd->Stat=(AnalyzeStat*)TypeEndOfBlock;
		pAnalyzeDataEnd->Value=0;
	}

}






