summaryrefslogtreecommitdiffstats
path: root/game/code/debug
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--game/code/debug/alldebug.cpp3
-rw-r--r--game/code/debug/debuginfo.cpp782
-rw-r--r--game/code/debug/debuginfo.h204
-rw-r--r--game/code/debug/profiler.cpp753
-rw-r--r--game/code/debug/profiler.h206
-rw-r--r--game/code/debug/ps2perf.hpp263
-rw-r--r--game/code/debug/section.cpp236
-rw-r--r--game/code/debug/section.h108
8 files changed, 2555 insertions, 0 deletions
diff --git a/game/code/debug/alldebug.cpp b/game/code/debug/alldebug.cpp
new file mode 100644
index 0000000..d11b9ea
--- /dev/null
+++ b/game/code/debug/alldebug.cpp
@@ -0,0 +1,3 @@
+#include <debug/debuginfo.cpp>
+#include <debug/profiler.cpp>
+#include <debug/section.cpp>
diff --git a/game/code/debug/debuginfo.cpp b/game/code/debug/debuginfo.cpp
new file mode 100644
index 0000000..7b41485
--- /dev/null
+++ b/game/code/debug/debuginfo.cpp
@@ -0,0 +1,782 @@
+//==============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: debuginfo.cpp
+//
+// Description: In-game visual debug output
+//
+// History: 2002/07/02 + Migrated from Mirth -- Darwin Chau
+//
+//==============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include <string.h>
+// FTech
+#include <raddebug.hpp>
+#include <raddebugwatch.hpp>
+// Pure3D
+#include <p3d/font.hpp>
+#include <p3d/matrixstack.hpp>
+#include <p3d/texturefont.hpp>
+#include <p3d/unicode.hpp>
+#include <p3d/utility.hpp>
+#include <pddi/pddi.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include <debug/debuginfo.h>
+#include <debug/section.h>
+
+#include <memory/srrmemory.h>
+
+#ifdef DEBUGINFO_ENABLED
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+
+//The Adlib font. <sigh>
+static unsigned char gFont[] =
+#include <font/defaultfont.h>
+
+// Static pointer to instance of singleton.
+DebugInfo* DebugInfo::_Instance = NULL;
+
+static void Next()
+{
+ DebugInfo::GetInstance()->OnNext();
+}
+
+static void Switch()
+{
+ DebugInfo::GetInstance()->OnSwitch();
+}
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+
+//==============================================================================
+// DebugInfo::DebugInfo
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+DebugInfo::DebugInfo() :
+ _pDebugFont(NULL),
+ _pTypeFace(NULL),
+ _NumSection(0),
+ _StackSize(0),
+ _CurrentSection(0),
+ _DebugMenuTime(0.0f),
+ _isRenderEnabled(false),
+ _isCreationSectionOpen(false),
+ _mode(OFF),
+ _shader(NULL)
+{
+ for(int i=0; i<MaxSections; i++)
+ {
+ _ppSections[i] = NULL;
+ }
+
+ radDbgWatchAddFunction( "Next Section", (RADDEBUGWATCH_CALLBACK)Next, 0, "DebugInfo" );
+ radDbgWatchAddFunction( "Toggle Display", (RADDEBUGWATCH_CALLBACK)Switch, 0, "DebugInfo" );
+}
+
+
+//==============================================================================
+// DebugInfo::~DebugInfo
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+DebugInfo::~DebugInfo()
+{
+ if(_pDebugFont)
+ {
+ _pDebugFont->Release ();
+ }
+
+ if(_shader)
+ _shader->Release();
+
+ int i;
+ for(i=0; i<MaxSections; i++)
+ {
+ if(_ppSections[i])
+ delete (GMA_DEBUG, _ppSections[i]);
+ }
+}
+
+
+//==============================================================================
+// DebugInfo::CreateInstance
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::CreateInstance()
+{
+MEMTRACK_PUSH_GROUP( "DebugInfo" );
+ HeapMgr()->PushHeap( GMA_DEBUG );
+
+ _Instance = new DebugInfo;
+
+ HeapMgr()->PopHeap ( GMA_DEBUG );
+MEMTRACK_POP_GROUP( "DebugInfo" );
+}
+
+
+//==============================================================================
+// DebugInfo::CreateNewSection
+//==============================================================================
+//
+// Description: Creates a new section
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::CreateNewSection( const char* section )
+{
+ HeapMgr()->PushHeap( GMA_DEBUG );
+ //Lazy section allocation
+ if(_ppSections[_NumSection])
+ {
+ _ppSections[_NumSection]->Reset( section );
+ }
+ else
+ {
+ if( _pDebugFont == NULL )
+ {
+ //
+ // find the font
+ //
+ _pDebugFont = p3d::find<tTextureFont>("adlibn_20");
+
+ if( _pDebugFont == NULL )
+ {
+ // Convert memory buffer into a texturefont.
+ //
+ p3d::load(gFont, DEFAULTFONT_SIZE, GMA_DEBUG);
+ _pDebugFont = p3d::find<tTextureFont>("adlibn_20");
+ rAssertMsg(_pDebugFont, ("ERROR - debug font not found."));
+ }
+
+ _pDebugFont->AddRef();
+ }
+
+ _ppSections[_NumSection] = new Section( _pDebugFont, section );
+ }
+ //_pStack[_StackSize++] = _NumSection;
+ _NumSection++;
+ HeapMgr()->PopHeap( GMA_DEBUG );
+}
+
+//==============================================================================
+// DebugInfo::DestroyInstance
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::DestroyInstance()
+{
+ delete(GMA_DEBUG, _Instance);
+}
+
+
+//==============================================================================
+// DebugInfo::GetInstance
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+DebugInfo* DebugInfo::GetInstance()
+{
+ if(!_Instance)
+ {
+ CreateInstance();
+ }
+
+ return _Instance;
+}
+
+//==============================================================================
+// DebugInfo::InitializeStaticVariables
+//==============================================================================
+//
+// Description: Initializes all the sections that we're ever going to use
+//
+// Parameters: none
+//
+// Return: none
+//
+//==============================================================================
+void DebugInfo::InitializeStaticVariables()
+{
+ GetInstance()->CreateNewSection( "Vehicle Terrain Type" );
+ GetInstance()->CreateNewSection( "Vehicle Shit" );
+}
+
+//==============================================================================
+// DebugInfo::OnSwitch
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::OnSwitch()
+{
+ _mode = (Mode) ((_mode + 1) % MODE_MAX);
+
+ if(_mode == OFF)
+ {
+ _isRenderEnabled = false;
+ _isBackgroundEnabled = false;
+ }
+ else if(_mode == BACKGROUND)
+ {
+ _isRenderEnabled = true;
+ _isBackgroundEnabled = true;
+ }
+ else if(_mode == NOBACKGROUND)
+ {
+ _isRenderEnabled = true;
+ _isBackgroundEnabled = false;
+ }
+
+}
+
+
+//==============================================================================
+// DebugInfo::Push
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+bool DebugInfo::Push(char* szSection)
+{
+MEMTRACK_PUSH_GROUP( "DebugInfo" );
+ HeapMgr()->PushHeap (GMA_DEBUG);
+
+ rAssert(szSection);
+ rAssert(_StackSize<MaxStackSize);
+
+ int i;
+ bool bFound = false;
+
+ //Check for exsisting section
+ for(i=0;i<_NumSection;i++)
+ {
+ //look for the global section (NULL) or a matching name
+ const char* szName = _ppSections[i]->GetName();
+ if(0==strcmp(szSection,szName))
+ {
+ _pStack[_StackSize++] = i;
+ bFound = true;
+ break;
+ }
+ }
+ //Create a new section
+ if(!bFound)
+ {
+ CreateNewSection( szSection );
+ }
+MEMTRACK_POP_GROUP( "DebugInfo" );
+ HeapMgr()->PopHeap (GMA_DEBUG);
+
+ //Return true if this is the current section
+ return (bFound && i==_CurrentSection);
+}
+
+
+//==============================================================================
+// DebugInfo::GetCurrentSection
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+const char* DebugInfo::GetCurrentSection()
+{
+ Section *pSect = _ppSections[_CurrentSection];
+ if (pSect && _isRenderEnabled)
+ return (pSect->GetName());
+ else
+ return (NULL);
+}
+
+
+//==============================================================================
+// DebugInfo::Pop
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::Pop()
+{
+ rAssert( _NumSection > 0 );
+ rAssert( _StackSize >= 0 );
+ --_StackSize;
+}
+
+
+
+//==============================================================================
+// int SignedMod
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+
+//==============================================================================
+int SignedMod(int a, int b)
+{
+ rAssert(b>0);
+ if (a>=0) return (a%b);
+ else return (b - ((-a)%b));
+}
+
+
+//==============================================================================
+// DebugInfo::Toggle
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::Toggle(int step)
+{
+ _CurrentSection = SignedMod(_CurrentSection+step, _NumSection);
+ _DebugMenuTime = 1.0f;
+}
+
+
+//==============================================================================
+// DebugInfo::SetAutoReset
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::SetAutoReset(bool autoreset)
+{
+ rAssert(_NumSection>0);
+ rAssert(_StackSize>0);
+
+ _ppSections[_pStack[_StackSize-1]]->SetAutoReset(autoreset);
+}
+
+
+
+//==============================================================================
+// DebugInfo::Reset
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::Reset(char* sectionName)
+{
+ rAssert(_NumSection>0);
+ rAssert(_StackSize>0);
+
+ _ppSections[_pStack[_StackSize-1]]->Reset(sectionName);
+}
+
+
+//==============================================================================
+// DebugInfo::AddLine
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::AddLine(const rmt::Vector& a, const rmt::Vector& b, tColour colour)
+{
+ rAssert(_NumSection>0);
+ rAssert(_StackSize>0);
+
+ _ppSections[_pStack[_StackSize-1]]->AddLine(a, b, colour);
+}
+
+
+//==============================================================================
+// DebugInfo::AddHVector
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::AddHVector(rmt::Vector o, rmt::Vector v, float h, tColour colour)
+{
+ // Add the origin to the vector
+ v.Add(o);
+ // Add the elevation
+ v.Add(rmt::Vector(0, h, 0));
+ o.Add(rmt::Vector(0, h, 0));
+ // Then, its a regular line
+ AddLine(o, v, colour);
+}
+
+
+//==============================================================================
+// DebugInfo::AddStar
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::AddStar(const rmt::Vector& vx, tColour colour, float scale)
+{
+ rAssert(_NumSection>0);
+ rAssert(_StackSize>0);
+
+ //Draw a kind of star
+ rmt::Vector a, b;
+ a = b = vx;
+ a.x += scale; b.x -= scale;
+ AddLine( a, b, colour );
+ a = b = vx;
+ a.y += scale; b.y -= scale;
+ AddLine( a, b, colour );
+ a = b = vx;
+ a.z += scale; b.z -= scale;
+ AddLine( a, b, colour );
+}
+
+
+//==============================================================================
+// DebugInfo::AddBox
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::AddBox(const rmt::Vector& a, const rmt::Vector& b, tColour colour)
+{
+ //Draw all 12 lines that make up the box
+ for(int i=0;i<4;i++)
+ {
+ AddLine(rmt::Vector((i&2)?a.x:b.x,(i&1)?a.y:b.y,a.z),
+ rmt::Vector((i&2)?a.x:b.x,(i&1)?a.y:b.y,b.z),colour);
+ AddLine(rmt::Vector((i&2)?a.x:b.x,a.y,(i&1)?a.z:b.z),
+ rmt::Vector((i&2)?a.x:b.x,b.y,(i&1)?a.z:b.z),colour);
+ AddLine(rmt::Vector(a.x,(i&2)?a.y:b.y,(i&1)?a.z:b.z),
+ rmt::Vector(b.x,(i&2)?a.y:b.y,(i&1)?a.z:b.z),colour);
+ }
+}
+
+
+//==============================================================================
+// DebugInfo::AddBox
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::AddBox(const rmt::Vector &center, const float r, tColour colour)
+{
+ rmt::Vector a,b;
+ a.Sub(center, rmt::Vector(r,r,r));
+ b.Add(center, rmt::Vector(r,r,r));
+
+ AddBox(a,b,colour);
+}
+
+
+//==============================================================================
+// DebugInfo::AddCircle
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::AddCircle( const rmt::Vector& center, const float r, tColour colour )
+{
+ rmt::Vector a,b;
+ int i;
+ int n = 8;
+ for( i = 0; i < n; i++ )
+ {
+ a.x = center.x + r * rmt::Cos( i * rmt::PI_2 / n );
+ a.y = center.y;
+ a.z = center.z + r * rmt::Sin( i * rmt::PI_2 / n );
+ b.x = center.x + r * rmt::Cos( ( i + 1 ) * rmt::PI_2 / n );
+ b.y = center.y;
+ b.z = center.z + r * rmt::Sin( ( i + 1 ) * rmt::PI_2 / n );
+ AddLine( a, b, colour );
+ }
+}
+
+
+//==============================================================================
+// DebugInfo::AddText
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::AddText(const char *szName, const rmt::Vector &pos, tColour colour)
+{
+ rAssert(_NumSection>0);
+ rAssert(_StackSize>0);
+
+ _ppSections[_pStack[_StackSize-1]]->AddText(szName, pos, colour);
+}
+
+
+//==============================================================================
+// DebugInfo::AddScreenLine
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::AddScreenLine(const rmt::Vector& a, const rmt::Vector& b, tColour colour)
+{
+ rAssert(_NumSection>0);
+ rAssert(_StackSize>0);
+
+ _ppSections[_pStack[_StackSize-1]]->AddScreenLine(a, b, colour);
+}
+
+
+//==============================================================================
+// DebugInfo::AddScreenText
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::AddScreenText(const char* szName, tColour colour )
+{
+ rAssert(_NumSection>0);
+ rAssert(_StackSize>0);
+
+ _ppSections[_pStack[_StackSize-1]]->AddScreenText(szName, colour);
+}
+
+
+//==============================================================================
+// DebugInfo::AddScreenText
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::AddScreenText(const char* szName, const rmt::Vector &a, tColour colour )
+{
+ rAssert(_NumSection>0);
+ rAssert(_StackSize>0);
+
+ _ppSections[_pStack[_StackSize-1]]->AddScreenText(szName, a,colour);
+}
+
+
+//==============================================================================
+// DebugInfo::RenderBackground
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::RenderBackground()
+{
+ p3d::stack->Push();
+ p3d::stack->LoadIdentity();
+ pddiProjectionMode mode = p3d::pddi->GetProjectionMode();
+ p3d::pddi->SetProjectionMode(PDDI_PROJECTION_DEVICE);
+ p3d::pddi->SetCullMode(PDDI_CULL_NONE);
+
+ if( _shader == NULL )
+ {
+ //
+ // init the shader
+ //
+ _shader = p3d::device->NewShader("simple");
+ _shader->SetInt(PDDI_SP_SHADEMODE, PDDI_SHADE_FLAT);
+ }
+ _shader->SetInt(PDDI_SP_BLENDMODE, PDDI_BLEND_ALPHA);
+
+ pddiPrimStream* stream = p3d::pddi->BeginPrims(_shader, PDDI_PRIM_TRIANGLES, PDDI_V_C, 6);
+
+ float nearplane, farplane, fov, aspect;
+ p3d::pddi->GetCamera(&nearplane, &farplane, &fov, &aspect);
+ nearplane += 0.01f;
+
+ float width, height;
+ width = (float)p3d::display->GetWidth();
+ height = (float)p3d::display->GetHeight();
+ pddiColour colour(0, 0, 0, 200);
+
+ stream->Colour(colour); stream->Coord(0, height, nearplane);
+ stream->Colour(colour); stream->Coord(width, height, nearplane);
+ stream->Colour(colour); stream->Coord(width, 0, nearplane);
+ stream->Colour(colour); stream->Coord(0, height, nearplane);
+ stream->Colour(colour); stream->Coord(width, 0, nearplane);
+ stream->Colour(colour); stream->Coord(0, 0, nearplane);
+
+
+ p3d::pddi->EndPrims(stream);
+
+ p3d::pddi->SetProjectionMode(mode);
+ p3d::stack->Pop();
+}
+
+
+//==============================================================================
+// DebugInfo::Render
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void DebugInfo::Render()
+{
+ //rAssert(_StackSize==0);
+
+ // skip if disabled or no sections
+ if(! _isRenderEnabled) return;
+ if(_NumSection == 0) return;
+
+ // this makes the text easier to read
+ if(_isBackgroundEnabled) RenderBackground();
+
+ // render the title with the name of the current section
+ char sectionName[255] = "DebugInfo : ";
+ Section *pSect = _ppSections[_CurrentSection];
+ sprintf(sectionName, "DebugInfo : %s", pSect->GetName());
+ p3d::pddi->DrawString(sectionName, 40, 50, tColour(0,255,255));
+
+ // render the current section
+ pSect->Render();
+
+ //Clear all the sections after we display
+ int i;
+ for(i=0;i<_NumSection;i++)
+ {
+ if(_ppSections[i]->GetAutoReset())
+ {
+ _ppSections[i]->Reset(_ppSections[i]->GetName());
+ }
+ }
+}
+
+#endif // DEBUGINFO_ENABLED \ No newline at end of file
diff --git a/game/code/debug/debuginfo.h b/game/code/debug/debuginfo.h
new file mode 100644
index 0000000..5c1b460
--- /dev/null
+++ b/game/code/debug/debuginfo.h
@@ -0,0 +1,204 @@
+//==============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: debuginfo.h
+//
+// Description: In-game visual debug output
+//
+// History: 2002/07/02 + Migrated from Mirth -- Darwin Chau
+//
+//==============================================================================
+
+#ifndef DEBUGINFO_HPP
+#define DEBUGINFO_HPP
+
+
+//
+// DebugInfo is only available in RAD_DEBUG and RAD_TUNE configurations
+//
+#ifndef RAD_RELEASE
+#define DEBUGINFO_ENABLED
+#endif // RAD_RELEASE
+
+
+
+#include "main/commandlineoptions.h"
+
+
+//==============================================================================
+// *** USE THESE MACROS, DO NOT INVOKE DEBUG INFO DIRECTLY ***
+//==============================================================================
+
+#ifndef DEBUGINFO_ENABLED
+
+#define CREATE_DEBUGINFO()
+#define DESTROY_DEBUGINFO()
+
+#define DEBUGINFO_PUSH_SECTION(s)
+#define DEBUGINFO_POP_SECTION()
+
+#define DEBUGINFO_ADDSCREENTEXT(s)
+#define DEBUGINFO_ADDSCREENTEXTVECTOR(s, v)
+#define DEBUGINFO_ADDSCREENTEXTVECTORCOLOUR(s, v, c)
+#define DEBUGINFO_ADDSCREENLINE(v1, v2, c)
+#define DEBUGINFO_ADDLINE(v1, v2, c)
+#define DEBUGINFO_ADDCIRCLE(v1, v2, c)
+#define DEBUGINFO_ADDSTAR(v1, c, s)
+
+#define DEBUGINFO_TOGGLE(step)
+
+#define DEBUGINFO_RENDER();
+
+#else
+
+#define CREATE_DEBUGINFO() if(!CommandLineOptions::Get(CLO_FIREWIRE)) { DebugInfo::CreateInstance(); }
+#define DESTROY_DEBUGINFO() if(!CommandLineOptions::Get(CLO_FIREWIRE)) { DebugInfo::DestroyInstance(); }
+
+#define DEBUGINFO_PUSH_SECTION(s) (!CommandLineOptions::Get(CLO_FIREWIRE)) ? DebugInfo::GetInstance()->Push(s) : false
+#define DEBUGINFO_POP_SECTION() if(!CommandLineOptions::Get(CLO_FIREWIRE)) { DebugInfo::GetInstance()->Pop(); }
+
+#define DEBUGINFO_ADDSCREENTEXT(s) if(!CommandLineOptions::Get(CLO_FIREWIRE)) { DebugInfo::GetInstance()->AddScreenText(s); }
+#define DEBUGINFO_ADDSCREENTEXTVECTOR(s, v) if(!CommandLineOptions::Get(CLO_FIREWIRE)) { DebugInfo::GetInstance()->AddScreenText(s, v); }
+#define DEBUGINFO_ADDSCREENTEXTVECTORCOLOUR(s, v, c) if(!CommandLineOptions::Get(CLO_FIREWIRE)) { DebugInfo::GetInstance()->AddScreenText(s, v, c); }
+#define DEBUGINFO_ADDSCREENLINE(v1, v2, c) if(!CommandLineOptions::Get(CLO_FIREWIRE)) { DebugInfo::GetInstance()->AddScreenLine(v1, v2, c); }
+#define DEBUGINFO_ADDLINE(v1, v2, c) if(!CommandLineOptions::Get(CLO_FIREWIRE)) { DebugInfo::GetInstance()->AddLine(v1, v2, c); }
+#define DEBUGINFO_ADDCIRCLE(v1, v2, c) if(!CommandLineOptions::Get(CLO_FIREWIRE)) { DebugInfo::GetInstance()->AddCircle(v1, v2, c); }
+#define DEBUGINFO_ADDSTAR(v1, c, s) if(!CommandLineOptions::Get(CLO_FIREWIRE)) { DebugInfo::GetInstance()->AddStar(v1, c, s); }
+
+#define DEBUGINFO_TOGGLE(step) if(!CommandLineOptions::Get(CLO_FIREWIRE)) { DebugInfo::GetInstance()->Toggle(step); }
+
+#define DEBUGINFO_RENDER() if(!CommandLineOptions::Get(CLO_FIREWIRE)) { DebugInfo::GetInstance()->Render(); }
+
+
+//========================================
+// Nested Includes
+//========================================
+// Radmath
+#include <radmath/radmath.hpp>
+// Pure3D
+#include <p3d/p3dtypes.hpp>
+#include <pddi/pddi.hpp>
+
+//========================================
+// Forward References
+//========================================
+
+class tFont;
+class tTypeFace;
+class Section;
+
+//==============================================================================
+//
+// Synopsis: DebugInfo class provides visual debugging support.
+//
+//==============================================================================
+class DebugInfo
+{
+public:
+ /** get the singleton */
+ static DebugInfo* GetInstance();
+
+ /** creates the singleton */
+ static void CreateInstance();
+
+ /** destroys the instance */
+ static void DestroyInstance();
+ static void InitializeStaticVariables();
+
+
+ /** Render */
+ void Render();
+
+ /** Push a section */
+ bool Push(char* szSection);
+
+ /** Pop a section */
+ void Pop();
+
+ /** Get the name of the last section pushed */
+ const char* GetCurrentSection();
+
+
+ //Toggle through the current sections
+ void Toggle(int step);
+
+ //Debugging output functions, for world space primitives
+ void BeginSectionCreation() { _isCreationSectionOpen = true; };
+ void EndSectionCreation() { _isCreationSectionOpen = false; };
+
+ /** make the section to resest automatically after the render */
+ void SetAutoReset(bool autoreset);
+
+ /** reset the current section
+ * @param sectionName the new name of the section
+ */
+ void Reset(char* sectionName);
+
+ void AddLine(const rmt::Vector &a, const rmt::Vector &b, tColour colour = tColour(255,255,255));
+ void AddHVector(rmt::Vector o, rmt::Vector v, float h, tColour colour = tColour(255,255,255));
+ void AddBox(const rmt::Vector &a, const rmt::Vector &b, tColour colour = tColour(255,255,255));
+ void AddBox(const rmt::Vector &center, const float r, tColour colour = tColour(255,255,255));
+ void AddCircle(const rmt::Vector &center, const float r, tColour colour = tColour(255,255,255));
+ void AddStar(const rmt::Vector& vx, tColour colour = tColour(255,255,255), float scale = 0.1f);
+ void AddText(const char *szName, const rmt::Vector &pos, tColour colour = tColour(255,255,255));
+
+ //Output functions for screen space primitives
+ //All screen space is in x=[0..1], y=[0..1], with (0,0) at the top left
+ void AddScreenLine(const rmt::Vector &a, const rmt::Vector &b, tColour colour = tColour(255,255,255));
+ void AddScreenText(const char* szName, tColour colour = tColour(255,255,255));
+ void AddScreenText(const char* szName, const rmt::Vector &a, tColour colour = tColour(255,255,255));
+
+ //
+ // GUI events
+ //
+ void OnNext() { Toggle(1); };
+ void OnSwitch();
+
+protected:
+ void CreateNewSection( const char* section );
+private:
+ /** Constructor */
+ DebugInfo();
+
+ /** Destructor */
+ ~DebugInfo();
+
+ /** Render the backgound */
+ void RenderBackground();
+
+
+// TODO: (chakib) do we need this ?
+#if 1
+ tFont* _pDebugFont;
+ tTypeFace* _pTypeFace;
+#endif
+
+ enum { MaxSections = 20 };
+ int _NumSection;
+ Section* _ppSections[MaxSections];
+
+ enum { MaxStackSize = 20 };
+ int _StackSize;
+ int _pStack[MaxStackSize];
+
+ int _CurrentSection;
+
+ float _DebugMenuTime;
+
+ static DebugInfo* _Instance;
+
+ bool _isRenderEnabled;
+ bool _isBackgroundEnabled;
+ bool _isCreationSectionOpen;
+
+ enum Mode {OFF, BACKGROUND, NOBACKGROUND, MODE_MAX};
+ Mode _mode;
+
+ pddiShader* _shader; //@- used the render the background
+};
+
+
+#endif // ! DEBUGINFO_ENABLED
+
+#endif // DEBUGINFO_HPP
+
diff --git a/game/code/debug/profiler.cpp b/game/code/debug/profiler.cpp
new file mode 100644
index 0000000..cb2949c
--- /dev/null
+++ b/game/code/debug/profiler.cpp
@@ -0,0 +1,753 @@
+//===========================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// Component: PS2Platform
+//
+// Description: Abstracts the differences for setting up and shutting down
+// the different platforms.
+//
+// History: + Stolen and cleaned up from Penthouse -- Darwin Chau
+//
+//===========================================================================
+
+//========================================
+// System Includes
+//========================================
+// Libraries
+#include <string.h>
+#include <stdio.h>
+// Foundation
+#include <radtime.hpp>
+#include <raddebug.hpp>
+#include <raddebugwatch.hpp>
+// Pure3D
+#include <pddi/pddi.hpp>
+#include <p3d/p3dtypes.hpp>
+#include <p3d/utility.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include <debug/profiler.h>
+#include <memory/srrmemory.h>
+
+
+#ifdef PROFILER_ENABLED
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+
+// Static pointer to instance of singleton.
+Profiler* Profiler::spInstance = NULL;
+
+int Profiler::sRed = 0;
+int Profiler::sGreen = 0;
+int Profiler::sBlue = 0;
+int Profiler::sPage = 0;
+int Profiler::sLeftOffset = 0;
+int Profiler::sTopOffset = 0;
+bool Profiler::sDisplay = false;
+bool Profiler::sDumpToOutput = false;
+bool Profiler::sEnableCollection = false;
+
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// Profiler::CreateInstance
+//==============================================================================
+//
+// Description: Creates the Profiler.
+//
+// Parameters: None.
+//
+// Return: Pointer to the Profiler.
+//
+// Constraints: This is a singleton so only one instance is allowed.
+//
+//==============================================================================
+Profiler* Profiler::CreateInstance()
+{
+MEMTRACK_PUSH_GROUP( "Profiler" );
+ rAssert( spInstance == NULL );
+
+ spInstance = new(GMA_DEBUG) Profiler;
+ rAssert( spInstance );
+MEMTRACK_POP_GROUP( "Profiler" );
+
+ return spInstance;
+}
+
+//==============================================================================
+// Profiler::GetInstance
+//==============================================================================
+//
+// Description: - Access point for the Profiler singleton.
+//
+// Parameters: None.
+//
+// Return: Pointer to the Profiler.
+//
+// Constraints: This is a singleton so only one instance is allowed.
+//
+//==============================================================================
+Profiler* Profiler::GetInstance()
+{
+ rAssert( spInstance != NULL );
+
+ return spInstance;
+}
+
+
+//==============================================================================
+// Profiler::DestroyInstance
+//==============================================================================
+//
+// Description: Destroy the Profiler.
+//
+// Parameters: None.
+//
+// Return: None.
+//
+//==============================================================================
+void Profiler::DestroyInstance()
+{
+ rAssert( spInstance != NULL );
+
+ delete( GMA_DEBUG, spInstance );
+ spInstance = NULL;
+}
+
+
+
+//==============================================================================
+// Profiler::Init
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void Profiler::Init()
+{
+}
+
+
+
+//==============================================================================
+// Profiler::AllocSample
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return: the next available sample or NULL
+//
+//==============================================================================
+Profiler::ProfileSample *Profiler::AllocSample(void)
+{
+ if (mNextSampleAllocIndex >= NUM_SAMPLES) return NULL;
+
+ return &mSamples[mNextSampleAllocIndex++];
+}
+
+//==============================================================================
+// Profiler::AllocHistory
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return: the next available history or NULL
+//
+//==============================================================================
+Profiler::ProfileSampleHistory *Profiler::AllocHistory(void)
+{
+ if (mNextHistoryAllocIndex >= NUM_SAMPLES) return NULL;
+
+ return &mHistory[mNextHistoryAllocIndex++];
+}
+
+//==============================================================================
+// Profiler::BeginFrame
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void Profiler::BeginFrame()
+{
+ int i;
+ for( i = 0; i < NUM_SAMPLES; ++i )
+ {
+ mSamples[i].bValid = false;
+ }
+
+ mOpenStackTop = -1;
+ mNextSampleAllocIndex = 0;
+
+ mStartProfile = ((float)radTimeGetMicroseconds()) / 1000.0F;
+
+ mOpenSampleStore->RemoveAll();
+
+ //
+ // Only collect profile data if we're actually going to show it on the screen.
+ // Check it here so that we don't turn it on/off in mid-sample.
+ //
+ sEnableCollection = sDisplay;
+}
+
+
+//==============================================================================
+// Profiler::EndFrame
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void Profiler::EndFrame()
+{
+ unsigned int i = 0;
+
+ if( !sEnableCollection )
+ {
+ return;
+ }
+
+ mEndProfile = ((float)radTimeGetMicroseconds()) / 1000.0F;
+
+ while( i < mNextSampleAllocIndex)
+ {
+ if (!mSamples[i].bValid) continue;
+ float sampleTime, percentTime;
+
+ rAssertMsg(!mSamples[i].isOpen, "ProfileEnd() called without a ProfileBegin()" );
+
+ sampleTime = mSamples[i].fAccumulator - mSamples[i].fChildrenSampleTime;
+
+ float profileTime = mEndProfile - mStartProfile;
+
+ if( profileTime < 0.001F )
+ {
+ percentTime = 0.0f;
+ }
+ else
+ {
+ percentTime = ( sampleTime / profileTime ) * 100.0f;
+ rAssert( percentTime <= 100.0f );
+ }
+
+ //
+ // Add new measurement into the history and get the ave, min, and max
+ //
+// this->StoreProfileHistory( mSamples[i].szName,
+// percentTime,
+// mEndProfile - mStartProfile,
+// mSamples[i].uiSampleTime, // single sample
+// mSamples[i].uiAccumulator ); // total sample
+ this->StoreProfileHistory( mSamples[i].uid,
+ percentTime,
+ profileTime,
+ mSamples[i].fSampleTime, // single sample
+ mSamples[i].fAccumulator ); // total sample
+ i++;
+ }
+}
+
+
+//==============================================================================
+// Profiler::BeginProfile
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void Profiler::BeginProfile( const char* name )
+{
+ int i;
+ tUID nameUID;
+
+ if( !sEnableCollection )
+ {
+ return;
+ }
+
+ i = 0;
+ nameUID = tEntity::MakeUID( name );
+
+ // If the sample is alread open this frame it will be in the store
+ ProfileSample *sample = mOpenSampleStore->Find(nameUID);
+
+ // Sample isn't in the store. Alloc a new one, set it up, and store it
+ if (sample == NULL)
+ {
+ sample = AllocSample();
+ rAssertMsg(sample != NULL, "Exceeded Maximum Available Profile Samples." );
+
+ sample->bValid = true;
+ sample->uid = nameUID;
+ sample->iProfileInstances = 0;
+ sample->fAccumulator = 0.0F;
+ sample->fChildrenSampleTime = 0.0F;
+ sample->fSampleTime = 0.0F;
+ sample->fTotalTime = 0.0F;
+ sample->iNumParents = 0;
+ sample->isOpen = false;
+
+ strncpy(sample->szName, name, 255);
+
+ mOpenSampleStore->Store(nameUID, sample);
+ }
+
+ rAssertMsg(!sample->isOpen, "Profiler section error: Started a second time without closing.");
+
+ sample->iProfileInstances++;
+ sample->isOpen = true;
+ sample->fStartTime = ((float)radTimeGetMicroseconds()) / 1000.0F;
+
+ // Ahh, pointer math.
+ unsigned sampleIndex = sample - mSamples;
+
+ // Add this sample to the open stack
+ rAssertMsg(mOpenStackTop < (MAX_PROFILER_DEPTH - 1), "Profiler error: Too many levels deep.");
+ ++mOpenStackTop;
+ mOpenStack[mOpenStackTop] = sampleIndex;
+}
+
+
+//==============================================================================
+// Profiler::EndProfile
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void Profiler::EndProfile( const char* name )
+{
+ tUID nameUID;
+
+ if( !sEnableCollection )
+ {
+ return;
+ }
+
+ nameUID = tEntity::MakeUID( name );
+
+ ProfileSample *sample = mOpenSampleStore->Find(nameUID);
+ rAssertMsg(sample != NULL, "Profiler error: Ending a section that isn't open.");
+ rAssertMsg(sample->isOpen, "Profiler error: Ending a section that isn't open.");
+
+ float endTime = ((float)radTimeGetMicroseconds()) / 1000.0F;
+ float duration = endTime - sample->fStartTime;
+
+ sample->isOpen = false;
+ sample->iNumParents = mOpenStackTop;
+ sample->fAccumulator += duration;
+ sample->fSampleTime = duration;
+
+ // Pop the stack
+ mOpenStackTop--;
+
+ // Only update the parent if there is one
+ if (mOpenStackTop > 0)
+ {
+ unsigned int parentIndex = mOpenStack[mOpenStackTop];
+ mSamples[parentIndex].fChildrenSampleTime += duration;
+ }
+}
+
+
+
+//==============================================================================
+// Profiler::Render
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void Profiler::Render(void)
+{
+ const int LEFT = 10;
+ const int TOP = 45;
+
+ if( !sDisplay )
+ {
+ return;
+ }
+
+ //int i = mScrollCount * NUM_VISIBLE_LINES;
+ unsigned int i = sPage * NUM_VISIBLE_LINES;
+
+ if( sDumpToOutput )
+ {
+ i = 0;
+ }
+
+ float startTime = ((float)radTimeGetMicroseconds()) / 1000.0F;
+
+ BEGIN_PROFILE("* Render Profile *")
+
+ //
+ // Display header info.
+ //
+ char fps[256];
+ sprintf(fps,"Game Time: %3.1f(fps) : %3.1f(ms) Adjusted Time: %3.1f(fps) : %3.1f(ms)", 1/(mFrameRate/1000), mFrameRate, 1/(mFrameRateAdjusted/1000), mFrameRateAdjusted);
+
+// const int SHADOW_OFFSET = 1;
+// tColour SHADOW_COLOUR(0,0,0);
+ tColour stringColour = tColour(sRed, sGreen, sBlue);
+/*
+ p3d::pddi->DrawString( fps,
+ LEFT + sLeftOffset + SHADOW_OFFSET,
+ TOP + sTopOffset + SHADOW_OFFSET,
+ SHADOW_COLOUR );
+
+ p3d::pddi->DrawString( "-------------------------------------------------------------------",
+ LEFT + sLeftOffset + SHADOW_OFFSET,
+ 20 + TOP + sTopOffset + SHADOW_OFFSET,
+ SHADOW_COLOUR);
+
+ p3d::pddi->DrawString( "Ave(%)\t| Single\t| #\t| Total\t| Profile Name\n",
+ LEFT + sLeftOffset + SHADOW_OFFSET,
+ 40 + TOP + sTopOffset + SHADOW_OFFSET,
+ SHADOW_COLOUR );
+
+ p3d::pddi->DrawString( "-------------------------------------------------------------------",
+ LEFT + sLeftOffset + SHADOW_OFFSET,
+ 60 + TOP + sTopOffset + SHADOW_OFFSET,
+ SHADOW_COLOUR);
+*/
+
+
+ p3d::pddi->DrawString( fps,
+ LEFT + sLeftOffset,
+ TOP + sTopOffset,
+ stringColour);
+
+ p3d::pddi->DrawString( "-------------------------------------------------------------------",
+ LEFT + sLeftOffset,
+ 20 + TOP + sTopOffset,
+ stringColour );
+
+ p3d::pddi->DrawString( "Ave(%)\t| Single\t| #\t| Total\t| Profile Name\n",
+ LEFT + sLeftOffset,
+ 40 + TOP + sTopOffset,
+ stringColour );
+
+ p3d::pddi->DrawString( "-------------------------------------------------------------------",
+ LEFT + sLeftOffset,
+ 60 + TOP + sTopOffset,
+ stringColour );
+
+ if( sDumpToOutput )
+ {
+ rTuneString( "-------------------------------------------------------------------------------\n" );
+ rTuneString( "Ave(%)\t| Single\t| #\t| Total\t| Profile Name\n" );
+ rTuneString( "-------------------------------------------------------------------------------\n" );
+ }
+
+ while( (i < mNextSampleAllocIndex) && mSamples[i].bValid )
+ {
+ unsigned int indent = 0;
+ float aveTime, minTime, maxTime, sampleAve, totalTime;
+ char line[256], name[256], indentedName[256];
+ char ave[32], min[32], max[32], num[32], sample[32], total[32];
+
+// this->GetProfileHistory( mSamples[i].szName, &aveTime, &minTime, &maxTime, &sampleAve, &totalTime);
+ this->GetProfileHistory( mSamples[i].uid, &aveTime, &minTime, &maxTime, &sampleAve, &totalTime);
+
+
+ // Format the data
+ sprintf( ave, "%3.2f", aveTime );
+ sprintf( min, "%3.2f", minTime );
+ sprintf( max, "%3.2f", maxTime );
+ sprintf( sample,"%3.2f", sampleAve );
+ sprintf( num, "%3d", mSamples[i].iProfileInstances );
+ sprintf( total, "%3.2f", totalTime );
+
+
+ strcpy( indentedName, mSamples[i].szName );
+
+
+ for( indent=0; indent<mSamples[i].iNumParents; indent++ )
+ {
+ sprintf( name, " %s", indentedName );
+ strcpy( indentedName, name );
+ }
+ sprintf(line,"%5s\t| %5s\t|%2s\t| %5s\t| %s ", ave, sample, num, total, indentedName);
+
+// p3d::pddi->DrawString( line,
+// LEFT + sLeftOffset + SHADOW_OFFSET,
+// 80 + TOP + ((i % NUM_VISIBLE_LINES)*20) + sTopOffset + SHADOW_OFFSET,
+// SHADOW_COLOUR);
+
+ p3d::pddi->DrawString( line,
+ LEFT + sLeftOffset,
+ 80 + TOP + ((i % NUM_VISIBLE_LINES)*20) + sTopOffset,
+ stringColour);
+
+ if( sDumpToOutput )
+ {
+ rTunePrintf( "%s\n", line );
+ }
+
+ i++;
+
+ if( i >= (unsigned int) (( sPage + 1 ) * NUM_VISIBLE_LINES ))
+ {
+ break;
+ }
+ }
+
+ END_PROFILE("* Render Profile *")
+
+ mDisplayTime = (((float)radTimeGetMicroseconds()) / 1000.0F) - startTime;
+
+ sDumpToOutput = false;
+}
+
+
+//==============================================================================
+// Profiler::Next
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void Profiler::NextPage()
+{
+ ++sPage;
+
+ if( sPage == NUM_VISIBLE_PANES )
+ {
+ sPage = 0;
+ }
+}
+
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// Profiler::Profiler
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================//
+Profiler::Profiler() :
+ mOpenStackTop( -1 ),
+ mStartProfile( 0.0F ),
+ mEndProfile( 0.0F ),
+ mFrameRate( 0.0f ),
+ mFrameRateAdjusted( 0.0f ),
+ mDisplayTime( 0.0F ),
+ mNextHistoryAllocIndex( 0 )
+{
+ int i;
+ for( i = 0; i < NUM_SAMPLES; ++i )
+ {
+ mSamples[i].bValid = false;
+ mSamples[i].iNumParents = 0;
+ }
+
+MEMTRACK_PUSH_GROUP( "Profiler" );
+
+ HeapMgr()->PushHeap( GMA_DEBUG );
+
+ mOpenSampleStore = new HashTable<ProfileSample>(NUM_SAMPLES * 2, 100, NUM_SAMPLES * 2);
+ mOpenHistoryStore = new HashTable<ProfileSampleHistory>(NUM_SAMPLES * 2, 100, NUM_SAMPLES * 2);
+
+ mOpenSampleStore->AddRef();
+ mOpenHistoryStore->AddRef();
+
+ HeapMgr()->PopHeap( GMA_DEBUG );
+
+MEMTRACK_POP_GROUP( "Profiler" );
+
+ radDbgWatchAddBoolean( &sDisplay, "Display", "Profiler", 0, 0 );
+ radDbgWatchAddInt( &sPage, "Select Page", "Profiler", 0, 0, 0, NUM_VISIBLE_PANES );
+ radDbgWatchAddInt( &sLeftOffset, "Left Position", "Profiler", 0, 0, -1000, 1000 );
+ radDbgWatchAddInt( &sTopOffset, "Top Position", "Profiler", 0, 0, -1000, 1000 );
+ radDbgWatchAddInt( &sRed, "Text Colour - Red", "Profiler", 0, 0, 0, 255 );
+ radDbgWatchAddInt( &sGreen, "Text Colour - Green", "Profiler", 0, 0, 0, 255 );
+ radDbgWatchAddInt( &sBlue, "Text Colour - Blue", "Profiler", 0, 0, 0, 255 );
+ radDbgWatchAddBoolean( &sDumpToOutput, "Dump to Output Window", "Profiler", 0, 0 );
+}
+
+
+//==============================================================================
+// Profiler::~Profiler
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================//
+Profiler::~Profiler()
+{
+}
+
+
+//==============================================================================
+// Profiler::StoreProfileHistory
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void Profiler::StoreProfileHistory
+(
+// char* name,
+ tUID nameUID,
+ float percent,
+ float elapsedTime,
+ float sampleTime,
+ float totalTime
+)
+{
+ float oldRatio;
+ float newRatio = 0.8f * (elapsedTime / 1000.0f);
+
+ if( newRatio > 1.0f )
+ {
+ newRatio = 1.0f;
+ }
+ oldRatio = 1.0f - newRatio;
+
+ mFrameRate = (mFrameRate * oldRatio) + (elapsedTime * newRatio);
+
+ // TODO: I had to put this in because there are cases where elapsedTime
+ // is 0 and mDisplayTime isn't... How can that happen?
+ //
+ float adjustedTime = 0.0F;
+
+ if( elapsedTime >= mDisplayTime )
+ {
+ adjustedTime = elapsedTime - mDisplayTime;
+ }
+
+ mFrameRateAdjusted = (mFrameRateAdjusted*oldRatio) + (adjustedTime * newRatio);
+
+ ProfileSampleHistory *history = mOpenHistoryStore->Find(nameUID);
+ if (history == NULL)
+ {
+ history = AllocHistory();
+ rAssertMsg(history != NULL, "Too many profiler histories.");
+
+ history->uid = nameUID;
+ history->fAve = percent;
+ history->fMin = percent;
+ history->fMax = percent;
+ history->fSampleAve = sampleTime;
+ history->fSampleTotal = totalTime;
+
+ mOpenHistoryStore->Store(nameUID, history);
+ }
+ else
+ {
+ history->fAve = (history->fAve * oldRatio) + (percent * newRatio);
+ history->fSampleAve = (history->fSampleAve * oldRatio) + (sampleTime * newRatio);
+ history->fSampleTotal = (history->fSampleTotal * oldRatio) + (totalTime * newRatio);
+
+ if( percent < history->fMin ) history->fMin = percent;
+ else history->fMin = (history->fMin * oldRatio) + (percent * newRatio);
+
+ if( history->fMin < 0.0f ) history->fMin = 0.0f;
+
+ if( percent > history->fMax ) history->fMax = percent;
+ else history->fMax = (history->fMax * oldRatio) + (percent * newRatio);
+ }
+
+}
+
+
+//==============================================================================
+// Profiler::GetProfileHistory
+//==============================================================================
+//
+// Description:
+//
+// Parameters:
+//
+// Return:
+//
+//==============================================================================
+void Profiler::GetProfileHistory
+(
+// char* name,
+ tUID nameUID,
+ float* ave,
+ float* min,
+ float* max,
+ float* sample,
+ float* total
+)
+{
+ *ave = *min = *max = *sample = 0.0f;
+
+ ProfileSampleHistory *history = mOpenHistoryStore->Find(nameUID);
+ //rAssertMsg(history != NULL, "Get Profile history Error: Never been stored!");
+
+ if (history != NULL)
+ {
+ *ave = history->fAve;
+ *min = history->fMin;
+ *max = history->fMax;
+ *sample = history->fSampleAve;
+ *total = history->fSampleTotal;
+ }
+}
+
+
+#endif // PROFILER_ENABLED \ No newline at end of file
diff --git a/game/code/debug/profiler.h b/game/code/debug/profiler.h
new file mode 100644
index 0000000..ba61ff1
--- /dev/null
+++ b/game/code/debug/profiler.h
@@ -0,0 +1,206 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: profiler.h
+//
+// Description: In-game profiler.
+//
+// History: 5/8/2002 + Migrated from SRR -- Darwin Chau
+//
+//=============================================================================
+
+#ifndef PROFILER_H
+#define PROFILER_H
+
+//========================================
+// Nested Includes
+//========================================
+
+//========================================
+// Forward References
+//========================================
+
+#if !defined( RAD_RELEASE ) && !defined( WORLD_BUILDER ) && !defined( RAD_MW ) && !defined( RAD_WIN32 )
+ #define PROFILER_ENABLED
+#endif // RAD_RELEASE
+
+
+#include "main/commandlineoptions.h"
+
+#include <p3d/entity.hpp>
+#include <radload/utility/hashtable.hpp>
+
+//===========================================================================
+// *** USE THESE MACROS, DO NOT INVOKE PROFILER DIRECTLY ***
+//===========================================================================
+
+
+#ifndef PROFILER_ENABLED
+
+ #define CREATE_PROFILER()
+ #define DESTROY_PROFILER()
+
+ #define BEGIN_PROFILE(string)
+ #define END_PROFILE(string)
+
+ #define BEGIN_PROFILER_FRAME()
+ #define END_PROFILER_FRAME()
+
+ #define RENDER_PROFILER()
+
+ #define SNSTART(id, txt)
+ #define SNSTOP(id)
+
+#else
+
+#ifdef SNTUNER
+#include <SNTuner.h>
+ #define SNSTART(id, txt) snStartMarker(id, txt)
+ #define SNSTOP(id) snStopMarker(id);
+#endif
+
+ #define CREATE_PROFILER() if(!(CommandLineOptions::Get(CLO_DESIGNER) || CommandLineOptions::Get(CLO_FIREWIRE))) { Profiler::CreateInstance(); }
+ #define DESTROY_PROFILER() if(!(CommandLineOptions::Get(CLO_DESIGNER) || CommandLineOptions::Get(CLO_FIREWIRE))) { Profiler::DestroyInstance(); }
+
+ #define BEGIN_PROFILE(string) if(!(CommandLineOptions::Get(CLO_DESIGNER) || CommandLineOptions::Get(CLO_FIREWIRE))) { GetProfiler()->BeginProfile(string); }
+ #define END_PROFILE(string) if(!(CommandLineOptions::Get(CLO_DESIGNER) || CommandLineOptions::Get(CLO_FIREWIRE))) { GetProfiler()->EndProfile(string); }
+
+ #define BEGIN_PROFILER_FRAME() if(!(CommandLineOptions::Get(CLO_DESIGNER) || CommandLineOptions::Get(CLO_FIREWIRE))) { GetProfiler()->BeginFrame(); }
+ #define END_PROFILER_FRAME() if(!(CommandLineOptions::Get(CLO_DESIGNER) || CommandLineOptions::Get(CLO_FIREWIRE))) { GetProfiler()->EndFrame(); }
+
+ #define RENDER_PROFILER() if(!(CommandLineOptions::Get(CLO_DESIGNER) || CommandLineOptions::Get(CLO_FIREWIRE))) { GetProfiler()->Render(); }
+
+
+#define MAX_PROFILER_DEPTH 32
+
+//===========================================================================
+//
+// Description: Generally, describe what behaviour this class possesses that
+// clients can rely on, and the actions that this service
+// guarantees to clients.
+//
+// Constraints: Describe here what you require of the client which uses or
+// has this class - essentially, the converse of the description
+// above. A constraint is an expression of some semantic
+// condition that must be preserved, an invariant of a class or
+// relationship that must be preserved while the system is in a
+// steady state.
+//
+//===========================================================================
+class Profiler
+{
+ public:
+
+ static Profiler* CreateInstance();
+ static Profiler* GetInstance();
+ static void DestroyInstance();
+
+ void Init();
+
+ void BeginProfile( const char* name );
+ void EndProfile( const char* name );
+
+ void BeginFrame();
+ void EndFrame();
+
+ void ToggleDisplay() { sDisplay = !sDisplay; }
+ void NextPage();
+
+ void Render();
+
+ //
+ // Watcher tunable
+ //
+ static int sRed;
+ static int sGreen;
+ static int sBlue;
+ static int sPage;
+ static int sLeftOffset;
+ static int sTopOffset;
+ static bool sDisplay;
+ static bool sDumpToOutput;
+
+ private:
+
+
+ Profiler();
+ ~Profiler();
+
+
+ void StoreProfileHistory( tUID nameUID,
+ float percent,
+ float elapsedTime,
+ float sampleTime,
+ float totalTime );
+
+ void GetProfileHistory( tUID nameUID,
+ float* ave,
+ float* min,
+ float* max ,
+ float* sample,
+ float* total );
+ struct ProfileSample
+ {
+ bool bValid; // Whether the data is valid
+ tUID uid; // Hashed name for comparisons.
+ unsigned int iProfileInstances; // # of times ProfileBegin called
+ float fStartTime; // The current open profile start time
+ float fAccumulator; // All samples this frame added together
+ float fChildrenSampleTime; // Time taken by all children
+ float fSampleTime; // Time for a single pass
+ float fTotalTime; // Time for all passess
+ unsigned int iNumParents; // Number of profile parents
+ bool isOpen; // Is the profile section open?
+ char szName[256]; // Name of sample
+ };
+
+ struct ProfileSampleHistory
+ {
+ tUID uid; //Hased name for comparisons
+ float fAve; //Average time per frame (percentage)
+ float fMin; //Minimum time per frame (percentage)
+ float fMax; //Maximum time per frame (percentage)
+ float fSampleAve;
+ float fSampleTotal;
+ };
+
+ static Profiler* spInstance;
+
+ ProfileSample *AllocSample(void);
+ ProfileSampleHistory *AllocHistory(void);
+
+ enum
+ {
+ NUM_SAMPLES = 256, // Must be power of two for hash table
+ NUM_VISIBLE_LINES = 15,
+ NUM_VISIBLE_PANES = 1 + ((NUM_SAMPLES-1) / NUM_VISIBLE_LINES )
+ };
+
+ HashTable<ProfileSample> *mOpenSampleStore;
+ HashTable<ProfileSampleHistory> *mOpenHistoryStore;
+
+ ProfileSample mSamples[NUM_SAMPLES];
+ ProfileSampleHistory mHistory[NUM_SAMPLES];
+
+ unsigned int mOpenStack[MAX_PROFILER_DEPTH];
+ int mOpenStackTop;
+
+ float mStartProfile;
+ float mEndProfile;
+
+ float mFrameRate;
+ float mFrameRateAdjusted;
+
+ float mDisplayTime;
+ unsigned int mNextSampleAllocIndex;
+ unsigned int mNextHistoryAllocIndex;
+
+ static bool sEnableCollection;
+};
+
+// A little syntactic sugar for getting at this singleton.
+inline Profiler* GetProfiler() { return( Profiler::GetInstance() ); }
+
+#endif // PROFILER_ENABLED
+
+#endif // PROFILER_H \ No newline at end of file
diff --git a/game/code/debug/ps2perf.hpp b/game/code/debug/ps2perf.hpp
new file mode 100644
index 0000000..562b4bf
--- /dev/null
+++ b/game/code/debug/ps2perf.hpp
@@ -0,0 +1,263 @@
+// Performance counter class for PS2
+// Nov 2001 - Amit Bakshi
+
+#ifndef PS2PERF_HPP
+#define PS2PERF_HPP
+
+/************************************************************************************/
+// nov6/2001 amb - Performance Counter class
+// based on David Coombes' (david_coombes@playstation.sony.com) code
+// sample usage :
+//
+// void TestSinCos()
+// {
+// ps2Perf perf("mySinCos");
+//
+// for(int i =0; i < 16; i++)
+// {
+// perf.StartSample();
+//
+// float s,c;
+// mySinCos( i, &s , &c );
+//
+// perf.EndSample();
+// }
+// perf.PrintStats();
+// };
+/************************************************************************************/
+
+#define ClocksToMs 294912
+
+inline unsigned int GetCycleCounter(void)
+{
+ unsigned int ret;
+ asm __volatile__ ("mfc0 %0,$9" : "=r" (ret) );
+ return ret;
+}
+
+// amb nov6/2001 - caution : do not call in middle of the code,
+// it'll mess up PDDI stats
+inline void ResetCycleCounter(void)
+{
+ asm __volatile__ ("mtc0 $0,$9 ");
+};
+
+
+class ps2Perf
+{
+public:
+
+ ps2Perf(const char* what)
+ {
+ strncpy( desc,what,sizeof(desc)-1);
+ Reset();
+ };
+
+ ~ps2Perf()
+ {
+ asm __volatile__ ("mtps $0,0");
+ };
+
+ inline void Reset()
+ {
+ count = 0;
+ for(int i = 0; i < PC0_NO_EVENT; i++)
+ {
+ pc0[i].min = pc1[i].min = 0xffff;
+ pc0[i].max = pc1[i].max = 0;
+ pc0[i].cur = pc1[i].cur = 0;
+ pc0[i].tot = pc1[i].tot = 0;
+ pc0[i].num = pc1[i].num = 0;
+ }
+ }
+
+ inline void BeginSample()
+ {
+ int evt = count % PC0_NO_EVENT;
+ BeginSample(evt);
+ };
+
+ inline void BeginSample(int evt)
+ {
+ pccr.cl0 = 0x8; // only user mode
+ pccr.event0 = evt;
+ pccr.cl1 = 0x8;
+ pccr.event1 = evt;
+ pccr.cte = 1;
+
+ int hack = *((int*)(&pccr));
+
+ asm __volatile__("
+ .set noreorder
+ .set noat
+ mtps $0,0 # halt performance counters
+ sync.p #
+ mtpc $0,0 # set perfcounter 0 to zero
+ mtpc $0,1 # set perfcounter 1 to zero
+ sync.p #
+ mtps %0,0 # truly - we rule ( well stewart does anyway...)
+ .set reorder
+ .set at
+ "
+ : // no output
+ : "r"(hack)
+ );
+ }
+ inline void EndSample()
+ {
+ int evt = count % PC0_NO_EVENT;
+ EndSample(evt);
+ count++;
+ };
+
+ inline void EndSample(int evt)
+ {
+ register unsigned int ret_pc0=0;
+ register unsigned int ret_pc1=0;
+
+ asm __volatile__("
+ .set noreorder
+ .set noat
+ mfpc %0,0
+ mfpc %1,1
+ .set reorder
+ .set at
+ ":"=r"(ret_pc0),"=r"(ret_pc1));
+
+ if(ret_pc0<pc0[evt].min) pc0[evt].min = ret_pc0;
+ if(ret_pc0>pc0[evt].max) pc0[evt].max = ret_pc0;
+ pc0[evt].cur = ret_pc0;
+ pc0[evt].tot+= ret_pc0;
+ pc0[evt].num++;
+
+ if(ret_pc1<pc1[evt].min) pc1[evt].min = ret_pc1;
+ if(ret_pc1>pc1[evt].max) pc1[evt].max = ret_pc1;
+ pc1[evt].cur = ret_pc1;
+ pc1[evt].tot+= ret_pc1;
+ pc1[evt].num++;
+
+ asm __volatile__ ("mtps $0,0");
+ };
+
+ inline void StopCounters()
+ {
+ asm __volatile__ ("mtps $0,0");
+ }
+
+ void PrintStats()
+ {
+ #define PRINT_STAT_0(desc,i) if (pc0[i].num) printf(desc "%6d, %6d, %6d, %6d\n",pc0[i].min, pc0[i].max, pc0[i].cur, pc0[i].tot/pc0[i].num);
+ #define PRINT_STAT_1(desc,i) if (pc1[i].num) printf(desc "%6d, %6d, %6d, %6d\n",pc1[i].min, pc1[i].max, pc1[i].cur, pc1[i].tot/pc1[i].num);
+
+ printf("==== %s ====(total iterations)%d (per event)%d (frame%%) ===========\n",desc,count,(count/PC0_NO_EVENT));
+ printf("Event , min, max, cur, ave \n");
+
+ PRINT_STAT_0("Processor cycle ,", 1 );
+ PRINT_STAT_0("Single instructions issue ,", 2 );
+ PRINT_STAT_0("Branch issued ,", 3 );
+ PRINT_STAT_0("BTAC miss ,", 4 );
+ PRINT_STAT_0("ITLB miss ,", 5 );
+ PRINT_STAT_0("Instruction cache miss ,", 6 );
+ PRINT_STAT_0("DTLB accessed ,", 7 );
+ PRINT_STAT_0("Non-blocking load ,", 8 );
+ PRINT_STAT_0("WBB single request ,", 9 );
+ PRINT_STAT_0("WBB burst request ,",10 );
+ PRINT_STAT_0("CPU address bus busy ,",11 );
+ PRINT_STAT_0("Instruction completed ,",12 );
+ PRINT_STAT_0("Non-BDS instruction completed ,",13 );
+ PRINT_STAT_0("COP2 instruction completed ,",14 );
+ PRINT_STAT_0("Load completed ,",15 );
+
+ PRINT_STAT_1("Low-order branch issued ,", 0 );
+ PRINT_STAT_1("Processor cycle ,", 1 );
+ PRINT_STAT_1("Dual instructions issue ,", 2 );
+ PRINT_STAT_1("Branch miss-predicted ,", 3 );
+ PRINT_STAT_1("TLB miss ,", 4 );
+ PRINT_STAT_1("DTLB miss ,", 5 );
+ PRINT_STAT_1("Data cache miss ,", 6 );
+ PRINT_STAT_1("WBB single request unavailable,", 7 );
+ PRINT_STAT_1("WBB burst request unavailable ,", 8 );
+ PRINT_STAT_1("WBB burst request almost full ,", 9 );
+ PRINT_STAT_1("WBB burst request full ,",10 );
+ PRINT_STAT_1("CPU data bus busy ,",11 );
+ PRINT_STAT_1("Instruction completed ,",12 );
+ PRINT_STAT_1("Non-BDS instruction completed ,",13 );
+ PRINT_STAT_1("COP1 instruction completed ,",14 );
+ PRINT_STAT_1("Store completed ,",15 );
+
+ #undef PRINT_STAT_0
+ #undef PRINT_STAT_1
+
+ }
+
+private:
+ enum PCOUNT0_EVENT // Performance Counter 0 Events
+ {
+ PC0_RESERVED =(0 ),
+ PC0_CPU_CYCLE =(1 ), // Processor cycle
+ PC0_SINGLE_ISSUE =(2 ), // Single instructions issue
+ PC0_BRANCH_ISSUED =(3 ), // Branch issued
+ PC0_BTAC_MISS =(4 ), // BTAC miss
+ PC0_ITLB_MISS =(5 ), // ITLB miss
+ PC0_ICACHE_MISS =(6 ), // Instruction cache miss
+ PC0_DTLB_ACCESSED =(7 ), // DTLB accessed
+ PC0_NONBLOCK_LOAD =(8 ), // Non-blocking load
+ PC0_WBB_SINGLE_REQ =(9 ), // WBB single request
+ PC0_WBB_BURST_REQ =(10), // WBB burst request
+ PC0_ADDR_BUS_BUSY =(11), // CPU address bus busy
+ PC0_INST_COMP =(12), // Instruction completed
+ PC0_NON_BDS_COMP =(13), // Non-BDS instruction completed
+ PC0_COP2_COMP =(14), // COP2 instruction completed
+ PC0_LOAD_COMP =(15), // Load completed
+ PC0_NO_EVENT =(16) // No event
+ };
+
+ enum PCOUNT1_EVENT // Performance Counter 1 Events
+ {
+ PC1_LOW_BRANCH_ISSUED =(0 ), // Low-order branch issued
+ PC1_CPU_CYCLE =(1 ), // Processor cycle
+ PC1_DUAL_ISSUE =(2 ), // Dual instructions issue
+ PC1_BRANCH_MISS_PREDICT =(3 ), // Branch miss-predicted
+ PC1_TLB_MISS =(4 ), // TLB miss
+ PC1_DTLB_MISS =(5 ), // DTLB miss
+ PC1_DCACHE_MISS =(6 ), // Data cache miss
+ PC1_WBB_SINGLE_UNAVAIL =(7 ), // WBB single request unavailable
+ PC1_WBB_BURST_UNAVAIL =(8 ), // WBB burst request unavailable
+ PC1_WBB_BURST_ALMOST =(9 ), // WBB burst request almost full
+ PC1_WBB_BURST_FULL =(10), // WBB burst request full
+ PC1_DATA_BUS_BUSY =(11), // CPU data bus busy
+ PC1_INST_COMP =(12), // Instruction completed
+ PC1_NON_BDS_COMP =(13), // Non-BDS instruction completed
+ PC1_COP1_COMP =(14), // COP1 instruction completed
+ PC1_STORE_COMP =(15), // Store completed
+ PC1_NO_EVENT =(16) // No event
+ };
+
+ struct count_t
+ {
+ unsigned int min,max,tot,cur,num;
+ };
+
+ // nov6/2001 amb - see p82 EE Core User's Manual 4.0
+ struct pccr_t
+ {
+ unsigned pad0:1; // unused
+ unsigned cl0:4; // events in which mode (eg user/kernel/super/exception)
+ unsigned event0:5; // event to count in counter 0 (see PCOUNT0_EVENT)
+ unsigned pad1:1; // unused
+ unsigned cl1:4; // events in which mode (eg user/kernel/super/exception)
+ unsigned event1:5; // event to count in counter 1 (see PCOUNT1_EVENT)
+ unsigned pad2:11; // unused
+ unsigned cte:1; // counter enable
+ };
+
+ char desc[32];
+
+ pccr_t pccr; // 16 events
+
+ count_t pc0[PC0_NO_EVENT];
+ count_t pc1[PC0_NO_EVENT];
+ unsigned int count;
+};
+
+#endif // PS2PERF_HPP
diff --git a/game/code/debug/section.cpp b/game/code/debug/section.cpp
new file mode 100644
index 0000000..d87379e
--- /dev/null
+++ b/game/code/debug/section.cpp
@@ -0,0 +1,236 @@
+#include <debug/section.h>
+#include <p3d/matrixstack.hpp>
+#include <p3d/utility.hpp>
+
+Section::Section(tFont* pFont, const char* szName) :
+ _pDebugFont(pFont),
+ _pLineShader(NULL),
+ _autoReset(true)
+{
+ assert(szName);
+
+ int i;
+
+ Reset(szName);
+
+ _pLineShader = p3d::device->NewShader(/*p3d::pddi, */"simple");
+ _pLineShader->AddRef();
+ _pLineShader->SetInt(PDDI_SP_BLENDMODE, PDDI_BLEND_ALPHA);
+
+ //Allocate string primitives for the 3d strings
+ for(i=0;i<MaxText;i++)
+ {
+ if(_pDebugFont)
+ {
+ _pDebugFont->AddRef();
+
+ P3D_UNICODE string[256];
+ char emptyString[] = "Empty String";
+ p3d::AsciiToUnicode(emptyString, string, strlen(emptyString));
+
+ _pText[i]._pText = new tTextString(_pDebugFont, string);
+ _pText[i]._pText->AddRef();
+ }
+ else
+ {
+ _pText[i]._pText = NULL;
+ }
+ }
+}
+Section::~Section()
+{
+ for(int i=0;i<MaxText;i++)
+ {
+ tRefCounted::Release(_pText[i]._pText);
+ }
+
+ tRefCounted::Release(_pLineShader);
+ tRefCounted::Release(_pDebugFont);
+}
+
+void Section::Reset(const char *szName)
+{
+ assert(szName);
+ strncpy(_szName, szName, sizeof(_szName));
+
+ _NumLines = _NumText = _NumScreenLines = _NumScreenText = 0;
+ ClearScreenText();
+}
+
+const char* Section::GetName() const
+{
+
+ return _szName;
+}
+
+void Section::AddLine(const rmt::Vector& a, const rmt::Vector& b, tColour colour/*, float time*/)
+{
+ if(_NumLines < MaxLines)
+ {
+ _Lines[_NumLines]._a = a;
+ _Lines[_NumLines]._b = b;
+ _Lines[_NumLines]._Colour = colour;
+ _NumLines++;
+ }
+}
+
+void Section::AddText(const char *szName, const rmt::Vector &pos, tColour colour/*, float time = 0*/)
+{
+ assert(szName);
+ if(_NumText < MaxText && _pText[_NumText]._pText)
+ {
+ tTextString* p = _pText[_NumText]._pText;
+
+ P3D_UNICODE string[256];
+ p3d::AsciiToUnicode(szName, string, strlen(szName));
+
+ p->SetString(string);
+ p->SetColour(colour);
+ p->SetScale(20.0f); //Fudge factor to make font appear about 1 meter high
+ _pText[_NumText]._Pos = pos;
+ _NumText++;
+ }
+}
+
+void Section::AddScreenLine(const rmt::Vector &a, const rmt::Vector &b, tColour colour)
+{
+ if(_NumScreenLines < MaxScreenLines)
+ {
+ _ScreenLines[_NumScreenLines]._a = a;
+ _ScreenLines[_NumScreenLines]._b = b;
+ _ScreenLines[_NumScreenLines]._Colour = colour;
+ _NumScreenLines++;
+ }
+}
+
+void Section::AddScreenText(const char* szName, tColour colour )
+{
+ assert(szName);
+ ScreenText &pST = _pScreenText[_NumScreenText];
+
+ if(_NumScreenText<MaxScreenText && pST._pText)
+ {
+ strncpy(pST._pText, szName, sizeof(pST._pText));
+ pST._Colour = colour;
+ pST._Pos = rmt::Vector(0.05f,_ScreenTextPos, 0);
+
+ //TODO:get correct debug font height!
+ _ScreenTextPos += 0.03f;
+ _NumScreenText++;
+ }
+}
+void Section::AddScreenText(const char* szName, const rmt::Vector &a, tColour colour)
+{
+ assert(szName);
+ ScreenText &pST = _pScreenText[_NumScreenText];
+
+ if(_NumScreenText<MaxScreenText && pST._pText)
+ {
+ if(pST._pText)
+ strncpy(pST._pText, szName, sizeof(pST._pText));
+ pST._Colour = colour;
+ pST._Pos = a;
+ _NumScreenText++;
+ }
+}
+
+void Section::ClearScreenText()
+{
+ _NumScreenText = 0;
+ _ScreenTextPos = 0.15f;
+}
+
+void Section::Render()
+{
+ pddiPrimStream* pStream;
+ int i;
+ assert(_pLineShader);
+
+ //Special case to get the pddi debugging information
+ p3d::pddi->EnableStatsOverlay(0==strcmp(_szName, "pddi"));
+
+ //Stream out world space lines
+ if(_NumLines > 0)
+ {
+ pStream = p3d::pddi->BeginPrims(_pLineShader, PDDI_PRIM_LINES, PDDI_V_C, _NumLines*2);
+ if(pStream)
+ {
+ for(i=0; i<_NumLines; i++)
+ {
+ Line &l = _Lines[i];
+
+ pddiVector A(l._a.x, l._a.y, l._a.z);
+ pddiVector B(l._b.x, l._b.y, l._b.z);
+ pStream->Vertex(&A,l._Colour);
+ pStream->Vertex(&B,l._Colour);
+ }
+ }
+ p3d::pddi->EndPrims(pStream);
+ }
+
+ //Draw all the world space vector text
+ for(i=0;i<_NumText;i++)
+ {
+ p3d::stack->Push();
+ p3d::stack->Translate(_pText[i]._Pos);
+ _pText[i]._pText->Display();
+ p3d::stack->Pop();
+ }
+
+ //Draw screen space lines
+ {
+ //Setup the matrix stack
+ p3d::stack->Push();
+ p3d::pddi->EnableZBuffer(false);
+ p3d::stack->LoadIdentity();
+ p3d::stack->Scale((float)p3d::display->GetWidth(),(float)p3d::display->GetHeight(),1);
+ p3d::pddi->SetProjectionMode(PDDI_PROJECTION_DEVICE);
+
+ //Stream out lines
+ if(_NumScreenLines > 0)
+ {
+ pStream = p3d::pddi->BeginPrims(_pLineShader, PDDI_PRIM_LINES, PDDI_V_C, _NumScreenLines*2);
+ if(pStream)
+ {
+ for(i=0; i<_NumScreenLines; i++)
+ {
+ Line &l = _ScreenLines[i];
+
+ pddiVector A(l._a.x, l._a.y, 1);
+ pddiVector B(l._b.x, l._b.y, 1);
+ pStream->Vertex(&A,l._Colour);
+ pStream->Vertex(&B,l._Colour);
+ }
+ }
+ p3d::pddi->EndPrims(pStream);
+ }
+
+ //Restore the old stack
+ p3d::pddi->SetProjectionMode(PDDI_PROJECTION_PERSPECTIVE);
+ p3d::pddi->EnableZBuffer(true);
+ p3d::stack->Pop();
+ }
+
+ //Draw all the screen text
+ p3d::stack->Push();
+ p3d::stack->LoadIdentity();
+ int height = p3d::display->GetHeight();
+ int width = p3d::display->GetWidth();
+
+ for(i=0;i<_NumScreenText;i++)
+ {
+ ScreenText &pST = _pScreenText[i];
+ if(pST._pText)
+ {
+
+ p3d::pddi->DrawString(pST._pText,
+ (int)(pST._Pos.x*width),
+ (int)(pST._Pos.y*height),
+ pST._Colour);
+
+ }
+ }
+
+ p3d::stack->Pop();
+}
+
diff --git a/game/code/debug/section.h b/game/code/debug/section.h
new file mode 100644
index 0000000..85547ba
--- /dev/null
+++ b/game/code/debug/section.h
@@ -0,0 +1,108 @@
+
+
+#if 1
+
+#ifndef _SECTION_HPP
+#define _SECTION_HPP
+
+#include <p3d/textstring.hpp>
+#include <p3d/font.hpp>
+#include <pddi/pddi.hpp>
+#include <radmath/radmath.hpp>
+
+// TODO: move this to internal namespace
+
+/**
+ * Section.
+ */
+class Section
+{
+public:
+ /** Constructor
+ * @param sectionName name of the section
+ */
+ Section(tFont* pFont, const char* sectionName);
+
+ /** Destructor */
+ ~Section();
+
+ void SetAutoReset(bool autoReset) { _autoReset = autoReset; }
+ bool GetAutoReset() { return _autoReset; }
+
+ void Reset(const char *name);
+ void ClearScreenText();
+ void Render();
+
+ const char* GetName() const;
+
+ //Debugging output functions
+ void AddLine(const rmt::Vector &a, const rmt::Vector &b, tColour colour);
+ void AddText(const char *szName, const rmt::Vector &pos, tColour colour);
+
+ //Output functions for screen space primitives
+ //All screen space is in x=[0..1], y=[0..1], with (0,0) at the top left
+ void AddScreenLine(const rmt::Vector &a, const rmt::Vector &b, tColour colour);
+ void AddScreenText(const char* szName, tColour colour);
+ void AddScreenText(const char* szName, const rmt::Vector &a, tColour colour);
+
+private:
+ struct Line
+ {
+ rmt::Vector _a;
+ rmt::Vector _b;
+ tColour _Colour;
+ };
+
+ struct ScreenText
+ {
+ enum { MaxTextSize = 256 };
+
+ tColour _Colour;
+ char _pText[MaxTextSize];
+ rmt::Vector _Pos;
+ };
+
+ struct VectorText
+ {
+ tTextString* _pText;
+ rmt::Vector _Pos;
+ };
+
+
+private:
+ char _szName[256];
+
+ tFont* _pDebugFont;
+
+ float _ScreenTextPos;
+
+ pddiShader* _pLineShader;
+
+ int _NumLines;
+ enum { MaxLines = 50 };
+ Line _Lines[MaxLines];
+
+ int _NumScreenLines;
+ enum { MaxScreenLines = 50 };
+ Line _ScreenLines[MaxScreenLines];
+
+ int _NumText;
+ enum { MaxText = 50 };
+ VectorText _pText[MaxText];
+
+ int _NumScreenText;
+ enum { MaxScreenText = 50 };
+ ScreenText _pScreenText[MaxScreenText];
+
+ bool _autoReset;
+
+//denied
+private:
+ Section();//don't use default constructor
+};
+
+
+#endif
+
+
+#endif