diff -r 7cab3d43a9b7 lib/irrlicht/include/IrrCompileConfig.h
--- a/lib/irrlicht/include/IrrCompileConfig.h	Tue Sep 02 00:54:04 2008 +0200
+++ b/lib/irrlicht/include/IrrCompileConfig.h	Tue Sep 02 13:28:56 2008 +0200
@@ -159,6 +159,8 @@
 	This is only used when _IRR_COMPILE_WITH_LIBPNG_ is defined. */
 #define _IRR_USE_NON_SYSTEM_LIB_PNG_
 
+//! Set IRR_PROFILE to 1 to enable or 0 to disable the profiling code
+#define IRR_PROFILE	1
 
 //! Define _IRR_D3D_NO_SHADER_DEBUGGING to disable shader debugging in D3D9
 /** If _IRR_D3D_NO_SHADER_DEBUGGING is undefined in IrrCompileConfig.h,
diff -r 7cab3d43a9b7 lib/irrlicht/include/irrlicht.h
--- a/lib/irrlicht/include/irrlicht.h	Tue Sep 02 00:54:04 2008 +0200
+++ b/lib/irrlicht/include/irrlicht.h	Tue Sep 02 13:28:56 2008 +0200
@@ -32,6 +32,7 @@
 #include "IrrCompileConfig.h"
 #include "aabbox3d.h"
 #include "coreutil.h"
+#include "profiler.h"
 #include "irrArray.h"
 #include "irrMap.h"
 #include "irrMath.h"
diff -r 7cab3d43a9b7 lib/irrlicht/include/profiler.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irrlicht/include/profiler.h	Tue Sep 02 13:28:56 2008 +0200
@@ -0,0 +1,463 @@
+#ifndef __PROFILER_H_INCLUDED__
+#define __PROFILER_H_INCLUDED__
+
+#include "IrrCompileConfig.h"
+#include "irrTypes.h"
+#include "rect.h"
+#include "irrString.h"
+#include "irrArray.h"
+#include "ITimer.h"
+#include "IGUIEnvironment.h"
+#include "IGUIListBox.h"
+#include <limits.h>
+
+namespace irr
+{
+struct ProfileData
+{
+	friend class Profiler;
+
+    ProfileData()
+	{
+		GroupId = 0;
+		reset();
+	}
+
+	bool operator<(const ProfileData& pd) const
+	{
+		return Id < pd.Id;
+	}
+
+private:
+	ProfileData(u32 id)	: Id(id) {}	// just to be used for searching
+
+	void reset()
+	{
+		CountCalls = 0;
+		HighestTime = 0;
+		LowestTime = UINT_MAX;
+		TimeSum = 0;
+		LastTimeStarted = 0;
+	}
+
+	u32 Id;
+    u32 GroupId;
+	core::stringw Name;
+
+    u32 CountCalls;
+    u32 HighestTime;
+    u32 LowestTime;
+    u32 TimeSum;
+
+    u32 LastTimeStarted;
+};
+
+class Profiler
+{
+public:
+    Profiler()
+	: IrrTimer(0)
+	, GuiID(-1)
+	, DisplayRect(20, 20, 600, 400)		
+	, OverviewGroupId(0)
+	{
+		addGroup(OverviewGroupId, "overview");
+		ProfileGroups[0].GroupId = UINT_MAX;	// overview does not belong to itself so it does not get printed on printAll
+		CurrentGroupId = OverviewGroupId;
+	}
+
+	virtual ~Profiler()
+	{
+	}
+
+    void init(irr::ITimer * irrlichtTimer, s32 guiId)   
+	{ 
+		IrrTimer = irrlichtTimer; 
+		GuiID = guiId;
+	}
+
+    // set the rectangle used for the display listbox
+    void setDisplayRect(const core::rect<s32> &rect_)   
+	{ 
+		DisplayRect = rect_; 
+	}
+
+    inline void add(u32 id_, u32 groupId_, const core::stringw &name_);
+    inline void addGroup(u32 groupId_, const core::stringw &name_);
+
+	inline void start(u32 id_);
+    inline void stop(u32 id_);
+
+    inline void reset(u32 id_);
+    inline void resetGroup(u32 groupId_);
+    inline void resetAll();
+    inline void show(gui::IGUIEnvironment* env_);        // print current display group on screen
+    inline void hide(gui::IGUIEnvironment* env_);
+	inline void print(core::stringw &ostream, bool suppressUncalled_=true);       // write current display group into string
+    inline void printAll(core::stringw &ostream, bool includeOverview=false,bool suppressUncalled_=true);    // write all groups itno string
+
+    inline void setDisplayGroup(u32 groupId_);
+    inline void nextDisplayGroup();
+    inline void previousDisplayGroup();
+    inline void firstDisplayGroup();
+
+protected:
+    inline void printGroup(core::stringw &ostream, u32 groupId_, bool suppressUncalled_);
+    inline core::stringw makeDataString(const ProfileData & data_);
+    inline core::stringw makeTitleString();
+
+private:
+    irr::ITimer * IrrTimer;
+	s32 GuiID;
+    core::rect<s32> DisplayRect;
+	u32 OverviewGroupId;
+    u32 CurrentGroupId;
+	core::array<ProfileData> ProfileDatas;
+    core::array<ProfileData> ProfileGroups;
+};
+
+IRRLICHT_API Profiler* IRRCALLCONV getProfiler();
+extern Profiler gPROFILER;
+
+
+// inline implementation
+void Profiler::add(u32 id, u32 groupId, const core::stringw &name)
+{
+	ProfileData data;
+	data.Id = id;
+    data.GroupId = groupId;
+    data.Name = name;
+
+	s32 idx = ProfileDatas.binary_search(data);
+	if ( idx < 0 )
+	{
+		ProfileDatas.push_back(data);
+		ProfileDatas.sort();
+	}
+	else
+	{
+		ProfileDatas[idx] = data;
+	}
+}
+
+void Profiler::addGroup(u32 groupId, const core::stringw &name)
+{
+    ProfileData group;
+	group.Id = groupId;
+	group.GroupId = OverviewGroupId;
+    group.Name = name;
+
+	s32 idx = ProfileGroups.binary_search(group);
+	if ( idx < 0 )
+	{
+		ProfileGroups.push_back(group);
+		ProfileGroups.sort();
+	}
+	else
+	{
+		ProfileGroups[idx] = group;
+	}
+}
+
+void Profiler::start(u32 id)
+{
+	s32 idx = ProfileDatas.binary_search(ProfileData(id));
+	if ( idx >= 0 && IrrTimer )
+	{
+		ProfileDatas[idx].LastTimeStarted = IrrTimer->getRealTime();
+	}
+}
+
+void Profiler::stop(u32 id)
+{
+	s32 idx = ProfileDatas.binary_search(ProfileData(id));
+	if ( idx >= 0 && IrrTimer )
+	{
+		ProfileData &data = ProfileDatas[idx];
+		u32 diffTime = IrrTimer->getRealTime() - data.LastTimeStarted;
+		if ( data.LastTimeStarted == 0 )
+			return;
+
+		++data.CountCalls;
+		data.TimeSum += diffTime;
+		if ( diffTime > data.HighestTime )
+			data.HighestTime = diffTime;
+		if ( diffTime < data.LowestTime )
+			data.LowestTime = diffTime;
+		data.LastTimeStarted = 0;
+
+
+		s32 idxGroup = ProfileGroups.binary_search(ProfileData(data.GroupId));
+		if ( idxGroup >= 0 )
+		{
+			ProfileData & group = ProfileGroups[idxGroup];
+			++group.CountCalls;
+			group.TimeSum += diffTime;
+			if ( diffTime > group.HighestTime )
+				group.HighestTime = diffTime;
+			if ( diffTime < group.LowestTime )
+				group.LowestTime = diffTime;
+			group.LastTimeStarted = 0;
+		}
+	}
+}
+
+void Profiler::reset(u32 id)
+{
+	s32 idx = ProfileDatas.binary_search(ProfileData(id));
+    if ( idx >= 0 )
+    {
+		ProfileData &data = ProfileDatas[idx];
+
+		s32 idxGroup = ProfileGroups.binary_search(ProfileData(data.GroupId));
+		if ( idxGroup >= 0 )
+		{
+			ProfileData & group = ProfileGroups[idxGroup];
+            group.CountCalls -= data.CountCalls;
+            group.TimeSum -= data.TimeSum;
+        }
+
+        data.reset();
+    }
+}
+
+void Profiler::resetGroup(u32 groupId)
+{
+    for ( u32 i=0; i<ProfileDatas.size(); ++i )
+    {
+        if ( ProfileDatas[i].GroupId == groupId )
+        {
+            reset(ProfileDatas[i].Id);
+        }
+    }
+}
+
+void Profiler::resetAll()
+{
+	for ( u32 i=0; i<ProfileDatas.size(); ++i )
+    {
+		ProfileDatas[i].reset();
+    }
+
+	for ( u32 i=0; i<ProfileGroups.size(); ++i )
+    {
+		ProfileGroups[i].reset();
+    }
+}
+
+void Profiler::show(irr::gui::IGUIEnvironment* env_)
+{
+    if ( !env_)
+        return;
+
+    hide(env_);
+
+	// I had no table yet when programming this. Would probably be nicer.
+	gui::IGUIListBox* listBox = env_->addListBox(DisplayRect, 0, GuiID, true);
+
+    core::stringw wstrTitle(makeTitleString());
+    listBox->addItem(wstrTitle.c_str());
+
+	s32 idxGroup = ProfileGroups.binary_search(ProfileData(CurrentGroupId));
+    if ( idxGroup < 0 )
+        return;
+
+    core::stringw wstrGroup(makeDataString(ProfileGroups[idxGroup]));
+    listBox->addItem(wstrGroup.c_str());
+
+	// show overview over groups?
+    if ( CurrentGroupId == OverviewGroupId )
+    {
+		for ( u32 i=0; i<ProfileGroups.size(); ++i )
+        {
+			if ( ProfileGroups[i].GroupId == OverviewGroupId )
+            {
+                core::stringw wstrData(makeDataString(ProfileGroups[i]));
+                listBox->addItem(wstrData.c_str());
+            }
+        }
+    }
+	// show data for current group
+    else
+    {
+		for ( u32 i=0; i<ProfileDatas.size(); ++i )
+        {
+            if ( ProfileDatas[i].GroupId == CurrentGroupId )
+            {
+                core::stringw wstrData(makeDataString(ProfileDatas[i]));
+                listBox->addItem(wstrData.c_str());
+            }
+        }
+    }
+}
+
+void Profiler::hide(irr::gui::IGUIEnvironment* env_)
+{
+    if ( !env_)
+        return;
+
+	gui::IGUIElement* root = env_->getRootGUIElement();
+	gui::IGUIElement* e = root->getElementFromId(GuiID, true);
+	if (e)
+	{
+        e->remove();
+	}
+}
+
+void Profiler::setDisplayGroup(u32 groupId)
+{
+    CurrentGroupId = groupId;
+}
+
+void Profiler::nextDisplayGroup()
+{
+	s32 idxGroup = ProfileGroups.binary_search(ProfileData(CurrentGroupId));
+    if ( idxGroup < 0 )
+    {
+        CurrentGroupId = 0;
+    }
+    else
+    {
+        ++idxGroup;
+		idxGroup %= ProfileGroups.size();
+        CurrentGroupId  = ProfileGroups[idxGroup].Id;
+    }
+}
+
+void Profiler::previousDisplayGroup()
+{
+	s32 idxGroup = ProfileGroups.binary_search(ProfileData(CurrentGroupId));
+	if ( idxGroup == 0 )
+    {
+		idxGroup = ProfileGroups.size()-1;
+	}
+	else
+	{
+		--idxGroup;
+	}
+	if ( idxGroup < 0 )
+    {
+        CurrentGroupId = 0;
+    }
+	else
+	{
+        CurrentGroupId  = ProfileGroups[idxGroup].Id;
+    }
+}
+
+void Profiler::firstDisplayGroup()
+{
+	if ( !ProfileGroups.size() )
+    {
+        CurrentGroupId = 0;
+    }
+    else
+    {
+        CurrentGroupId = ProfileGroups[0].Id;
+    }
+}
+
+// print current active group
+void Profiler::print(core::stringw &ostream, bool suppressUncalled)
+{
+    ostream += makeTitleString();
+    printGroup(ostream, CurrentGroupId, suppressUncalled);
+}
+
+void Profiler::printAll(core::stringw &ostream, bool includeOverview, bool suppressUncalled)
+{
+    ostream += makeTitleString();
+	for ( u32 i=0; i<ProfileGroups.size(); ++i )
+    {
+		if ( !includeOverview && ProfileGroups[i].Id == OverviewGroupId )
+			continue;
+        printGroup( ostream, ProfileGroups[i].Id, suppressUncalled );
+    }
+}
+
+void Profiler::printGroup(core::stringw &ostream, u32 groupId, bool suppressUncalled)
+{
+	s32 idxGroup = ProfileGroups.binary_search(ProfileData(groupId));
+    if ( idxGroup < 0 )
+        return;
+
+    ostream += makeDataString(ProfileGroups[idxGroup]);
+
+	// print overview for groups
+    if ( groupId == OverviewGroupId )
+    {
+		for ( u32 i=0; i<ProfileGroups.size(); ++i )
+        {
+            if ( (!suppressUncalled || ProfileGroups[i].CountCalls > 0)
+				&& ProfileGroups[i].GroupId == OverviewGroupId )
+            {
+                ostream += makeDataString(ProfileGroups[i]);
+            }
+        }
+    }
+	// print all data in a group
+    else
+    {
+		for ( u32 i=0; i<ProfileDatas.size(); ++i )
+        {
+            if ( (!suppressUncalled || ProfileDatas[i].CountCalls > 0)
+				&& ProfileDatas[i].GroupId == groupId )
+            {
+                ostream += makeDataString(ProfileDatas[i]);
+            }
+        }
+    }
+}
+
+core::stringw Profiler::makeTitleString()
+{
+	return core::stringw("name           calls       time(sum)   time(avg)   time(max)   time(min)   \n");
+}
+
+core::stringw Profiler::makeDataString(const ProfileData & data_)
+{
+	core::stringw ostr;
+
+    if ( data_.CountCalls > 0 )
+    {
+		// don't we all sometimes dream of stl-streaming in irrlicht?
+#ifdef _MSC_VER	    
+#pragma warning(disable:4996)	// 'sprintf' was declared deprecated
+#endif
+		char dummy[1023];
+		core::stringc name( data_.Name.c_str() );	// not a perfect conversion but don't wanna fight with finding platform independent wide-char printfs now
+		sprintf(dummy, "%-15.15s%-12u%-12u%-12u%-12u%-12u\n",
+			name.c_str(), data_.CountCalls, data_.TimeSum,
+            data_.TimeSum / data_.CountCalls, data_.HighestTime,
+            (data_.LowestTime <= data_.HighestTime ? data_.LowestTime : 0)
+			);
+		dummy[1022] = 0;
+		ostr += core::stringw(dummy);
+#ifdef _MSC_VER	    
+#pragma warning(default :4996)	// 'sprintf' was declared deprecated
+#endif
+	}
+    else
+    {
+        ostr += data_.Name;
+		ostr += L"\n";
+    }
+
+    return ostr;
+}
+
+} // namespace irr
+
+#if IRR_PROFILE
+	#define PROFILE_ADD(id_, groupId_, name_)   irr::getProfiler()->add(id_, groupId_, name_)
+    #define PROFILE_ADD_GROUP(groupId_, name_)  irr::getProfiler()->addGroup(groupId_, name_)
+    #define PROFILE_START(id_)                  irr::getProfiler()->start(id_)
+    #define PROFILE_STOP(id_)                   irr::getProfiler()->stop(id_)
+#else
+    #define PROFILE_ADD(id_, groupId_, name_)
+    #define PROFILE_ADD_GROUP(groupId_, name_)
+    #define PROFILE_START(id_)
+    #define PROFILE_STOP(id_)
+#endif // IRR_PROFILE
+
+#endif // __PROFILER_H_INCLUDED__
diff -r 7cab3d43a9b7 lib/irrlicht/source/Irrlicht/CIrrDeviceStub.cpp
--- a/lib/irrlicht/source/Irrlicht/CIrrDeviceStub.cpp	Tue Sep 02 00:54:04 2008 +0200
+++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceStub.cpp	Tue Sep 02 13:28:56 2008 +0200
@@ -12,6 +12,8 @@
 #include "CTimer.h"
 #include "CLogger.h"
 #include "irrString.h"
+#include "profiler.h"
+#include "profile_ids.h"
 
 namespace irr
 {
@@ -43,6 +45,14 @@
 	os::Printer::log(s.c_str(), ELL_INFORMATION);
 
 	checkVersion(params.SDK_version_do_not_use);
+	
+	// some default profile id's which can be used for quick profiles
+	PROFILE_ADD_GROUP(EPG_IRRLICHT, "Irrlicht");
+	PROFILE_ADD(EPD_TESTING1, EPG_IRRLICHT, "TESTING1");
+	PROFILE_ADD(EPD_TESTING2, EPG_IRRLICHT, "TESTING2");
+	PROFILE_ADD(EPD_TESTING3, EPG_IRRLICHT, "TESTING3");
+	PROFILE_ADD(EPD_TESTING4, EPG_IRRLICHT, "TESTING4");
+	PROFILE_ADD(EPD_TESTING5, EPG_IRRLICHT, "TESTING5");	
 }
 
 
diff -r 7cab3d43a9b7 lib/irrlicht/source/Irrlicht/Makefile
--- a/lib/irrlicht/source/Irrlicht/Makefile	Tue Sep 02 00:54:04 2008 +0200
+++ b/lib/irrlicht/source/Irrlicht/Makefile	Tue Sep 02 13:28:56 2008 +0200
@@ -34,7 +34,7 @@
 IRRVIDEOOBJ = CVideoModeList.o CFPSCounter.o $(IRRDRVROBJ) $(IRRIMAGEOBJ)
 IRRSWRENDEROBJ = CSoftwareDriver.o CSoftwareTexture.o CTRFlat.o CTRFlatWire.o CTRGouraud.o CTRGouraudWire.o CTRTextureFlat.o CTRTextureFlatWire.o CTRTextureGouraud.o CTRTextureGouraudAdd.o CTRTextureGouraudNoZ.o CTRTextureGouraudWire.o CZBuffer.o CTRTextureGouraudVertexAlpha2.o CTRTextureGouraudNoZ2.o CTRTextureLightMap2_M2.o CTRTextureLightMap2_M4.o CTRTextureLightMap2_M1.o CSoftwareDriver2.o CSoftwareTexture2.o CTRTextureGouraud2.o CTRGouraud2.o CTRGouraudAlpha2.o CTRGouraudAlphaNoZ2.o CTRTextureDetailMap2.o CTRTextureGouraudAdd2.o CTRTextureGouraudAddNoZ2.o CTRTextureWire2.o CTRTextureLightMap2_Add.o CTRTextureLightMapGouraud2_M4.o IBurningShader.o CTRTextureBlend.o CTRTextureGouraudAlpha.o CTRTextureGouraudAlphaNoZ.o CDepthBuffer.o CBurningShader_Raster_Reference.o
 IRRIOOBJ = CFileList.o CFileSystem.o CLimitReadFile.o CMemoryReadFile.o CReadFile.o CWriteFile.o CXMLReader.o CXMLWriter.o CZipReader.o CPakReader.o irrXML.o CAttributes.o
-IRROTHEROBJ = CIrrDeviceSDL.o CIrrDeviceLinux.o CIrrDeviceStub.o CIrrDeviceWin32.o CLogger.o COSOperator.o Irrlicht.o os.o
+IRROTHEROBJ = CIrrDeviceSDL.o CIrrDeviceLinux.o CIrrDeviceStub.o CIrrDeviceWin32.o CLogger.o COSOperator.o Irrlicht.o os.o profiler.o
 IRRGUIOBJ = CGUIButton.o CGUICheckBox.o CGUIComboBox.o CGUIContextMenu.o CGUIEditBox.o CGUIEnvironment.o CGUIFileOpenDialog.o CGUIFont.o CGUIImage.o CGUIInOutFader.o CGUIListBox.o CGUIMenu.o CGUIMeshViewer.o CGUIMessageBox.o CGUIModalScreen.o CGUIScrollBar.o CGUISpinBox.o CGUISkin.o CGUIStaticText.o CGUITabControl.o CGUITable.o CGUIToolBar.o CGUIWindow.o CGUIColorSelectDialog.o CDefaultGUIElementFactory.o CGUISpriteBank.o
 ZLIBOBJ = zlib/adler32.o zlib/compress.o zlib/crc32.o zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o zlib/uncompr.o zlib/zutil.o
 JPEGLIBOBJ = jpeglib/jcapimin.o jpeglib/jcapistd.o jpeglib/jccoefct.o jpeglib/jccolor.o jpeglib/jcdctmgr.o jpeglib/jchuff.o jpeglib/jcinit.o jpeglib/jcmainct.o jpeglib/jcmarker.o jpeglib/jcmaster.o jpeglib/jcomapi.o jpeglib/jcparam.o jpeglib/jcphuff.o jpeglib/jcprepct.o jpeglib/jcsample.o jpeglib/jctrans.o jpeglib/jdapimin.o jpeglib/jdapistd.o jpeglib/jdatadst.o jpeglib/jdatasrc.o jpeglib/jdcoefct.o jpeglib/jdcolor.o jpeglib/jddctmgr.o jpeglib/jdhuff.o jpeglib/jdinput.o jpeglib/jdmainct.o jpeglib/jdmarker.o jpeglib/jdmaster.o jpeglib/jdmerge.o jpeglib/jdphuff.o jpeglib/jdpostct.o jpeglib/jdsample.o jpeglib/jdtrans.o jpeglib/jerror.o jpeglib/jfdctflt.o jpeglib/jfdctfst.o jpeglib/jfdctint.o jpeglib/jidctflt.o jpeglib/jidctfst.o jpeglib/jidctint.o jpeglib/jidctred.o jpeglib/jmemmgr.o jpeglib/jmemnobs.o jpeglib/jquant1.o jpeglib/jquant2.o jpeglib/jutils.o
diff -r 7cab3d43a9b7 lib/irrlicht/source/Irrlicht/profile_ids.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irrlicht/source/Irrlicht/profile_ids.h	Tue Sep 02 13:28:56 2008 +0200
@@ -0,0 +1,22 @@
+#ifndef __IRR_PROFILE_IDS_H_INCLUDED__
+#define __IRR_PROFILE_IDS_H_INCLUDED__
+
+enum EPROFILE_GROUP
+{
+	//! general group for irrlicht profiling
+	EPG_IRRLICHT = 1,
+};
+
+enum EPROFILE_DATA
+{
+	//! Testing are just thought for those moments when you just need some 
+	//! profiling which you will remove again after you're finished profiling.
+	//! They are addded in CIrrDeviceStub right after creating a device
+	EPD_TESTING1 = 1,
+	EPD_TESTING2,
+	EPD_TESTING3,
+	EPD_TESTING4,
+	EPD_TESTING5,
+};
+
+#endif // #define __IRR_PROFILE_IDS_H_INCLUDED__
diff -r 7cab3d43a9b7 lib/irrlicht/source/Irrlicht/profiler.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irrlicht/source/Irrlicht/profiler.cpp	Tue Sep 02 13:28:56 2008 +0200
@@ -0,0 +1,13 @@
+#include "profiler.h"
+
+namespace irr
+{
+
+Profiler gPROFILER;
+
+IRRLICHT_API Profiler* IRRCALLCONV getProfiler()
+{
+    return &gPROFILER;
+}
+
+} // namespace irr
