
///////////////////////////////////////////////////////////////////////////////
//
// File   : Asura_MemoryBank.cpp
// Author : Andy Tate
// Date   : 7-Feb-2006
//
// Copyright (C) 2006 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Include files...
////////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header...
#include "Core/Memory/Asura_MemoryBank.h"

// Asura independent header-files...
#include "Core/Asura_Maths.h"
#include "Core/Asura_String.h"
#if defined(ASURA_MEMORYBANK_ALLOW_LOGGING)
#include "Core/Asura_Timers.h"
#include "Debugging/Asura_Logfile.h"
#endif	// defined(ASURA_MEMORYBANK_ALLOW_LOGGING)
#if defined(ASURA_MEMORYBANK_ALLOW_STATS)
#include "Rendering/Asura_Font_System.h"
#endif	// defined(ASURA_MEMORYBANK_ALLOW_STATS)

// Asura platform header-files...

// Game independent header-files...

// Game platform header-files...

// Tools header-files...


////////////////////////////////////////////////////////////////////////////////
// Constant declarations...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Static variable declarations...
////////////////////////////////////////////////////////////////////////////////

// Debug variables...
#if defined(ASURA_MEMORYBANK_ALLOW_LOGGING)
DEBUGVAR bool	dbg_bLogAllMemAllocs	= false;
DEBUGVAR bool	dbg_bLogAllMemDeallocs	= false;
#endif // #if defined(ASURA_MEMORYBANK_ALLOW_LOGGING)

// Invalid handle value...
#if defined(ASURA_MEMORYBANK_INT_HANDLE)
Asura_MemoryBank::Handle	Asura_MemoryBank::s_xInvalidHandle	= ASURA_INVALID_HANDLE;
#else
Asura_MemoryBank::Handle	Asura_MemoryBank::s_xInvalidHandle	= NULL;
#endif	// defined(ASURA_MEMORYBANK_INT_HANDLE)

#if defined(ASURA_MEMORYBANK_ALLOW_STATS)
// Temporary text-buffer for stats debug-rendering...
static const u_int	g_uSizeOfTempText	= 256;
static Asura_Char	g_szTempTextBuffer [g_uSizeOfTempText];
#endif	// defined(ASURA_MEMORYBANK_ALLOW_STATS)


////////////////////////////////////////////////////////////////////////////////
// Private functions...
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank::Allocate
// Author       : Andy Tate
// Date         : 27-Feb-2006
//
// Description  : Allocates the specified number of bytes on this memory-bank.
//
// Parameters   : The number of bytes to allocate.
//
// Return value : "true" if allocated successfully, "false" if failed.
////////////////////////////////////////////////////////////////////////////////

bool Asura_MemoryBank::Allocate (const u_int uSize)
{
	const u_int	uSpaceRemaining	= m_uSizeOfData - m_uCurrentSize;

	// Is there room?
	if(uSpaceRemaining >= uSize)
	{
		// Yes - allocate the padding...
		m_uCurrentSize	+= uSize;
		return(true);
	}
	else
	{
		// No - report the error...
		Asura_Assertf(false, ("Failed to allocated %d bytes on the memory-bank.", uSize));
		return(false);
	}
}

/// End of function 'Asura_MemoryBank::Allocate'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank::PadForAlignment
// Author       : Andy Tate
// Date         : 27-Feb-2006
//
// Description  : Allocates the necessary number of bytes required for the
//				  specified memory-alignment.
//
// Parameters   : The byte alignment necessary.
//
// Return value : "true" if allocated successfully, "false" if failed.
////////////////////////////////////////////////////////////////////////////////

bool Asura_MemoryBank::PadForAlignment (const u_int uAlignment)
{
	// ART - 16/02/06 - NOTE: C-style cast here because PS3 currently has 64-bit pointers
	// and we can't perform a "reinterpret_cast" on them.
	const Handle xHandle = GetCurrentHandle();
	const u_char* pucAddress = static_cast<u_char*>(GetAddress(xHandle));
	const u_int uSizeOfUInt = sizeof(u_int);
	const u_int	uActualAlignment = Asura_Maths::Max(uAlignment, uSizeOfUInt);
	const u_int	uAlignmentOffset = (u_int)(pucAddress) % uActualAlignment;

	// Do we need to re-align the data?
	if(uAlignmentOffset > 0)
	{
		const u_int	uAlignmentModifier	= uActualAlignment - uAlignmentOffset;

		// Yes - allocate the space...
		return(Allocate(uAlignmentModifier));
	}
	else
	{
		// No - return success...
		return(true);
	}
}

/// End of function 'Asura_MemoryBank::PadForAlignment'. ///



////////////////////////////////////////////////////////////////////////////////
// Protected functions...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Public functions...
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank::Asura_MemoryBank
// Author       : Andy Tate
// Date         : 7-Feb-2006
//
// Description  : Constructor function for the memory-bank class.
//
// Parameters   : The size of the memory-bank to allocate.
//
// Return value : N/A.
////////////////////////////////////////////////////////////////////////////////

Asura_MemoryBank::Asura_MemoryBank (const char* szName,
									const u_int uSizeOfData) :
	m_xName(szName),
	m_bAllowDeletion(false),
	m_bDataAllocated(true),
	m_uSizeOfData(uSizeOfData),
	m_uCurrentSize(0),
	m_xHandleOfLastAlloc(s_xInvalidHandle),
	m_xHandleBeforeLastAlloc(s_xInvalidHandle)
{
	// Allocate the data...
	m_pucStartOfData	= new u_char [uSizeOfData];

#if defined(ASURA_MEMORYBANK_ALLOW_STATS)
	// Initialise the stats...
	m_uNumStatsTypes	= 0;
	m_pxStats			= NULL;
#endif	// defined(ASURA_MEMORYBANK_ALLOW_STATS)
}

/// End of function 'Asura_MemoryBank::Asura_MemoryBank'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank::Asura_MemoryBank
// Author       : Andy Tate
// Date         : 7-Feb-2006
//
// Description  : Constructor function for the memory-bank class.
//
// Parameters   : The size of the memory-bank to use and the address of the block
//				  of memory which has already been allocated.
//
// Return value : N/A.
////////////////////////////////////////////////////////////////////////////////

Asura_MemoryBank::Asura_MemoryBank (const char* szName,
									const u_int uSizeOfData,
									u_char* pucStartOfData) :
	m_xName(szName),
	m_bAllowDeletion(false),
	m_bDataAllocated(false),
	m_pucStartOfData(pucStartOfData),
	m_uSizeOfData(uSizeOfData),
	m_uCurrentSize(0),
	m_xHandleOfLastAlloc(s_xInvalidHandle),
	m_xHandleBeforeLastAlloc(s_xInvalidHandle)
{
#if defined(ASURA_MEMORYBANK_ALLOW_STATS)
	// Initialise the stats...
	m_uNumStatsTypes	= 0;
	m_pxStats			= NULL;
#endif	// defined(ASURA_MEMORYBANK_ALLOW_STATS)
}

/// End of function 'Asura_MemoryBank::Asura_MemoryBank'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank::~Asura_MemoryBank
// Author       : Andy Tate
// Date         : 7-Feb-2006
//
// Description  : Destructor function for the memory-bank class.
//
// Return value : N/A.
////////////////////////////////////////////////////////////////////////////////

Asura_MemoryBank::~Asura_MemoryBank ()
{
#if defined(ASURA_MEMORYBANK_ALLOW_STATS)
	// Delete the stats...
	delete[](m_pxStats);
#endif	// defined(ASURA_MEMORYBANK_ALLOW_STATS)

	// Have we allocated the data?
	if(m_bDataAllocated)
	{
		delete[](m_pucStartOfData);
	}
}

/// End of function 'Asura_MemoryBank::~Asura_MemoryBank'. ///



#if defined(ASURA_MEMORYBANK_ALLOW_STATS)

////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank::CreateStats
// Author       : Andy Tate
// Date         : 7-Feb-2006
//
// Description  : Creates the stats collection data for this memory-bank.
//
// Parameters   : The number of stats entries to use.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_MemoryBank::CreateStats (const u_int uNumStatsTypes,
									const char** pszStatsNames)
{
	// Remove any existing stats...
	delete[](m_pxStats);

	// Create the new ones...
	m_uNumStatsTypes	= uNumStatsTypes;
	m_pxStats			= new Asura_MemoryBank_Stats [uNumStatsTypes];

	// Set the individual names...
	for(u_int u = 0; u < uNumStatsTypes; u++)
	{
		m_pxStats[u].SetName(pszStatsNames[u]);
	}
}

/// End of function 'Asura_MemoryBank::CreateStats'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank_StatsRender::Asura_MemoryBank_StatsRender
// Author       : Andy Tate
// Date         : 15-Mar-2006
//
// Description  : Constructor function for the memory-bank stats render class.
//
// Parameters   : The font-handle to use, the heights of the title and line (in
//				  pixels) and the array of column-offsets (again in pixels).
//
// Return value : N/A.
////////////////////////////////////////////////////////////////////////////////

Asura_MemoryBank_StatsRender::Asura_MemoryBank_StatsRender (const Asura_Handle uFontHandle,
															const float fTitleHeight,
															const float fLineHeight,
															const float* pfColumnOffsets) :
	m_uFontHandle(uFontHandle),
	m_uColour(0xFFFFFFFF),
	m_xTopLeft(0.0f, 0.0f),
	m_fTitleHeight(fTitleHeight),
	m_fTitleScale(1.0f),
	m_fLineHeight(fLineHeight),
	m_fLineScale(1.0f)
{
	// Initialise the column-offsets...
	for(u_int u = 0; u < MAX_COLUMNS; u++)
	{
		m_afColumnOffset[u]	= pfColumnOffsets[u];
	}
}

/// End of function 'Asura_MemoryBank_StatsRender::Asura_MemoryBank_StatsRender'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank_StatsRender::RenderTitle
// Author       : Andy Tate
// Date         : 15-Mar-2006
//
// Description  : Title render function for the memory-bank stats.
//
// Parameters   : The column to render and the text to be rendered.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_MemoryBank_StatsRender::RenderTitle (const Column eColumn,
												const Asura_Char* szText) const
{
	const float		fLineSpacing	= 1.0f;
	const u_int		uFormat			= ASURA_TEXTFORMAT_DEFAULT;

	Asura_Vector_2	xPosition(m_xTopLeft);

	// Calculate the position...
	xPosition[0]	+= m_afColumnOffset[eColumn];

	// Render the text...
	Asura_Font_System::PrintShortString(szText, NULL, xPosition[0], xPosition[1], fLineSpacing, m_fTitleScale, m_uColour, uFormat);
}

/// End of function 'Asura_MemoryBank_StatsRender::RenderTitle'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank_StatsRender::RenderLine
// Author       : Andy Tate
// Date         : 15-Mar-2006
//
// Description  : Line render function for the memory-bank stats.
//
// Parameters   : The column to render, the row and text to be rendered.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_MemoryBank_StatsRender::RenderLine (const Column eColumn,
											   const u_int uRow,
											   const Asura_Char* szText) const
{
	const float		fLineSpacing	= 1.0f;
	const u_int		uFormat			= ASURA_TEXTFORMAT_DEFAULT;
	const u_int		uColour			= ((uRow & 1) == 0)
									? m_uColour
									: (m_uColour & 0xFF000000) | ((m_uColour & 0x00FEFEFE) >> 1);

	Asura_Vector_2	xPosition(m_xTopLeft);

	// Calculate the position...
	xPosition[0]	+= m_afColumnOffset[eColumn];
	xPosition[1]	+= m_fTitleHeight;
	xPosition[1]	+= (m_fLineHeight * uRow);

	// Render the text...
	Asura_Font_System::PrintShortString(szText, NULL, xPosition[0], xPosition[1], fLineSpacing, m_fLineScale, uColour, uFormat);
}

/// End of function 'Asura_MemoryBank_StatsRender::RenderLine'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank_StatsRender::RenderRow
// Author       : Andy Tate
// Date         : 15-Mar-2006
//
// Description  : Row render function for the memory-bank stats.
//
// Parameters   : The column to render, the row and text to be rendered.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_MemoryBank_StatsRender::RenderRow (const u_int uRow,
											  const Asura_Char* szText) const
{
	const float		fLineSpacing	= 1.0f;
	const u_int		uFormat			= ASURA_TEXTFORMAT_DEFAULT;

	Asura_Vector_2	xPosition(m_xTopLeft);

	// Calculate the position...
	xPosition[0]	+= m_afColumnOffset[NAME_COLUMN];
	xPosition[1]	+= m_fTitleHeight;
	xPosition[1]	+= (m_fLineHeight * uRow);

	// Render the text...
	Asura_Font_System::PrintShortString(szText, NULL, xPosition[0], xPosition[1], fLineSpacing, m_fLineScale, m_uColour, uFormat);
}

/// End of function 'Asura_MemoryBank_StatsRender::RenderTitle'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank_Stats::DebugRender
// Author       : Andy Tate
// Date         : 15-Mar-2006
//
// Description  : Performs the debug render for these stats.
//
// Parameters   : A reference to the stats-render to use for this memory-bank.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_MemoryBank_Stats::DebugRender (const Asura_MemoryBank_StatsRender& xRender,
										  const u_int uRow) const
{
	const float	fUsed	= static_cast<float>(static_cast<int>(m_uNumBytesAllocated)) / (1024.0f * 1024.0f);

	// Render the title...
	xRender.RenderLine(Asura_MemoryBank_StatsRender::NAME_COLUMN, uRow, GetName());

	Asura_PrintfToBfr(g_szTempTextBuffer, "%u", g_uSizeOfTempText, true, m_uNumAllocations);
	xRender.RenderLine(Asura_MemoryBank_StatsRender::NUM_ALLOCATIONS_COLUMN, uRow, g_szTempTextBuffer);

	Asura_PrintfToBfr( g_szTempTextBuffer, "%.3f", g_uSizeOfTempText, true, Asura_Maths::FtoD( fUsed ) );
	xRender.RenderLine(Asura_MemoryBank_StatsRender::SIZE_COLUMN, uRow, g_szTempTextBuffer);
}

/// End of function 'Asura_MemoryBank_Stats::DebugRender'. ///


#if defined(ASURA_MEMORYBANK_ALLOW_LOGGING)

////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank_Stats::OutputToDebugger
// Author       : Andy Tate
// Date         : 27-Feb-2006
//
// Description  : Dumps the current state of this set of memory-bank stats.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_MemoryBank_Stats::OutputToDebugger (void) const
{
	const float	fUsed	= static_cast<float>(static_cast<int>(m_uNumBytesAllocated)) / (1024.0f * 1024.0f);

	// Output the data...
	Asura_OutputToDebugger(("%s: %u allocations, %.3fMb\n", GetName(), m_uNumAllocations, fUsed));
}

/// End of function 'Asura_MemoryBank_Stats::OutputToDebugger'. ///

#endif	// defined(ASURA_MEMORYBANK_ALLOW_LOGGING)

#endif	// defined(ASURA_MEMORYBANK_ALLOW_STATS)



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank::Reset
// Author       : Andy Tate
// Date         : 7-Feb-2006
//
// Description  : Resets the memory-bank - effectively, blanks the contents.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_MemoryBank::Reset (void)
{
	// Reset the current size...
	m_uCurrentSize		= 0;
	m_bAllowDeletion	= false;

#if defined(ASURA_MEMORYBANK_ALLOW_STATS)
	// Do we have any stats?
	if(m_pxStats != NULL)
	{
		// Reset the stats...
		for(u_int u = 0; u < m_uNumStatsTypes; u++)
		{
			m_pxStats[u].Reset();
		}
	}
#endif	// defined(ASURA_MEMORYBANK_ALLOW_STATS)
}

/// End of function 'Asura_MemoryBank::Reset'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank::Allocate
// Author       : Andy Tate
// Date         : 7-Feb-2006
//
// Description  : Allocates the specified amount of data using the current block
//				  of memory in this memory-bank.
//
// Parameters   : The number of bytes to allocate, the type of data we're allocating
//				  and the type of alignment to use.
//
// Return value : A handle to the allocation, "ASURA_INVALID_HANDLE" if failed.
////////////////////////////////////////////////////////////////////////////////

Asura_MemoryBank::Handle Asura_MemoryBank::Allocate (const u_int uNumEntries,
													 const u_int uSizeOfEntry,
													 const u_int uDataType,
													 const ASURA_ALIGN_ID eAlignment)
{
	Handle	xHandleBeforeAlloc	= GetCurrentHandle();

#if defined(ASURA_MEMORYBANK_ALLOW_STATS)
	const u_int	uInitialSize	= m_uCurrentSize;
#endif	// defined(ASURA_MEMORYBANK_ALLOW_STATS)

	// Firstly, allocate room for the number-of-entries and the size-of-entry...
	if(Allocate(2 * sizeof(u_int)))
	{
		// Now, align for the data...
		if(PadForAlignment(static_cast<u_int>(eAlignment)))
		{
			const u_int		uNumBytes	= uNumEntries * uSizeOfEntry;
			const Handle	xHandle		= GetCurrentHandle();
			u_int*			puData		= static_cast<u_int*>(GetAddress(xHandle));

			// Now, store the size immediately before the data...
			puData[-1]	= uSizeOfEntry;
			puData[-2]	= uNumEntries;

			// ...before allocating the data itself...
			if(Allocate(uNumBytes))
			{
#if defined(ASURA_MEMORYBANK_ALLOW_STATS)
				// Collect the stats...
				if(m_pxStats != NULL)
				{
					// Is the data-type in range?
					if(uDataType < m_uNumStatsTypes)
					{
						const u_int	uActualSize	= m_uCurrentSize - uInitialSize;

						// Yes - add the actual amount of data allocated...
						m_pxStats[uDataType].AddAllocation(uActualSize);
					}
					else
					{
						Asura_Assert(false, "Data-type out of range for memory-bank stats collection.");
					}
				}
#endif	// defined(ASURA_MEMORYBANK_ALLOW_STATS)

				// Store the data for this allocation...
				m_xHandleBeforeLastAlloc	= xHandleBeforeAlloc;
				m_xHandleOfLastAlloc		= xHandle;

				// Return the handle...
				return(xHandle);
			}
			else
			{
				return(s_xInvalidHandle);
			}
		}
		else
		{
			return(s_xInvalidHandle);
		}
	}
	else
	{
		return(s_xInvalidHandle);
	}
}

/// End of function 'Asura_MemoryBank::Allocate'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank::Deallocate
// Author       : Andy Tate
// Date         : 10-Feb-2006
//
// Description  : Deallocates the specified data using the current block of 
//				  memory in this memory-bank.
//
// Parameters   : The type of data to deallocate and a handle to that data.
//
// Return value : "true" if successful, "false" if failed.
////////////////////////////////////////////////////////////////////////////////

bool Asura_MemoryBank::Deallocate (const u_int uDataType,
								   const Handle xHandle)
{
	// Is the handle valid?
	if(IsHandleValid(xHandle))
	{
		// Do we have a previous handle?
		if(m_xHandleOfLastAlloc == xHandle)
		{
			SetCurrentHandle(m_xHandleBeforeLastAlloc);
			m_xHandleBeforeLastAlloc	= s_xInvalidHandle;
			m_xHandleOfLastAlloc		= s_xInvalidHandle;
			return(true);
		}
		else
		{
			Asura_Assert(m_bAllowDeletion, "Cannot deallocate data from a memory-block.");
			return(false);
		}
	}
	else
	{
		Asura_Assert(false, "Specified handle is not from this memory-block.");
		return(false);
	}
}

/// End of function 'Asura_MemoryBank::Deallocate'. ///



#if defined(ASURA_MEMORYMANAGEMENT_ENABLED)

////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank::Allocate
// Author       : Andy Tate
// Date         : 24-Feb-2006
//
// Description  : Allocates the specified amount of data using the current block
//				  of memory in this memory-bank.
//
// Parameters   : The number of bytes to allocate, the type of data we're allocating
//				  and the type of alignment to use.
//
// Return value : A handle to the allocation, "ASURA_INVALID_HANDLE" if failed.
////////////////////////////////////////////////////////////////////////////////

Asura_MemoryBank::Handle Asura_MemoryBank::Allocate (const u_int uNumEntries,
													 const u_int uSizeOfEntry,
													 const u_int uDataType,
													 const ASURA_ALIGN_ID eAlignment,
													 const char* szFile,
													 const int iLine,
													 const u_int uReturnAddr)
{
	const Handle	xHandle	= Allocate(uNumEntries, uSizeOfEntry, uDataType, eAlignment);

#if defined(ASURA_MEMORYBANK_ALLOW_LOGGING)
	// Do we need to log this allocation?
	if(dbg_bLogAllMemAllocs)
	{
		const void*	pvData	= GetAddress(xHandle);

		// Simply call the other function (for now)...
		Asura_SimpleLogfileOutput(("Logfiles\\Memory.txt",
								   "Memory-bank alloc:   frame %4i, [0x%08x] %10i bytes at line %4i of %s\n\r",
								   Asura_Timers::GetFrameNumber(),
								   pvData,
								   uNumEntries * uSizeOfEntry,
								   iLine,
								   szFile));
	}
#endif	// defined(ASURA_MEMORYBANK_ALLOW_LOGGING)

	// Return the handle...
	return(xHandle);
}

/// End of function 'Asura_MemoryBank::Allocate'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank::Deallocate
// Author       : Andy Tate
// Date         : 24-Feb-2006
//
// Description  : Deallocates the specified data using the current block of 
//				  memory in this memory-bank.
//
// Parameters   : The type of data to deallocate and a handle to that data.
//
// Return value : "true" if successful, "false" if failed.
////////////////////////////////////////////////////////////////////////////////

bool Asura_MemoryBank::Deallocate (const u_int uDataType,
								   const Handle xHandle,
								   const char* szFile,
								   const int iLine)
{
#if defined(ASURA_MEMORYBANK_ALLOW_LOGGING)
	// Do we need to log this deallocation?
	if(dbg_bLogAllMemDeallocs)
	{
		const void*			pvData	= GetAddress(xHandle);

		// Simply call the other function (for now)...
		Asura_SimpleLogfileOutput(("Logfiles\\Memory.txt",
								   "Memory-bank dealloc: frame %4i, [0x%08x] at line %4i of %s\n\r",
								   Asura_Timers::GetFrameNumber(),
								   pvData,
								   iLine,
								   szFile));
	}
#endif	// defined(ASURA_MEMORYBANK_ALLOW_LOGGING)

	// Is the handle valid?
	if(IsHandleValid(xHandle))
	{
		// Temporary...
		Asura_Assertf(m_bAllowDeletion, ("Cannot deallocate data from a memory-block.\nFile: %s\nLine: %d", szFile, iLine));
		return(false);
	}
	else
	{
		Asura_Assert(false, "Specified handle is not from this memory-block.");
		return(false);
	}
}

/// End of function 'Asura_MemoryBank::Deallocate'. ///

#endif	// defined(ASURA_MEMORYMANAGEMENT_ENABLED)


#if defined(ASURA_MEMORYBANK_ALLOW_LOGGING)

////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank::OutputToDebugger
// Author       : Andy Tate
// Date         : 27-Feb-2006
//
// Description  : Dumps the current state of this memory-bank.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_MemoryBank::OutputToDebugger (void) const
{
	const float	fUsedMb			= static_cast<float>(static_cast<int>(m_uCurrentSize)) / (1024.0f * 1024.0f);
	const float	fTotalMb		= static_cast<float>(static_cast<int>(m_uSizeOfData)) / (1024.0f * 1024.0f);
	const float	fPercentageUsed	= (fUsedMb / fTotalMb) * 100.0f;

	// Output the data...
	Asura_OutputToDebugger(("--------------------------------------------------------------------------------\n"));
	Asura_OutputToDebugger(("Memory-bank \"%s\"\n", GetName()));
	Asura_OutputToDebugger(("--------------------------------------------------------------------------------\n"));
	Asura_OutputToDebugger(("Used %.3fMb of %.3fMb (%.3f%%)\n", fUsedMb, fTotalMb, fPercentageUsed));
	Asura_OutputToDebugger(("--------------------------------------------------------------------------------\n"));

#if defined(ASURA_MEMORYBANK_ALLOW_STATS)
	// Do we have any stats?
	if(m_pxStats != NULL)
	{
		// Output the specific stats...
		for(u_int u = 0; u < m_uNumStatsTypes; u++)
		{
			m_pxStats[u].OutputToDebugger();
		}
		Asura_OutputToDebugger(("--------------------------------------------------------------------------------\n"));
	}
#endif	// defined(ASURA_MEMORYBANK_ALLOW_STATS)
}

/// End of function 'Asura_MemoryBank::OutputToDebugger'. ///

#endif	// defined(ASURA_MEMORYBANK_ALLOW_LOGGING)


#if defined(ASURA_MEMORYBANK_ALLOW_STATS)

////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_MemoryBank::DebugRenderStats
// Author       : Andy Tate
// Date         : 15-Mar-2006
//
// Description  : Performs the render for the stats.
//
// Parameters   : The handle to the font to use, along with the 
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_MemoryBank::DebugRenderStats (const Asura_MemoryBank_StatsRender& xRender) const
{
	const float	fUsedMb			= static_cast<float>(static_cast<int>(m_uCurrentSize)) / (1024.0f * 1024.0f);
	const float	fTotalMb		= static_cast<float>(static_cast<int>(m_uSizeOfData)) / (1024.0f * 1024.0f);
	const float	fPercentageUsed	= (fUsedMb / fTotalMb) * 100.0f;

	// Render the title...
	xRender.RenderTitle(Asura_MemoryBank_StatsRender::NAME_COLUMN, GetName());
	xRender.RenderTitle(Asura_MemoryBank_StatsRender::NUM_ALLOCATIONS_COLUMN, "Allocs");
	xRender.RenderTitle(Asura_MemoryBank_StatsRender::SIZE_COLUMN, "Mb");

	// Do we have any stats?
	if(m_pxStats != NULL)
	{
		// Yes - output the specific stats...
		for(u_int u = 0; u < m_uNumStatsTypes; u++)
		{
			m_pxStats[u].DebugRender(xRender, u);
		}
	}

	// Render the summary...
	Asura_PrintfToBfr(g_szTempTextBuffer, "Used %.3fMb of %.3fMb (%.3f%%)", g_uSizeOfTempText, true, Asura_Maths::FtoD( fUsedMb ), Asura_Maths::FtoD( fTotalMb ), Asura_Maths::FtoD( fPercentageUsed ) );
	xRender.RenderRow(m_uNumStatsTypes + 1, g_szTempTextBuffer);
}

/// End of function 'Asura_MemoryBank::DebugRenderStats'. ///

#endif	// defined(ASURA_MEMORYBANK_ALLOW_STATS)


/// End of file. ///
